Question

I need to change all my product URLs and I would like to use a code snippet to use it. All I need is a simple code which is Magento 2 compatible and will change the URL for one product then saves it. I have this so far:

<?php
use \Magento\Framework\App\Bootstrap;
include('/var/www/html/app/bootstrap.php');

$bootstrap = Bootstrap::create(BP, $_SERVER);  
$obj = $bootstrap->getObjectManager();
$deploymentConfig = $obj->get('Magento\Framework\App\DeploymentConfig');

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

$productCollection = $objectManager->create('\Magento\Catalog\Model\Product');

$product = $objectManager->create('\Magento\Catalog\Model\Product')->load(2933);
$name = $product->getName();
print $name;
$url="new-product-url";
$product ->setUrlKey($url);
$objectManager->get('\Magento\Catalog\Model\Product')->save($product);
#$product->save(); 
?>

The code goes as far as the URL change then it fails with:

PHP Fatal error:  Uncaught Magento\Framework\Exception\LocalizedException: Area code is not set in /var/www/html/vendor/magento/framework/App/State.php:153
Stack trace:
#0 /var/www/html/vendor/magento/module-catalog/Model/Product.php(2415): Magento\Framework\App\State->getAreaCode()
#1 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Catalog\Model\Product->getIdentities()
#2 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Catalog\Model\Product\Interceptor->___callParent('getIdentities', Array)
#3 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Catalog\Model\Product\Interceptor->Magento\Framework\Interception\{closure}()
#4 /var/www/html/generated/code/Magento/Catalog/Model/Product/Interceptor.php(52): Magento\Catalog\Model\Product\Interceptor->___callPlugins('getIdentities', Array, Array)
#5 /var/www/html/vendor/magento/framework/App/Cache/Tag/Strategy/Identifier.php(25): Magento\Catalog\Model\Product\Interceptor->getIdentities( in /var/www/html/vendor/magento/framework/App/State.php on line 153


I am unsure why would I be defining any area codes when I am only changing a product not an order or a customer?!

Was it helpful?

Solution

You need to set Area code in your root file. Add this below code and run your script :

$state = $objectManager->get('\Magento\Framework\App\State');
$state->setAreaCode('frontend');

OTHER TIPS

You always need to set an area code if you want to modify some data in Magento2 and for a lot of other stuff.

Setting the area code can be done by injecting, or in your case using the objectmanager to get an instance of the class \Magento\Framework\App\State and calling the method setAreaCode with one of the areas provided as constants in \Magento\Framework\App\Area.

If you create custom console commands for Magento2 you may run into the same issue, also for this one you can set the area code manually like described here: 'Area code not set' issue in custom CLI commands in Magento 2.

You still need to take care, that the area code is not set already, because setting the area code, if it is already set, will also throw an exception. So checking this by getting the area code first, is in my opinion recommended.

I also would not recommend to write Magento2 shell scripts like this, because you can usually run into a lot of issues you may not occur when creating a small module around a script.

I have finalized the code adding command line parameters such as

  • new url
  • store id
  • product id

Run this from inside your magento 2 root directory to change an url. Also I added support for create permanent redirect to the old url as by default it is not set.

<?php

use \Magento\Framework\App\Bootstrap;
include('/var/www/html/app/bootstrap.php');

$url=$argv[1];
$storeid=$argv[2];
$productid=$argv[3];

$bootstrap = Bootstrap::create(BP, $_SERVER);  
$obj = $bootstrap->getObjectManager();
$deploymentConfig = $obj->get('Magento\Framework\App\DeploymentConfig');

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

#Setting area code, it won't work without this
$state = $objectManager->get('\Magento\Framework\App\State');
$state->setAreaCode('frontend');

#Load product using the product id 
$product = $objectManager->create('\Magento\Catalog\Model\Product')->load($productid);
$name = $product->getName();
$urlcode = $product->getUrlKey();

print $name."\n";
print $urlcode."\n";

#Setting store id, important of you have multiple stores
$product ->setStoreId($storeid);
#Setting the URL
$product ->setUrlKey($url);
#Setting Create Permanent Redirect for old URL
$product ->setData('save_rewrites_history',1);
#Saving Product
$product->save($product); 

?>

The syntax of the script would be:

php urlchange.php new-url-you-want-to-set your-store-id productid

Example:

php urlchange.php dell-inspiron-14500 3 1222

I hope this will help others.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top