Meta keywords for OpenCart

OpenCart out of the box does not support meta keywords throughout the system. This is relatively easy to add, but you will need to edit each controller to enable this.

In this particular post we’ll take a look at adding support for meta keywords on the OpenCart home page. There is support already for a meta description and this can be configured in the back end of OpenCart under System » Settings » Store » Meta Tag Description.

Our aim will be to add another field beneath that called “Meta Tag Keywords” and have this reflect in the source of the homepage.

There are two parts to this: adding support for editing and storing the meta keywords in the admin, and adding the code to the front of the website so that the value will be used.

In the admin:

There are three things you’ll need to do to provide support for this in the admin.

  1. Edit the setting controller to get the value from the database.
  2. Edit the setting language file to provide labels for the form.
  3. Edit the settings template to provide the HTML for the form.

The Controller

The admin controller we want is found in the admin/controller/setting/setting.php file. Depending on which version of OpenCart you have, at about line 47 you’ll find a reference to the entry_meta_description. Simply copy that line and replace the text entry_meta_description with entry_meta_keywords.
$this->data['entry_meta_keywords'] = $this->language->get('entry_meta_keywords');
Also, a bit later in the file (search for config_meta_description) we want to add a section which will take care of collecting up the posted results of the form. Use the other sections as a guide:
if (isset($this->request->post['config_meta_keywords'])) {
	$this->data['config_meta_keywords'] = $this->request->post['config_meta_keywords'];
} else {
	$this->data['config_meta_keywords'] = $this->config->get('config_meta_keywords');
}

The language file

The language file changes are very simple. Open the file admin/language/english/setting/setting.php and add a line beneath the entry_meta_description line that says:

$_['entry_meta_keywords']     = 'Meta Tag Keywords:';

The settings template (view)

Oopen the file admin/view/template/setting/setting.tpl, find the config_meta_description and paste this after it. Note that it’s a HTML table so you’ll paste this after the closing </tr> tag of the table row for the meta description:

<tr>
  <td><?php echo $entry_meta_keywords; ?></td>
  <td><input type="text" name="config_meta_keywords" value="<?php echo $config_meta_keywords; ?>" />
    <?php if ($error_entry_meta_keywords) { ?>
    <span class="error"><?php echo $error_entry_meta_keywords; ?></span>
    <?php } ?></td>
</tr>

In the front end:

The front end changes are very straightforward. We need to make changes to the header template and the home controller.

The header template

Open the file catalog/view/theme/default/template/common/header.tpl and add the following code after the definition of the description meta tag:

<?php if ($keywords) { ?>
<meta name="keywords" content="<?php echo $keywords; ?>" />
<?php } ?>

The home controller

Finally, open the home controller (catalog/controller/common/home.php) and find the reference to the config_meta_description. Simply copy that line and change it for the keywords:

$this->document->keywords = $this->config->get('config_meta_keywords');

Complete

Now you’re done – you should be able to update the keywords in the System » Settings » Store » Meta Tag Keywords and see these in the HTML source.

In addition to this, you’ve also made a key change to the template so that in any controller you can set $this->document->keywords to whatever you like and those keywords will show in the HTML source.

 

 

Magento: Default Product Listing Sort by not exists on Available Product Listing Sort By

We have a system that populates a Magento installation by reading an external database and creating, updating and deleting products and categories. Recently I had been receiving an obscure message when trying to update categories using the Magento API.

The message was simply: Default Product Listing Sort by not exists on Available Product Listing Sort By

After Googling around I hadn’t turned up much, which forced me into the bowels of Magento. This exception is thrown in the file app/code/core/Mage/Model/Category/Attribute/Backend/Sortby.php on line 81 and 85. This file is responsible for checking that the Sort By method specified for a category is valid.

Default Display Settings for a new cateogry

Default Display Settings for a new cateogry

When you create a category in Magento using the Admin UI, the values in the Display Settings tab of the category as set as per this screenshot (click to enlarge).  The default values are:

  • Available Product Listing Sort By = Use All Available Attributes
  • Default Product Listing Sort By = Use Config Settings

With this category created, I used the following test script to check to see if I could update the category.  This script simply asks for the information about the category (category 4066 in my case) and attempts to update the category with that information.

