Adding a Second Image for PrestaShop Categories

PrestaShop only allows using one image as category thumbnail by default, thus creating issues in having different formats for subcategory images in the product list view. In this tutorial we will add a secondary image to prestashop categories, to increase flexibility on thumbs display when showing them as subcategories.

  • Prestashop version: any 1.6 (used: 1.6.0.9, should equally apply to 1.5, though not tested)

Download Project Files

Introduction

Before starting, it’s worth noticing this tutorial implies quite a lot of modifications and overrides, and it’s therefore recommended that you have a solid knowledge of php before doing anything. As always, refer to the Official Prestashop documentation on Overrides if you are new to the subject. That said, these are the files we need to override/modify:

  • AdminCategoriesController.php: here is where most of the magic will occur, to upload and delete the new image
  • Category.php: the category class, as we have to implement the new field and image file deletion
  • category.tpl: to display the new image for subcategories
  • .htaccess: only needed if you use Friendly urls, otherwise no image will be shown

Extending the AdminCategoriesController file

The categories’ admin controller is the file we will be mostly dealing with. Although we could modify it directly, it’s always best practice to use an override. Therefore, create a new file in /override/controllers/admin named AdminCategoriesController.php, and paste the following inside php tags:

[php]
class AdminCategoriesController extends AdminCategoriesControllerCore
{
}
[/php]

Then, reach the original AdminCategoriesController located within /controllers/admin, open it, locate and copy the whole renderForm method. Then, paste it inside the new override:

[php]

