Страница 1 из 2
Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.26, 22:11
slo_nik
Вечер добрый.
Есть задача показывать разные шаблоны страницы ошибок для разных контролеров.
Знаю, что можно переопределить в конфигурационном файле, можно через init() контроелера.
Но вот тут я не могу сообразить как правильно сделать.
Структура проекта следующая(yii2-basic).
Код: Выделить всё
controllers
admin
users
UsersController
countries
CountriesController
AdminController
DefaultController
SiteController
views
admin
users
countries
default
error.php
index.php
site
index.php
error.php
В контролере AdminController через AccessControl закрыл доступ к остальным контролерам админки и пытаюсь переопределить errorAction. Остальные контролеры наследуют AdminController
Код: Выделить всё
<?php
class AdminController extends Controller
{
public function init()
{
parent::init();
$this->layout = 'admin/main.php';
Yii::$app->view->getAssetManager()->bundles = [];
Yii::$app->errorHandler->errorAction = 'admin/default/error';
Yii::$app->user->loginUrl = ['/admin/login'];
Yii::$app->errorHandler->errorView = '@app/views/admin/default/error';
}
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
// 'view' => '@app/views/admin/default/error'
]
];
}
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'except' => ['login'],
'rules' => [
[
'allow' => true,
'roles' => ['@']
]
]
]
];
}
}
Получается, что я не использую модули для админки, просто выделил файлы админики в директорию admin.
Проблема в следующем.
Я перехожу в админку по
localhost/admin.
Если я намеренно делаю ошибку в адресе, например,
localhost/admin/use2rs, то меня перекидывает на
site/error, вроде бы всё правильно, страницы
use2rs у меня не существует. Если делаю ошибку, вызов несуществующей записи
localhost/admin/user/view/09, то меня перекидывает туда, куда я хочу - на
admin/error.
Как сделать так, чтобы при переходе на несуществующую страницу в админе перекидывало не на
site/error, а на
admin/error?
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.27, 01:19
slo_nik
Задачу решил пока таким способом.
Код: Выделить всё
<?php
namespace app\components;
class ErrorHandler extends \yii\web\ErrorHandler
{
public $actionsForPrefix;
public function __construct($config = [])
{
parent::__construct($config);
foreach ($this->actionsForPrefix as $prefix => $action) {
if (strpos($_SERVER['REQUEST_URI'], $prefix) !== false) {
$this->errorAction = $action;
}
}
}
}
В конфигурационном файле
Код: Выделить всё
'errorHandler' => [
'class' => ErrorHandler::class,
'actionsForPrefix' => [
'/' => 'site/error',
'admin' => 'admin/default/error',
]
],
Если есть более изящное решение буду рад помощи.
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.27, 18:54
yiiliveext
Правила просто правильно пропишите
Код: Выделить всё
'admin/<controller:\w+>/<action:\w+>' => 'admin/<controller>/<action>',
'admin/<action:\w+>' => 'admin/default/<action>',
'admin' => 'admin/default/index',
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.27, 21:36
slo_nik
yiiliveext писал(а): ↑2019.09.27, 18:54
Правила просто правильно пропишите
Код: Выделить всё
'admin/<controller:\w+>/<action:\w+>' => 'admin/<controller>/<action>',
'admin/<action:\w+>' => 'admin/default/<action>',
'admin' => 'admin/default/index',
Это не поможет. Я перепробовал много вариантов правил.
Если попытаться переопределить страницу ошибки в контролере, то до него ход не дойдёт, будет сгенерирован errorHandler по умолчанию, со страницей "site/error".
Админ не модуль, а обычный контролер, такой же как и SiteController.
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.27, 23:11
yiiliveext
slo_nik писал(а): ↑2019.09.27, 21:36
Админ не модуль, а обычный контролер, такой же как и SiteController.
Я это понимаю. Только что сэмулировал вашу структуру проекта. Все работает.
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 18:55
slo_nik
yiiliveext писал(а): ↑2019.09.27, 23:11
slo_nik писал(а): ↑2019.09.27, 21:36
Админ не модуль, а обычный контролер, такой же как и SiteController.
Я это понимаю. Только что сэмулировал вашу структуру проекта. Все работает.
У меня не захотело работать.
Прописал Ваш пример правил, оставил только их, но при переходе на
localhost/admin/use2r открылась страница ошибки
site/error.
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 19:13
yiiliveext
slo_nik писал(а): ↑2019.09.28, 18:55
У меня не захотело работать.
Прописал Ваш пример правил, оставил только их, но при переходе на
localhost/admin/use2r открылась страница ошибки
site/error.
При переходе по этому адресу сработает правило 'admin/<action:\w+>' => 'admin/default/<action>',
Соответственно будет создан DefaultController. Вам нужно указать желаемый errorAction в методе init этого контроллера.
Код: Выделить всё
public function init()
{
parent::init();
\Yii::$app->errorHandler->errorAction = 'admin/default/error';
}
Если используете стандартный errorAction в этом контроллере, то еще указываете view, если оно отличается от стандартного views/admin/default/error.php
Код: Выделить всё
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
'view' => '@app/views/admin/default/error2'
],
];
}
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 20:53
slo_nik
В том-то и дело, что user это не действие контролера, а отдельный котролер.
DefaultController и все остальные контролеры в админке наследуются от одного,
AdminController, в котором я как раз и переопределяю в
init() страницу для ошибок, так же там я подключаю
ErrorHandler, всё так, как Вы показали в своих примерах.
Но это не работает.
Заработало так, как мне надо после того, как я переопределил
ErrorHandler.
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:05
yiiliveext
Если у меня работает, то должно и у вас работать. Логично?
Покажите конфиг web.php
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:09
slo_nik
Вот сейчас, подключил Все Ваши примеры.
В AdminController
Код: Выделить всё
public function init()
{
parent::init();
$this->layout = 'admin/main.php';
Yii::$app->view->getAssetManager()->bundles = [];
Yii::$app->errorHandler->errorAction = '/admin/default/error';
Yii::$app->user->loginUrl = ['/admin/login'];
}
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
'view' => '@app/views/admin/default/error'
]
];
}
В urlManager удалил все правила, оставил только Ваши.
Код: Выделить всё
'admin/<controller:\w+>/<action:\w+>' => 'admin/<controller>/<action>',
'admin/<action:\w+>' => 'admin/default/<action>',
'admin' => 'admin/default/index'
В config/web.php вернул стандартный ErrorHandler.
Перехожу на разные адреса
Код: Выделить всё
localhost/admin/globe/cou???ntries ---> site/error
Возвращаю переопределённый ErrorHandler, правила urlManager оставляю Ваши
Перехожу на разные адреса
Код: Выделить всё
localhost/admin/globe/cou???ntries ---> admin/default/error
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:09
slo_nik
yiiliveext писал(а): ↑2019.09.28, 21:05
Покажите конфиг web.php
Весь или какую-то определённую часть?
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:13
yiiliveext
slo_nik писал(а): ↑2019.09.28, 21:09
yiiliveext писал(а): ↑2019.09.28, 21:05
Покажите конфиг web.php
Весь или какую-то определённую часть?
Если не слишком большой, то весь. А так ErrorHadler и ControllerMap
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:15
slo_nik
yiiliveext писал(а): ↑2019.09.28, 21:13
slo_nik писал(а): ↑2019.09.28, 21:09
yiiliveext писал(а): ↑2019.09.28, 21:05
Покажите конфиг web.php
Весь или какую-то определённую часть?
Если не слишком большой, то весь. А так ErrorHadler и ControllerMap
Код: Выделить всё
params = require __DIR__ . '/params.php';
$urlRules = require __DIR__ . '/urlRules.php';
$db = ArrayHelper::merge(require __DIR__ . '/db.php', require __DIR__ . '/db-local.php');
Yii::setAlias('@tests', dirname(__DIR__) . '/tests');
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__) . '/src',
'runtimePath' => dirname(__DIR__) . '/runtime',
'vendorPath' => dirname(__DIR__) . '/vendor',
'language' => 'ru-RU',
'bootstrap' => ['log', SetUp::class],
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
'on beforeAction' => function($event) use ($params) {
if(!Yii::$app->user->can('admin')){
if(in_array($event->action->id, $params['no_section']))
{
return Yii::$app->response->redirect(['site/no-section']);
}
}
return false;
},
'components' => [
'authManager' => [
'class' => AuthManager::class,
],
'user' => [
'identityClass' => Identity::class,
'enableAutoLogin' => true,
'loginUrl' => ['user/login']
],
'errorHandler' => [
'class' => ErrorHandler::class,
'actionsForPrefix' => [
'/' => 'site/error',
'admin' => 'admin/default/error',
]
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'useFileTransport' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => $db,
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'rules' => $urlRules
],
'assetManager' => [
'bundles' => [
'yii\bootstrap\BootstrapAsset' => [
'css' => []
],
'yii\bootstrap\BootstrapPluginAsset' => [
'js' => []
]
]
],
'view' => [
'theme' => [
'basePath' => '@app/themes/custom',
'baseUrl' => '@web/themes/custom',
'pathMap' => [
'@app/views' => '@app/themes/custom',
//'@app/modules' => '@app/themes/custom/modules'
]
]
],
'siteSettings' => [
'class' => SiteSettings::class
],
'i18n' => [
'translations' => [
'*' => [
'class' => 'yii\i18n\PhpMessageSource',
'forceTranslation' => true,
'basePath' => '@app/messages'
],
],
],
],
'modules' => [
'gridview' => [
'class' => '\kartik\grid\Module'
]
],
'params' => $params,
];
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:26
yiiliveext
localhost/admin/ ---> site/error - не срабатывает из-за слеша в конце, используйте нормалайзер в менеджере правил или попробуйте без слеша
localhost/admin/globe/cou???ntries ---> site/error - так будет, если нет контроллера globe
Что с роутом localhost/admin/use2r ?
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:33
slo_nik
Я ещё запускал debug в PhpStorm, пытался пройти пошагово и посмотреть что и как.
Код возвращал ошибку 404 и представление
site/error сразу после прохода строки в web/index.php
Получается, что до контролеров ход не доходил.
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:34
slo_nik
yiiliveext писал(а): ↑2019.09.28, 21:26
Что с роутом localhost/admin/use2r ?
Всё тоже самое - не работает, перекидывает на site/error
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:41
slo_nik
yiiliveext писал(а): ↑2019.09.28, 21:26
Что с роутом localhost/admin/use2r ?
Ошибка вышла, этот вариант работает, но не работает localhost/admin/user )))
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:44
slo_nik
yiiliveext писал(а): ↑2019.09.28, 21:26
localhost/admin/globe/cou???ntries ---> site/error - так будет, если нет контроллера globe
Да, контролера globe нет, это просто директория.
Я пытался задать это условие в urlManager через такие правила
Код: Выделить всё
[
'class' => GroupUrlRule::class,
'prefix' => 'admin',
'routePrefix' => 'admin',
'rules' => [
'' => 'default/index',
'<_a:(login|logout)>' => 'default/<_a>',
'<_c:[-\w]+>' => '<_c>/index',
'<_c:[-\w]+>/<id:\d+>' => '<_c>/view',
'<_c:[-\w]+>/<_a:[-\w]+>' => '<_c>/<_a>',
'<_c:[-\w]+>/<_a:[-\w]+>/<id:\d+>' => '<_c>/<_a>',
'<_url:\w+>/<_c:[-\w]+>/<_a:[-\w]+>/<id:\d+>' => '<_url>/<_c>/<_a>',
'<_url:\w+>/<_c:[-\w]+>/<id:\d+>' => '<_url>/<_c>/view',
'<_url:\w+>/<_c:[-\w]+>/<_a:[-\w]+>' => '<_url>/<_c>/<_a>',
'<_url:\w+>/<_c:[-\w]+>' => '<_url>/<_c>/index',
]
],
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 21:49
yiiliveext
slo_nik писал(а): ↑2019.09.28, 21:33
Получается, что до контролеров ход не доходил.
Да, работать будет только если в роуте определился существующий контроллер при парсинге запроса
Re: Как сделать разные страницы ошибок для разных контролеров?
Добавлено: 2019.09.28, 22:15
yiiliveext
Как вариант, чтобы не подменять родной ErrorHandler, можете добавить в конфиг
Код: Выделить всё
'on beforeRequest' => function($event) {
$path = $event->sender->getRequest()->getPathInfo();
if (preg_match('#^admin(/.*)?$#i', $path)) {
\Yii::$app->errorHandler->errorAction = 'admin/default/error';
}
},