I have a few settings set up in the AppController
in the initialize
function:
// src/Controller/AppController.php
public function initialize(): void
{
parent::initialize();
$settings = \Cake\Core\Configure::read('Settings');
$nav = \Cake\Core\Configure::read('Navigation');
$debug = \Cake\Core\Configure::read('debug');
$this->set(compact('settings', 'nav', 'debug'));
}
Those variables are accessible from all other controllers/views. My problem is, when an error page is displayed (ErrorController.php
& templates/layout/error.php
), those three variables are not handed over and my layout is not displaying anything (because I need the $settings
and $nav
variables).
In my ErrorController.php
I set a standard initialize:
// src/Controller/ErrorController.php
public function initialize(): void
{
parent::initialize();
$this->viewBuilder()->setTemplatePath('Error');
}
When I add the same variables to the ErrorController/initialize
, the variables are not handed over, or only, when I remove the parent::initialize();
.
What am I missing?
Does ErrorController actually extend AppController?
Yes it does.
Here is the full controller:
namespace App\Controller;
use Cake\Event\EventInterface;
use App\Controller\AppController;
/**
* Error Handling Controller
*
* Controller used by ExceptionRenderer to render error responses.
*/
class ErrorController extends AppController
{
public function initialize(): void
{
parent::initialize();
$this->viewBuilder()->setTemplatePath('Error');
}
}
I can’t replicate your problem in v4. What version are you using?
Personally, to debug this I would start by checking the existence of the vars are a couple of points and see where the failure is happening…
// src/Controller/AppController.php
public function initialize(): void
{
parent::initialize();
$settings = \Cake\Core\Configure::read('Settings');
$nav = \Cake\Core\Configure::read('Navigation');
$debug = \Cake\Core\Configure::read('debug');
$this->set(compact('settings', 'nav', 'debug'));
debug($this->viewBuilder()->getVars());
}
then
// src/Controller/ErrorController.php
public function initialize(): void
{
parent::initialize();
debug($this->viewBuilder()->getVars());
$this->viewBuilder()->setTemplatePath('Error');
debug($this->viewBuilder()->getVars());
}
This would tell
- if AppController was getting called and properly setting the values
- if the values were surviving back in the controller
- if the template path call was destroying them somehow.
Okay, found the issue.
I didn’t post following part of my initialize
function:
if($this->Authentication->getResult()->isValid()) {
$authUser = $this->Authentication->getIdentity()->getOriginalData();
// fetch notifications & messages
$notificationsBar = $this->Notification->fetch($authUser->id);
$messagesBar = $this->Message->fetch($authUser->id);
$this->set(compact('authUser', 'notificationsBar', 'messagesBar'));
}
The if($this->Authentication->getResult()->isValid())
fails in AppController
when ErrorController
is called. But how to fix this?
Why isn’t $this->Authentication
not valid (and getting no logs), when ErrorController
is called?
Edit
In AppController:initialize()
doing following:
debug($this->viewBuilder()->getVars()); // returns output
debug($this->Authentication); // no output
Weird…
is AppController extending Controller? Probably, but still have to ask
Just so there is no misunterstanding…
Here is my full AppController.php
. I just removed the /***/
doc comments.
<?php
declare(strict_types=1);
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\Event;
use Cake\Datasource\ConnectionManager;
use Cake\Core\Configure;
class AppController extends Controller
{
public function initialize(): void
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Toast');
$this->loadComponent('Notification');
$this->loadComponent('Message');
$this->loadComponent('Authentication.Authentication', [
'logoutRedirect' => '/users/login'
]);
// $this->viewBuilder()->setHelpers(['AssetCompress.AssetCompress']);
// load settings, navigation and debug state
$settings = \Cake\Core\Configure::read('Settings');
$nav = \Cake\Core\Configure::read('Navigation');
$debug = \Cake\Core\Configure::read('debug');
$this->set(compact('settings', 'nav', 'debug'));
// debug($this->viewBuilder()->getVars());
debug($this->Authentication);
// authenticated user
if($this->Authentication->getResult()->isValid()) {
$authUser = $this->Authentication->getIdentity()->getOriginalData();
// fetch notifications & messages
$notificationsBar = $this->Notification->fetch($authUser->id);
$messagesBar = $this->Message->fetch($authUser->id);
$this->set(compact('authUser', 'notificationsBar', 'messagesBar'));
}
}
/**
* beforeFilter method
* @param \Cake\Event\EventInterface $event
* @return \Cake\Http\Response|null
*/
public function beforeFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);
$this->Authentication->addUnauthenticatedActions(['login', 'register', 'logout', 'activate', 'forgot']);
}
}
And here the full ErrorController.php
<?php
declare(strict_types=1);
namespace App\Controller;
use Cake\Event\EventInterface;
use App\Controller\AppController;
class ErrorController extends AppController
{
public function initialize(): void
{
parent::initialize();
$this->viewBuilder()->setTemplatePath('Error');
}
public function beforeRender(\Cake\Event\EventInterface $event)
{
parent::beforeRender($event);
}
public function beforeFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);
}
public function afterFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);
}
}
It must be that the user is not being authenticated in that case.
You can see some of what is happening with authentication if, just before your conditional statement in AppController you take a peak at the data in the Authentication object:
debug($this->Authentication->getResult()->getData());
if($this->Authentication->getResult()->isValid()) {
// your code
}
Probably, for your successful pages you will see an entity for your logged in user. And it seems like you are going to see NULL for your ErrorController.
If so, this will confirm that your user is not being authenticated in the ErrorController case.
I don’t know how you have authentication configured, but probably you have a login page, then you rely on the Session to carry the proof of login. Is there something leading up to the ErrorController that could be killing your session?