class AdminCategoriesController extends AdminCategoriesControllerCore
{

public function renderForm()
{
$this->initToolbar();
$obj = $this->loadObject(true);
$id_shop = Context::getContext()->shop->id;
$selected_categories = array((isset($obj->id_parent) && $obj->isParentCategoryAvailable($id_shop))? (int)$obj->id_parent : (int)Tools::getValue(‘id_parent’, Category::getRootCategory()->id));
$unidentified = new Group(Configuration::get(‘PS_UNIDENTIFIED_GROUP’));
$guest = new Group(Configuration::get(‘PS_GUEST_GROUP’));
$default = new Group(Configuration::get(‘PS_CUSTOMER_GROUP’));

$unidentified_group_information = sprintf($this->l(‘%s – All people without a valid customer account.’), ‘<b>’.$unidentified->name[$this->context->language->id].'</b>’);
$guest_group_information = sprintf($this->l(‘%s – Customer who placed an order with the guest checkout.’), ‘<b>’.$guest->name[$this->context->language->id].'</b>’);
$default_group_information = sprintf($this->l(‘%s – All people who have created an account on this site.’), ‘<b>’.$default->name[$this->context->language->id].'</b>’);

if (!($obj = $this->loadObject(true)))
return;

$image = _PS_CAT_IMG_DIR_.$obj->id.’.jpg’;
$image_url = ImageManager::thumbnail($image, $this->table.’_’.(int)$obj->id.’.’.$this->imageType, 350,
$this->imageType, true, true);
$image_size = file_exists($image) ? filesize($image) / 1000 : false;

$this->fields_form = array(
‘tinymce’ => true,
‘legend’ => array(
‘title’ => $this->l(‘Category’),
‘icon’ => ‘icon-tags’
),
‘input’ => array(
array(
‘type’ => ‘text’,
‘label’ => $this->l(‘Name’),
‘name’ => ‘name’,
‘lang’ => true,
‘required’ => true,
‘class’ => ‘copy2friendlyUrl’,
‘hint’ => $this->l(‘Invalid characters:’).’ <>;=#{}’,
),
array(
‘type’ => ‘switch’,
‘label’ => $this->l(‘Displayed’),
‘name’ => ‘active’,
‘required’ => false,
‘is_bool’ => true,
‘values’ => array(
array(
‘id’ => ‘active_on’,
‘value’ => 1,
‘label’ => $this->l(‘Enabled’)
),
array(
‘id’ => ‘active_off’,
‘value’ => 0,
‘label’ => $this->l(‘Disabled’)
)
)
),
array(
‘type’ => ‘categories’,
‘label’ => $this->l(‘Parent category’),
‘name’ => ‘id_parent’,
‘tree’ => array(
‘id’ => ‘categories-tree’,
‘selected_categories’ => $selected_categories,
‘disabled_categories’ => !Tools::isSubmit(‘add’.$this->table) ? array($this->_category->id) : null
)
),
array(
‘type’ => ‘textarea’,
‘label’ => $this->l(‘Description’),
‘name’ => ‘description’,
‘autoload_rte’ => true,
‘lang’ => true,
‘hint’ => $this->l(‘Invalid characters:’).’ <>;=#{}’
),
array(
‘type’ => ‘file’,
‘label’ => $this->l(‘Image’),
‘name’ => ‘image’,
‘display_image’ => true,
‘image’ => $image_url ? $image_url : false,
‘size’ => $image_size,
‘delete_url’ => self::$currentIndex.’&’.$this->identifier.’=’.$this->_category->id.’&token=’.$this->token.’&deleteImage=1′,
‘hint’ => $this->l(‘Upload a category logo from your computer.’),
),
array(
‘type’ => ‘text’,
‘label’ => $this->l(‘Meta title’),
‘name’ => ‘meta_title’,
‘lang’ => true,
‘hint’ => $this->l(‘Forbidden characters:’).’ <>;=#{}’
),
array(
‘type’ => ‘text’,
‘label’ => $this->l(‘Meta description’),
‘name’ => ‘meta_description’,
‘lang’ => true,
‘hint’ => $this->l(‘Forbidden characters:’).’ <>;=#{}’
),
array(
‘type’ => ‘tags’,
‘label’ => $this->l(‘Meta keywords’),
‘name’ => ‘meta_keywords’,
‘lang’ => true,
‘hint’ => $this->l(‘To add "tags," click in the field, write something, and then press "Enter."’).’&nbsp;’.$this->l(‘Forbidden characters:’).’ <>;=#{}’
),
array(
‘type’ => ‘text’,
‘label’ => $this->l(‘Friendly URL’),
‘name’ => ‘link_rewrite’,
‘lang’ => true,
‘required’ => true,
‘hint’ => $this->l(‘Only letters, numbers, underscore (_) and the minus (-) character are allowed.’)
),
array(
‘type’ => ‘group’,
‘label’ => $this->l(‘Group access’),
‘name’ => ‘groupBox’,
‘values’ => Group::getGroups(Context::getContext()->language->id),
‘info_introduction’ => $this->l(‘You now have three default customer groups.’),
‘unidentified’ => $unidentified_group_information,
‘guest’ => $guest_group_information,
‘customer’ => $default_group_information,
‘hint’ => $this->l(‘Mark all of the customer groups which you would like to have access to this category.’)
)
),
‘submit’ => array(
‘title’ => $this->l(‘Save’),
‘name’ => ‘submitAdd’.$this->table.($this->_category->is_root_category && !Tools::isSubmit(‘add’.$this->table) && !Tools::isSubmit(‘add’.$this->table.’root’) ? ”: ‘AndBackToParent’)
)
);

$this->tpl_form_vars[‘shared_category’] = Validate::isLoadedObject($obj) && $obj->hasMultishopEntries();
$this->tpl_form_vars[‘PS_ALLOW_ACCENTED_CHARS_URL’] = (int)Configuration::get(‘PS_ALLOW_ACCENTED_CHARS_URL’);
$this->tpl_form_vars[‘displayBackOfficeCategory’] = Hook::exec(‘displayBackOfficeCategory’);

// Display this field only if multistore option is enabled
if (Configuration::get(‘PS_MULTISHOP_FEATURE_ACTIVE’) && Tools::isSubmit(‘add’.$this->table.’root’))
{
$this->fields_form[‘input’][] = array(
‘type’ => ‘switch’,
‘label’ => $this->l(‘Root Category’),
‘name’ => ‘is_root_category’,
‘required’ => false,
‘is_bool’ => true,
‘values’ => array(
array(
‘id’ => ‘is_root_on’,
‘value’ => 1,
‘label’ => $this->l(‘Yes’)
),
array(
‘id’ => ‘is_root_off’,
‘value’ => 0,
‘label’ => $this->l(‘No’)
)
)
);
unset($this->fields_form[‘input’][2],$this->fields_form[‘input’][3]);
}
// Display this field only if multistore option is enabled AND there are several stores configured
if (Shop::isFeatureActive())
$this->fields_form[‘input’][] = array(
‘type’ => ‘shop’,
‘label’ => $this->l(‘Shop association’),
‘name’ => ‘checkBoxShopAsso’,
);

// remove category tree and radio button "is_root_category" if this category has the root category as parent category to avoid any conflict
if ($this->_category->id_parent == Category::getTopCategory()->id && Tools::isSubmit(‘updatecategory’))
foreach ($this->fields_form[‘input’] as $k => $input)
if (in_array($input[‘name’], array(‘id_parent’, ‘is_root_category’)))
unset($this->fields_form[‘input’][$k]);

if (!($obj = $this->loadObject(true)))
return;

$image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.’/’.$obj->id.’.jpg’, $this->table.’_’.(int)$obj->id.’.’.$this->imageType, 350, $this->imageType, true);

$this->fields_value = array(
‘image’ => $image ? $image : false,
‘size’ => $image ? filesize(_PS_CAT_IMG_DIR_.’/’.$obj->id.’.jpg’) / 1000 : false
);

// Added values of object Group
$category_groups_ids = $obj->getGroups();

$groups = Group::getGroups($this->context->language->id);
// if empty $carrier_groups_ids : object creation : we set the default groups
if (empty($category_groups_ids))
{
$preselected = array(Configuration::get(‘PS_UNIDENTIFIED_GROUP’), Configuration::get(‘PS_GUEST_GROUP’), Configuration::get(‘PS_CUSTOMER_GROUP’));
$category_groups_ids = array_merge($category_groups_ids, $preselected);
}
foreach ($groups as $group)
$this->fields_value[‘groupBox_’.$group[‘id_group’]] = Tools::getValue(‘groupBox_’.$group[‘id_group’], (in_array($group[‘id_group’], $category_groups_ids)));

$this->fields_value[‘is_root_category’] = (bool)Tools::isSubmit(‘add’.$this->table.’root’);

return parent::renderForm();
}

}
[/php]

Notice the last row, return parent::renderForm();. Change it to return AdminController::renderForm();. if we didn’t take this counter-measure, all of our changes would have been overridden by the original controller. To make sure the override works, reach the cache/ and erase class_index.php to enable the new file. Then login to the back office, and check the single category view works as expected. If so, read on.

Adding the new field

First off, we will need to add the code that displays any eventual image we upload. To do so, locate the following:

[php]
$image = _PS_CAT_IMG_DIR_.$obj->id.’.jpg’;
$image_url = ImageManager::thumbnail($image, $this->table.’_’.(int)$obj->id.’.’.$this->imageType, 350,
$this->imageType, true, true);
$image_size = file_exists($image) ? filesize($image) / 1000 : false;
[/php]

Right after it, add

[php]
$image2 = _PS_CAT_IMG_DIR_.$obj->id.’_second.jpg’;
$image_url2 = ImageManager::thumbnail($image2, $this->table.’_’.(int)$obj->id.’_second.’.$this->imageType, 350,
$this->imageType, true, true);
$image_size2 = file_exists($image2) ? filesize($image2) / 1000 : false;
[/php]

Which is basically the same with modified names. Next, right below we have the fields list. We need to add our file input here, so that we can later upload the image. Therefore, locate:

[php]
array(
‘type’ => ‘file’,
‘label’ => $this->l(‘Image’),
‘name’ => ‘image’,
‘display_image’ => true,
‘image’ => $image_url ? $image_url : false,
‘size’ => $image_size,
‘delete_url’ => self::$currentIndex.’&’.$this->identifier.’=’.$this->_category->id.’&token=’.$this->token.’&deleteImage=1′,
‘hint’ => $this->l(‘Upload a category logo from your computer.’),
),
[/php]

And add the following right after it

[php]
array(
‘type’ => ‘file’,
‘label’ => $this->l(‘Image2’),
‘name’ => ‘image2’,
‘display_image’ => true,
‘image’ => $image_url2 ? $image_url2 : false,
‘size’ => $image_size2,
‘delete_url’ => self::$currentIndex.’&’.$this->identifier.’=’.$this->_category->id.’&token=’.$this->token.’&deleteImage2=1′,
‘hint’ => $this->l(‘Upload a secondary category logo from your computer.’),
),
[/php]

Once again, same code, different names. And, lastly, change this:

[php]
$image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.’/’.$obj->id.’.jpg’, $this->table.’_’.(int)$obj->id.’.’.$this->imageType, 350, $this->imageType, true);

$this->fields_value = array(
‘image’ => $image ? $image : false,
‘size’ => $image ? filesize(_PS_CAT_IMG_DIR_.’/’.$obj->id.’.jpg’) / 1000 : false
);
[/php]

Into this

[php]
$image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.’/’.$obj->id.’.jpg’, $this->table.’_’.(int)$obj->id.’.’.$this->imageType, 350, $this->imageType, true);
$image2 = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.’/’.$obj->id.’_second.jpg’, $this->table.’_’.(int)$obj->id.’_second.’.$this->imageType, 350, $this->imageType, true);

