if a 500 error occurs then the output is nested with the specified template at the position where this error occurs. this leads to the entire layout no longer being correct.
i want a 500 error to be mapped (like a 404) within the default layout. the cakephp docs don’t give me any hint if this is possible at all.
config/app.php
'Error' => [
'exceptionRenderer' => App\Error\AppExceptionRenderer::class,
'errorLevel' => E_ALL & ~E_USER_DEPRECATED,
'log' => true,
'trace' => true,
'skipLog' => [
'Cake\Http\Exception\NotFoundException',
'Cake\Http\Exception\UnauthorizedException',
],
],
Application.php
public function middleware($middlewareQueue): MiddlewareQueue
{
$middlewareQueue
->add(new ErrorHandlerMiddleware(null, Configure::read('Error')))
->add(new AssetMiddleware([
'cacheTime' => Configure::read('Asset.cacheTime'),
]))
->add(new RoutingMiddleware($this, '_cake_routes_'));
return $middlewareQueue;
}
Error/AppExceptionRenderer.php
class AppExceptionRenderer extends ExceptionRenderer
{
/**
* @return \Psr\Http\Message\ResponseInterface
*/
public function render(): ResponseInterface
{
$this->_findHighlights();
return parent::render();
}
/**
* @return void
*/
protected function _findHighlights()
{
$Products = TableRegistry::getTableLocator()->get('Products');
$mostPopularProducts = $Products->find('forHighlights')->find('mostPopular');
$newestProducts = $Products->find('forHighlights')->find('newestWeddingOrPartnerRings');
$this->controller->set('mostPopularProducts', $mostPopularProducts);
$this->controller->set('newestProducts', $newestProducts);
}
}
Controller/ErrorController.php
public function beforeRender(Event $event)
{
parent::beforeRender($event);
$this->viewBuilder()->setHelpers(['Captcha.Captcha']);
$this->viewBuilder()->setTemplatePath('Error');
}
Template/Error/error500.ctp
use Cake\Core\Configure;
use Cake\Error\Debugger;
$this->layout = 'default';
if (Configure::read('debug')):
$this->layout = 'dev_error';
$this->assign('title', $message);
$this->assign('templateName', 'error500.ctp');
$this->start('file'); ?>
<?php if (!empty($error->queryString)): ?>
<p class="notice">
<strong>SQL Query: </strong>
<?= h($error->queryString) ?>
</p>
<?php endif; ?>
<?php if (!empty($error->params)): ?>
<strong>SQL Query Params: </strong>
<?php Debugger::dump($error->params) ?>
<?php endif; ?>
<?php if ($error instanceof Error): ?>
<strong>Error in: </strong>
<?= sprintf('%s, line %s', str_replace(ROOT, 'ROOT', $error->getFile()), $error->getLine()) ?>
<?php endif; ?>
<?php echo $this->element('auto_table_warning');
if (extension_loaded('xdebug')) :
xdebug_print_function_stack();
endif;
$this->end();
endif; ?>
<h2><?= __d('cake', 'An Internal Error Has Occurred') ?></h2>
ProductsController.php
public function view()
{
$id = $this->_retrieveProductId();
if (!$id) {
throw new NotFoundException();
}
$product = $this->Products->get($id, [
'finder' => 'withFullInfo',
]);
if (empty($product)) {
throw new NotFoundException();
} elseif ($product->status != 1) {
$breadCrumbs = $product->getBreadCrumb();
return $this->redirect($this->_getCategoryUrl($breadCrumbs));
} elseif (!$this->_validateCurrentUrl($product)) {
return $this->redirect($product->makeProductUrl(), 301);
}
if ($this->Products->exists(['variant_id' => $product->variant_id])) {
$variant = $this->Products->Variants->get($product->variant_id);
$variantsproducts = $this->Products->find('all', [
'contain' => [
'Categories',
'ProductImages',
'WomenWidths',
],
])->where([
'variant_id' => $product->variant_id,
'status' => 1,
])->order(['WomenWidths.width' => 'ASC']);
$this->set(compact('variant', 'variantsproducts'));
}
$this->set(compact(
'product',
'cartItem',
'cartId',
'eventID',
));
}