How to return 404 status if an item is not found?
Forum rules
Always add your Aimeos and PHP version as well as your environment (Linux/Mac/Win)
Spam and unrelated posts will be removed immediately!
Always add your Aimeos and PHP version as well as your environment (Linux/Mac/Win)
Spam and unrelated posts will be removed immediately!
-
- Posts: 27
- Joined: 04 Jun 2020, 14:00
How to return 404 status if an item is not found?
Hi, seems that right now exists no mechanic to return 404 properly for SEO need. For example, if product, page, custom cms post domain is not found by URL I want to return 404 status. But it is hard, because, aimeos has a block structure with exceptions on each level.
I didn`t find a better solution as roughly and dirty iterate view of each page component in each controller method
and iterate each ErrorList
It of course has broken with translation in 2021.07.
Maybe, you have an idea how to do it in a proper way? I should be grateful for a reply.
I didn`t find a better solution as roughly and dirty iterate view of each page component in each controller method
Code: Select all
if ( $this->is404( Shop::get( $component )->getView() ) ) return abort(404);
Code: Select all
private function is404( $view ) {
$name = last(explode('/', $view->get('component')));
$regex = [
'/^Unable to find (product|post|page|supplier)/',
'/^No item found/'
];
$messages = $view->get("${name}ErrorList", []);
foreach( $regex as $pattern ) {
$matches = preg_grep($pattern, $messages);
if ( $matches ) return true;
}
return false;
}
Code: Select all
$msg = $this->getContext()->getI18n()->dt( 'controller/frontend', 'Unable to find product "%1$s"' );
Maybe, you have an idea how to do it in a proper way? I should be grateful for a reply.
Re: How to return 404 status if an item is not found?
That's difficult indeed. A better way would be if the Aimeos HTML components would throw an exception with a status 404 in that case which could be handled in the controller actions properly.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, give us a star
If you like Aimeos, give us a star
-
- Posts: 27
- Joined: 04 Jun 2020, 14:00
Re: How to return 404 status if an item is not found?
Are you planning to provide this feature in the next releases?
-
- Posts: 27
- Joined: 04 Jun 2020, 14:00
Re: How to return 404 status if an item is not found?
What about add code to Exceptions?
For example,
app/vendor/aimeos/aimeos-core/lib/mshoplib/src/MShop/Common/Manager/Base.php
il-grapejs is a fork of ai-cms-grapejs (is just for example of concept)
app/ext/il-grapesjs/client/html/src/Client/Html/Cms/Page/Standard.php
Or for example,
app/vendor/aimeos/ai-controller-frontend/controller/frontend/src/Controller/Frontend/Product/Standard.php
app/vendor/aimeos/ai-client-html/client/html/src/Client/Html/Catalog/Detail/Standard.php
By code from Exception client/html can understand how to return, with $view->ErrorList message or with something to Controller or anyway else. And you can add it only to specific client/html
I don`t want to create self solution because it will break with updates. We can do it together via pull request
For example,
app/vendor/aimeos/aimeos-core/lib/mshoplib/src/MShop/Common/Manager/Base.php
Code: Select all
$msg = $this->getContext()->i18n()->dt( 'mshop', 'No item found for conditions: %1$s' );
throw new \Aimeos\MShop\Exception( sprintf( $msg, print_r( $pairs, true ) ), 404 );
app/ext/il-grapesjs/client/html/src/Client/Html/Cms/Page/Standard.php
Code: Select all
catch( \Aimeos\MShop\Exception $e ) {
if ( $e->getCode() == 404 ) abort(404);
$tplconf = 'client/html/cms/page/template-error';
$error = array( $context->getI18n()->dt( 'mshop', $e->getMessage() ) );
$view->pageErrorList = array_merge( $view->get( 'pageErrorList', [] ), $error );
}
app/vendor/aimeos/ai-controller-frontend/controller/frontend/src/Controller/Frontend/Product/Standard.php
Code: Select all
$msg = $this->getContext()->getI18n()->dt( 'controller/frontend', 'Unable to find product "%1$s"' );
throw new \Aimeos\Controller\Frontend\Product\Exception( sprintf( $msg, $name ), 404 );
Code: Select all
catch( \Aimeos\Controller\Frontend\Exception $e ) {
if ( 404 == $e->getCode() ) abort(404);
$error = array( $context->getI18n()->dt( 'controller/frontend', $e->getMessage() ) );
$view->detailErrorList = array_merge( $view->get( 'detailErrorList', [] ), $error );
}
I don`t want to create self solution because it will break with updates. We can do it together via pull request
Re: How to return 404 status if an item is not found?
Yes, something similar would be the way to go. Instead of using Laravel specific "abort()" method, a custom "NotFound" exception should be thrown and caught by the Aimeos Laravel controller which can then call "abort(404)".
If you create a pull request, we will review and merge it into the core
If you create a pull request, we will review and merge it into the core
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, give us a star
If you like Aimeos, give us a star
-
- Posts: 27
- Joined: 04 Jun 2020, 14:00
Re: How to return 404 status if an item is not found?
Hi, please, check the conception, and I will make the pull request.
1. All controller frontends find/resolve methods need to check item null and have 404 code.
Example: app/vendor/aimeos/ai-controller-frontend/controller/frontend/src/Controller/Frontend/Product/Standard.php:347
2. Aimeos\Client\Html\NotFound Exception needs to be created.
3. Aimeos\Client\Html\Base needs to be extended by the throw method.
Example: app/vendor/aimeos/ai-client-html/client/html/src/Client/Html/Base.php
Which will be added to all client/html which can return 404 responses, for example:
app/vendor/aimeos/ai-client-html/client/html/src/Client/Html/Catalog/Product/Standard.php
It will be disabled by default, and those who want to enable it, will make config adjustments:
client/html/common/http/404/product => true
4. Then, the controller may catch it.
1. All controller frontends find/resolve methods need to check item null and have 404 code.
Example: app/vendor/aimeos/ai-controller-frontend/controller/frontend/src/Controller/Frontend/Product/Standard.php:347
Code: Select all
if( ( $item = $this->manager->search( $search, $this->domains )->first() ) === null )
{
$msg = $this->getContext()->getI18n()->dt( 'controller/frontend', 'Unable to find product "%1$s"' );
throw new \Aimeos\Controller\Frontend\Product\Exception( sprintf( $msg, $name ), 404 );
}
3. Aimeos\Client\Html\Base needs to be extended by the throw method.
Example: app/vendor/aimeos/ai-client-html/client/html/src/Client/Html/Base.php
Code: Select all
protected function throwHttpException( \Exception $e, $domain )
{
$code = $e->getCode();
$config = $this->getContext()->getConfig();
if ( $config->get("client/html/common/http/$code/$domain", false) )
throw $e;
}
app/vendor/aimeos/ai-client-html/client/html/src/Client/Html/Catalog/Product/Standard.php
Code: Select all
catch( \Aimeos\Controller\Frontend\Exception $e )
{
$this->throwHttpException(
new \Aimeos\Client\Html\NotFound( $e->getMessage(), $e->getCode() ), 'product'
);
$error = array( $context->getI18n()->dt( 'controller/frontend', $e->getMessage() ) );
$view->productErrorList = array_merge( $view->get( 'productErrorList', [] ), $error );
}
client/html/common/http/404/product => true
4. Then, the controller may catch it.
Re: How to return 404 status if an item is not found?
Just simplify that to:
Then, you can add the try/catch in the controller action.
Code: Select all
catch( \Aimeos\Controller\Frontend\Exception $e )
{
if( $e->getCode() === 404 ) { throw $e; }
$error = array( $context->getI18n()->dt( 'controller/frontend', $e->getMessage() ) );
$view->productErrorList = array_merge( $view->get( 'productErrorList', [] ), $error );
}
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, give us a star
If you like Aimeos, give us a star
-
- Posts: 27
- Joined: 04 Jun 2020, 14:00
Re: How to return 404 status if an item is not found?
Ok, I thought about those who don`t want to handle 404 and want to keep it as is.
Maybe for those is better change the order:
Those who want to keep $view->ErrorList just will add empty try/catch in the controller.
Maybe for those is better change the order:
Code: Select all
catch( \Aimeos\Controller\Frontend\Exception $e )
{
$error = array( $context->getI18n()->dt( 'controller/frontend', $e->getMessage() ) );
$view->productErrorList = array_merge( $view->get( 'productErrorList', [] ), $error );
if( $e->getCode() === 404 ) { throw $e; }
}
Re: How to return 404 status if an item is not found?
If you re-throw the exception, the error message is never displayed.
We would like to change the 404 handling in the upcoming 2021.10 LTS for all.
We would like to change the 404 handling in the upcoming 2021.10 LTS for all.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, give us a star
If you like Aimeos, give us a star
- PedroLópezAndradas
- Posts: 22
- Joined: 16 Jan 2023, 11:30
Re: How to return 404 status if an item is not found?
With 2022 package, when the url does not match a product, it throws an exception.
Finally, ¿did you set an option to return a 404 page instead a 500?
Thanks!
Finally, ¿did you set an option to return a 404 page instead a 500?
Thanks!