$this->fields_value = array(
‘image’ => $image ? $image : false,
‘size’ => $image ? filesize(_PS_CAT_IMG_DIR_.’/’.$obj->id.’.jpg’) / 1000 : false,
‘image2’ => $image2 ? $image2 : false,
‘size2′ => $image2 ? filesize(_PS_CAT_IMG_DIR_.’/’.$obj->id.’_second.jpg’) / 1000 : false
);
[/php]

Useless to mention we are doing the same, once more. We are done with renderForm, let’s deal with postImage() now!

Managing the new image upload and removal

Trying to fill in the new file input would not produce anything, at the moment. The whole upload magic is held through a method named postImage(), which we are going to override and extend. Thus, copy it from the original AdminCategoriesController, and paste it inside the override file. It should look like the following:

[php]

protected function postImage($id)
{
$ret = parent::postImage($id);
if (($id_category = (int)Tools::getValue(‘id_category’)) &&
isset($_FILES) && count($_FILES) && $_FILES[‘image’][‘name’] != null &&
file_exists(_PS_CAT_IMG_DIR_.$id_category.’.jpg’))
{
$images_types = ImageType::getImagesTypes(‘categories’);
foreach ($images_types as $k => $image_type)
{
ImageManager::resize(
_PS_CAT_IMG_DIR_.$id_category.’.jpg’,
_PS_CAT_IMG_DIR_.$id_category.’-‘.stripslashes($image_type[‘name’]).’.jpg’,
(int)$image_type[‘width’], (int)$image_type[‘height’]
);
}
}

return $ret;
}
[/php]

