June 29, 2017


Thinking Magento

Update Product URL's Programmatically with 301 redirect

Recently I needed to update the URL's of existing products, without losing the 301 redirects. There are ways of course of doing this with extensions and uploading CSV's to extensions, however I decided to take a different route and update the URL's programmatically. 

Created a PHP file and placed it in root, in this case we can call it URL_UPDATER.php and added the following code. Set the ID's that you would like update to avoid overloading your database. Job don.


require_once 'app/Mage.php';
/*Set store to be admin so that you the URL change affects global*/

/*Build collection of products*/
$collection = Mage::getResourceModel('catalog/product_collection');

/*Set the product ID range of products you would like to adjust 7157 - 7357*/
$collection->addFieldToFilter('entity_id', array('gt' => 7156));
$collection->addFieldToFilter('entity_id', array('lt' => 7358));

foreach($collection as $id) {

/*Get the ID of the product to load*/
$load = $id['entity_id'];

/*Load the product*/
$_product = Mage::getModel('catalog/product')->load($load);

/*New URL based on product name*/
$new_url = Mage::getModel('catalog/product_url')->formatUrlKey($_product->getName());

// save rewrites history for old to new url redirect
$_product->setData('save_rewrites_history', true);

// set new url

// set new url path

// save the product


Daylight Savings and Magento - date_default_timezone_set problem

A strange situation I've noticed can happen if you directly use date_default_timezone_set anywhere in your PHP code.

I had this set in an Observer.php file that was activated by cron.php / cron.sh.

Once this script was activated it changed the behaviour of the cronjob timestamps.

A job that started at 9am would finish not at 9AM, but finish at 10AM.

I then noticed that in using date_default_timezone_set in s script to look for products that were on sale, it again was changing timestamps in the database.

Finally I noticed that order date/time were sometimes in the future and sometimes not. This again came about due to date_default_timezone_set  was being used against shipping methods and when those methods would be available.

Removing date_default_timezone_set removed this timezone problems and there was no need for any work around to get Magento to work with BST.

However, you still need perform a datetime lookup in your code, which means you can do one of a few things.

Either you can use the following to check date and time for BST/GMT stores

date('Y-m-d H:i:s', Mage::getModel('core/date')->Timestamp());
date('H', Mage::getModel('core/date')->Timestamp());

Or you could use something a bit more complex, however does the job as well.

$tz = new DateTimeZone(Mage::getStoreConfig('general/locale/timezone')); 
$theTime = time();$transition = $tz->getTransitions($theTime, $theTime); 
$i = $transition[0]['offset'];
date("Y-m-d", time() + $i);

Warning: simplexml_load_string(): Entity: line parser error : StartTag: invalid element name

So you've enabled your Magento cache and your var/log/system.log file is starting to fill up with entries. This is because it's just built a cache of your config.xml, system.xml & adminhtml.xml files and there is an error in one of them.

StartTag: invalid element name - This is often simple because the xml element starts with a number, but could be a symbol etc

Can we be sure it's a configuration .xml file? Yep, because of the following error lib/Varien/Simplexml/Config.php

Navigate via SSH to your app directory and run

find . -type f -name "*.xml" -exec xmllint --noout {} \;

This will validate your xml files and find the bad one... hopefully.

Unfortunately Magento throws a spanner into the works that you should also be aware of  the table CORE_CONFIG_DATA in your database. Magento takes the path value of each entry and converts it to an XML. So in your core_config_data table, you may see postcode/license and Magento will convert this to <postcode><license>

However if an old module corrupted or was badly formed when it was saved, you may find something with a path like 2DSoR0swfgww77YzlyE0EsGDiyjUIE4G, which would create an XML value of <2DSoR0swfgww77YzlyE0EsGDiyjUIE4G>, which is invalid anyway but also doesn't pertain to a modules configuration.

Delete this entry from your core_config_data table and you will be steam rolling along again

Magento Patch SUPEE-6285: What Developers Need to Know

Magento Patch SUPEE-6285 is one of those patches you are going to hate.

The problem you are going to face is tracking down any module that extends Mage_Adminhtml_Controller_Action

Now a formal check has been put in place in the form of protected function _isAllowed() 

The check affects admin users who have restrictived roles. The moment a role becomes restricted the extra check comes into play.

Going to an admin menu that results in Access Denied is frustrating, but solvable.

You will need to go to your controllers directory and in Controller.php that extends Mage_Adminhtml_Controller_Action will need to have protected function _isAllowed() added in which a check to see if the session allows for access.

It's not always straight forward. Checking the session against access to the modules configuration page isn't normal practice. You normally don't want employees fiddling with the configuration of the module, so my advice is to check the session against the top of the menu tree.

For example you have a main menu for your module which has 6 sub / children menus. Set your allowed action to check the main menu only.

protected function _isAllowed()
return Mage::getSingleton('admin/session')->isAllowed('pathto/acl_mainmenu');

Placing this into your Controller.php will then give access back to those who are suffering from Access Denied for that module.

Need to find your acl mainmenu path. This will be either in adminhtml.xml or config.xml in your etc directory for the module. 

<trackingimport translate="title" module="trackingimport">

This translates to the following to add into your Controller.php

return Mage::getSingleton('admin/session')->isAllowed('sales/trackingimport');

-------------------- THEME UPDATES ------------------


If you have any themes that overwrite these files, you will need to patch them as well. These files are vulnerable to unescaped HTML injection attacks.

Magento - My Cron Is Running, But No Cron Schedule

So you've just finished off your Magento installation and you're trying to get the cronjob to queue up so that they can run, however nothing is being populated in your cron_schedule table.

As long as you've not updated the cron configuration in System > Configuration > System your generation ahead is for every 20 minutes and this is produced every 15 minutes.

This should mean running http://www.yourdomain.com/cron.php will populate cron_schedule in your database. In the cases that this doesn't happen, it's time to check your cache directory.

var/cache needs to be writeable

If it is writeable, try deleting it's contents and running http://www.yourdomain.com/cron.php again and seeing if it populates cron_schedule in your database.

In the instance that it works briefly, but either stops generating or only generates half of the schedule, then it's time to look at your permissions.

Check to see which user is creating the files in var/cache

It maybe that your PHP or PHP-FPM is configured to use the wrong user. It could be using apache/apache as the initial file user/group.

Page 1 of 8