<?php
 	define('MAGENTO', getcwd() );
 	define('CATEGORY_ID', 4066 );
	require_once MAGENTO . '/app/Mage.php';
	umask(0);
	Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
 
	try
	{
		$info = Mage::getModel('catalog/category_api')->info( CATEGORY_ID );
		var_dump( $info );
		Mage::getModel('catalog/category_api')->update( CATEGORY_ID, $info );
 
		echo "\n\nSUCCESS\n\n";
	}
	catch( Exception $e )
	{
		var_dump( $e );
	}
?>

When I ran this with the default settings, I received a “data_invalid” exception, however tweaking it to use any of the values in the select box for the Default Product Listing Sort By resulted in the exception “Default Product Listing Sort by not exists on Available Product Listing Sort By” (tip: it was useful to pipe the output of this script to `less’). I then had a test script that I could use to verify when my problem was fixed.

I then fiddled around with the display settings in Magento (which by the way does not suffer from this problem when saving a category) and found that if I set the Available Product Listing Sort By to anything other than using the tick to use all available attributes, and set the Default Product Listing Sort By to anything other than using the tick to use the Config Settings, then things magically started working.

This eventually led to me reworking a bit of code to include specific values for the available_sort_by and default_sort_by attributes when updating the category. Here’s my bit of code – out of context, but you get the idea.

    $result = $api->update
    (
        $category_id,
        array
        (
            'image' => $image_path,
            'description' => $description,
            'meta_description' => $meta_description,
            'meta_keywords' => $meta_keywords,
            'available_sort_by' => array( 'name' ),
            'default_sort_by' => 'name'
        )
    );

Good luck!

Magento: loadParentProductIds() is deprecated

As of Magento 1.4.2.0, the loadParentProductIds() method in the product model has been deprecated and is no longer available.

Here’s an example of it being used:
http://www.magentocommerce.com/boards/viewthread/74229

Prior to Magento 1.4.2.0, this would have worked:

list( $parentId ) = $_product->loadParentProductIds()->getData('parent_product_ids');

After Magento 1.4.2.0, this works:

list( $parentId ) = Mage::getModel( 'catalog/product_type_grouped' )->getParentIdsByChild( $_product->getId() );

Note that the above fetched the parent product ID’s for a grouped product – there are also versions for configurable products in the catalog/product_type_configurable model.

Good luck!

Updating Magento categories, en masse

I had a problem where I had to update all of the categories in a Magento store to change the CMS block to “Sub Category Listing” because they had been created without a CMS block selected. Doing this through the UI would have been painful as there were over 300 categories that had to be updated.

The solution was relatively simple, thanks to a quick PHP script. I put this in the webroot as updatecategories.php:

<?php
 
ob_end_flush();
echo "Started " . date( "d/m/y h:i:s" ) . "\r\n";
require_once '/app/Mage.php';
umask(0);
Mage::app()->setCurrentStore( Mage_Core_Model_App::ADMIN_STORE_ID );
 
$categories = Mage::getModel( 'catalog/category' )->getCollection();
echo "Processing " . count( $categories ) . " categories\r\n";
foreach( $categories as $category )
{
    // 6 is the ID for "Sub Category Listing"
    $category->setData( 'landing_page', 6 )->save();
    echo ".";
}
echo "\r\n";
echo "Finished ".date( "d/m/y h:i:s" )."\r\n";
 
?>

I then ran the script (e.g. php updatecategories.php) and after about 30 seconds all categories were changed. You could probably point your web browser at the file as well to achieve the same effect. This will give you a starting point if you need to do anything else to the category, e.g. change the description, name, image etc.

Emulating “immediate mode” in a PHP CLI script

I’ve been working on a complex PHP CLI script lately and in order to debug something I’ve been putting var_dump() and die commands at the appropriate place.  This is annoying.

Packages like xdebug provide the ability to put a breakpoint in, but this requires you to configure your environment appropriately and use an IDE that can listen and step through the script.  Also, I’ve seen people having trouble using xdebug with PHP CLI – I haven’t tried it myself.

So, anyway my hacky solution was to roll the following code at the point I wanted to debug.  I had the variable scope at my disposal, so I could issue my own var_dump(), echo and variable assignment commands, before then entering “break;” to get out of the loop (I had to put an exception in for “break;” because the break is run in the eval command and it won’t break out of it without an error).

// Helper line so I can find and remove this code later:
echo "\n" . __FILE__ . ':' . __LINE__ . ' breakpoint' . PHP_EOL;
while( true )
{
	$cmd = readline( "debug&gt; " );
	if( $cmd == 'break;' ) { break; }
	eval( $cmd );
}

You may want to wrap this in some logic test so that it only fires when certain criteria are met.

WordPress Themes