Get rid of return $ret;, and add the following instead:

[php]

$ret2 = $this->uploadImage($id.’_second’, ‘image2’, $this->fieldImageSettings[‘dir’].’/’);
if (($id_category = (int)Tools::getValue(‘id_category’)) &&
isset($_FILES) && count($_FILES) && $_FILES[‘image2’][‘name’] != null &&
file_exists(_PS_CAT_IMG_DIR_.$id_category.’_second.jpg’))
{
$images_types = ImageType::getImagesTypes(‘categories’);
foreach ($images_types as $k => $image_type)
{
ImageManager::resize(
_PS_CAT_IMG_DIR_.$id_category.’_second.jpg’,
_PS_CAT_IMG_DIR_.$id_category.’_second-‘.stripslashes($image_type[‘name’]).’.jpg’,
(int)$image_type[‘width’], (int)$image_type[‘height’]
);
}
}

return $ret && $ret2;

[/php]

Explanation: first, we are grabbing some code directly from the adminController. We have to use a custom name for the image upload, which is the category id plus _second, using the field “image2”. The rest is simply a copy/paste of the above, with, again, changes in the name only. Lastly, we make sure that we return true only if both eventual uploads were successful.

We have a problem though. At the time being, Prestashop still thinks we only have one image for the category entity. Thus, when uploading any other image for it (excluding thumbs), it will erase the previous one. We can test it right away: upload a new image for the image2 field, you will notice the original category image will be erased. As we don’t want this, we have to grab imageUpload() directly from the AdminController.php file, and extend it. Locate the method, and paste it inside our override. In Prestashop 1.6.0.9, it looks like this:

[php]
protected function uploadImage($id, $name, $dir, $ext = false, $width = null, $height = null)
{
if (isset($_FILES[$name][‘tmp_name’]) && !empty($_FILES[$name][‘tmp_name’]))
{
// Delete old image
if (Validate::isLoadedObject($object = $this->loadObject()))
$object->deleteImage();
else
return false;

// Check image validity
$max_size = isset($this->max_image_size) ? $this->max_image_size : 0;
if ($error = ImageManager::validateUpload($_FILES[$name], Tools::getMaxUploadSize($max_size)))
$this->errors[] = $error;

$tmp_name = tempnam(_PS_TMP_IMG_DIR_, ‘PS’);
if (!$tmp_name)
return false;

if (!move_uploaded_file($_FILES[$name][‘tmp_name’], $tmp_name))
return false;

// Evaluate the memory required to resize the image: if it’s too much, you can’t resize it.
if (!ImageManager::checkImageMemoryLimit($tmp_name))
$this->errors[] = Tools::displayError(‘Due to memory limit restrictions, this image cannot be loaded. Please increase your memory_limit value via your server\’s configuration settings. ‘);

// Copy new image
if (empty($this->errors) && !ImageManager::resize($tmp_name, _PS_IMG_DIR_.$dir.$id.’.’.$this->imageType, (int)$width, (int)$height, ($ext ? $ext : $this->imageType)))
$this->errors[] = Tools::displayError(‘An error occurred while uploading the image.’);

if (count($this->errors))
return false;
if ($this->afterImageUpload())
{
unlink($tmp_name);
return true;
}
return false;
}
return true;
}

[/php]

Pay attention at this snippet:

[php]

// Delete old image
if (Validate::isLoadedObject($object = $this->loadObject()))
$object->deleteImage();
else
return false;
[/php]

It’s where the original image gets erased to make room for a new one. Change it to:

[php]

// Delete old image
if (Validate::isLoadedObject($object = $this->loadObject()))
{
if($name == ‘image2’)
$object->deleteImage2();
else $object->deleteImage();
} else
return false;
[/php]

It won’t work yet as didn’t override the Category class and added the deleteImage2 method. Before leaving this file, we need to extend one, last function, postProcess(). Copy it again from the original AdminCategoriesController, it should be something like:

[php]

public function postProcess()
{
if (!in_array($this->display, array(‘edit’, ‘add’)))
$this->multishop_context_group = false;
if (Tools::isSubmit(‘forcedeleteImage’) || (isset($_FILES[‘image’]) && $_FILES[‘image’][‘size’] > 0) || Tools::getValue(‘deleteImage’))
{
$this->processForceDeleteImage();
if (Tools::isSubmit(‘forcedeleteImage’))
Tools::redirectAdmin(self::$currentIndex.’&token=’.Tools::getAdminTokenLite(‘AdminCategories’).’&conf=7′);
}

return parent::postProcess();
}
[/php]

We need to take care of the secondary image deletion:

[php]

public function postProcess()
{
if (!in_array($this->display, array(‘edit’, ‘add’)))
$this->multishop_context_group = false;
if (Tools::isSubmit(‘forcedeleteImage’) || (isset($_FILES[‘image’]) && $_FILES[‘image’][‘size’] > 0) || Tools::getValue(‘deleteImage’))
{
$this->processForceDeleteImage();
if (Tools::isSubmit(‘forcedeleteImage’))
Tools::redirectAdmin(self::$currentIndex.’&token=’.Tools::getAdminTokenLite(‘AdminCategories’).’&conf=7′);
} else if(Tools::getValue(‘deleteImage2′))
{
$category = $this->loadObject(true);

if (Validate::isLoadedObject($category))
if($category->deleteImage2(true))
Tools::redirectAdmin(self::$currentIndex.’&token=’.Tools::getAdminTokenLite(‘AdminCategories’).’&updatecategory&id_category=’.$category->id.’&conf=7′);
}

return parent::postProcess();
}
[/php]

And we are done with this file, let’s extend the Category class now.

Overriding the category class

Create a new file inside override/classes and name it Category.php (or use an existing override if you have it). First of all, we need to test it the back office functionality, so let’s add that deleteImage2() method:

[php]

Class Category extends CategoryCore
{

public function deleteImage2($force_delete = false)
{
if (!$this->id)
return false;

if ($force_delete || !$this->hasMultishopEntries())
{
/* Deleting object images and thumbnails (cache) */
if ($this->image_dir)
{
if (file_exists($this->image_dir.$this->id.’_second.’.$this->image_format)
&& !unlink($this->image_dir.$this->id.’_second.’.$this->image_format))
return false;
}
if (file_exists(_PS_TMP_IMG_DIR_.$this->def[‘table’].’_’.$this->id.’_second.’.$this->image_format)
&& !unlink(_PS_TMP_IMG_DIR_.$this->def[‘table’].’_’.$this->id.’_second.’.$this->image_format))
return false;
if (file_exists(_PS_TMP_IMG_DIR_.$this->def[‘table’].’_mini_’.$this->id.’_second.’.$this->image_format)
&& !unlink(_PS_TMP_IMG_DIR_.$this->def[‘table’].’_mini_’.$this->id.’_second.’.$this->image_format))
return false;

$types = ImageType::getImagesTypes();
foreach ($types as $image_type)
if (file_exists($this->image_dir.$this->id.’_second-‘.stripslashes($image_type[‘name’]).’.’.$this->image_format)
&& !unlink($this->image_dir.$this->id.’_second-‘.stripslashes($image_type[‘name’]).’.’.$this->image_format))
return false;
}
return true;
}
}
[/php]

To create it, I simply copied the original deleteImage from the objectModel, and modified the name of each entry to reflect our convention (_second).

Time to test the back office! Access the categories tab, then open up one of them and try adding an image. Then, delete this image to check if that works as well. Then again add one, and one immediately after to check it gets over-written. Lastly, make sure the original one isn’t erased during this process, and the new one is not affected by any operation on the first one.

After checking this, it’s time to display the new thumb. Since we will use it in subcategories, we need to assign it at the time they are retrieved for the template display. This is held through the getSubcategories() method of the Category class. Thus, copy the original one and paste it inside our override:

[php]
public function getSubCategories($id_lang, $active = true)
{
$sql_groups_where = ”;
$sql_groups_join = ”;
if (Group::isFeatureActive())
{
$sql_groups_join = ‘LEFT JOIN `’._DB_PREFIX_.’category_group` cg ON (cg.`id_category` = c.`id_category`)’;
$groups = FrontController::getCurrentCustomerGroups();
$sql_groups_where = ‘AND cg.`id_group` ‘.(count($groups) ? ‘IN (‘.implode(‘,’, $groups).’)’ : ‘=’.(int)Group::getCurrent()->id);
}

$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(‘
SELECT c.*, cl.id_lang, cl.name, cl.description, cl.link_rewrite, cl.meta_title, cl.meta_keywords, cl.meta_description
FROM `’._DB_PREFIX_.’category` c
‘.Shop::addSqlAssociation(‘category’, ‘c’).’
LEFT JOIN `’._DB_PREFIX_.’category_lang` cl ON (c.`id_category` = cl.`id_category` AND `id_lang` = ‘.(int)$id_lang.’ ‘.Shop::addSqlRestrictionOnLang(‘cl’).’)
‘.$sql_groups_join.’
WHERE `id_parent` = ‘.(int)$this->id.’
‘.($active ? ‘AND `active` = 1′ : ”).’
‘.$sql_groups_where.’
GROUP BY c.`id_category`
ORDER BY `level_depth` ASC, category_shop.`position` ASC’);

foreach ($result as &$row)
{

$row[‘legend’] = ‘no picture’;
}
return $result;
}
[/php]

Then, right after this:

[php]
$row[‘id_image’] = Tools::file_exists_cache(_PS_CAT_IMG_DIR_.$row[‘id_category’].’.jpg’) ? (int)$row[‘id_category’] : Language::getIsoById($id_lang).’-default’;
[/php]

Add our new image definition

[php]
$row[‘id_image2’] = Tools::file_exists_cache(_PS_CAT_IMG_DIR_.$row[‘id_category’].’_second.jpg’) ? (int)$row[‘id_category’] .’_second’ : Language::getIsoById($id_lang).’-default’;
[/php]

And we are done with php!

Display the new image in the template

We are almost there. Open category.tpl, located in the theme’s folder. Locate:

[php htmlscript=”true”]
{if $subcategory.id_image}
<img class="replace-2x" src="{$link->getCatImageLink($subcategory.link_rewrite, $subcategory.id_image, ‘medium_default’)|escape:’html’:’UTF-8′}" alt="" width="{$mediumSize.width}" height="{$mediumSize.height}" />
{else}
[/php]

And change it to

[php htmlscript=”true”]
{if $subcategory.id_image2}
<img class="replace-2x" src="{$link->getCatImageLink($subcategory.link_rewrite, $subcategory.id_image2, ‘medium_default’)|escape:’html’:’UTF-8′}" alt="" width="{$mediumSize.width}" height="{$mediumSize.height}" />
{else}
[/php]

This will be enough if friendly urls are not enabled. But what if we are using rewritten URLs? Sadly, we need to hardcode one, last modification in the .htaccess file. It is not exactly bulletproof, but it worked out well in all my tests. Therefore, open your .htaccess, and add the following at the very beginning, right BEFORE “# ~~start~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again”

[php]
<IfModule mod_rewrite.c>
RewriteRule ^c/([0-9]+)_second(\-[\.*_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1_second$2$3.jpg [L]
</IfModule>
[/php]

This will make sure our “_second” text in the image path won’t be treated as part of the category ID, thus making it impossible to retrieve the picture.

Conclusion

Despite being a bit cumbersome, adding a secondary image for categories (or actually any other entity such as manufacturers or suppliers) is indeed possible by using this technique. The final trick for rewritten-url environments is to make sure the proper regEx is added right at the beginning of the .htaccess file.

Need PrestaShop Modules? Have a look at my Prestashop Addons Store!

Looking for quality PrestaShop Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , , , , , | Posted under PrestaShop | RSS 2.0

Author Spotlight

Fabio Porta

Fabio has been involved in web development and design since 2005, when launched his first website at the age of 16. He’s now highly skilled in both client and server side development, along with design, and since August 2012 runs a successful website about PrestaShop tutorials and Prestashop Modules called Nemo’s Post Scriptum, at http://nemops.com

Leave a Reply

Your email address will not be published. Required fields are marked *