Adding an Image Attribute To A Product

This post deals with adding an image (or any other type of media) to a product. This is useful where an image is required to be separate from Magento’s built in product media system.

The Installer

First, we want to create our attribute.

<?php
$installer = $this;

$installer->startSetup();

$this->addAttribute('catalog_product', 'poster_frame', array(
    'attribute_set' => 'Default',
    'group'         => 'iWeb Media',
    'input'         => 'image',
    'type'          => 'varchar',
    'label'         => 'Poster Frame',
    'visible'       => true,
    'required'      => false,
    'visible_on_front' => true,
    'global'        => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
    'backend'       => 'iwebmedia/product_attribute_backend_image',
    'input_renderer'=> 'iwebmedia/adminhtml_product_image',
    'sort_order' => 10
));

$this->endSetup();
  • Because we’re saving an image, we need to create our own backend class to deal with the saving of the image and setting the filename of the image on the product object.
  • We also need to create a custom renderer for the input. This is a block class which we’ll create in our module. By default, Magento will use its own image renderer which is Mage_Adminhtml_Block_Catalog_Category_Helper_Image. This extends Varien_Data_Form_Element_Image and hardcodes the getUrl() method to look in media/catalog/product.

Note: The input_renderer is a special field for the catalog_product EAV type and is stored in the catalog_eav_attribute table as frontend_input_renderer.

The Input Renderer

<?php
class Iweb_Media_Block_Adminhtml_Product_Image extends Varien_Data_Form_Element_Image{
    protected function _getUrl()
    {
        $url = false;
        if ($this->getValue()) {
            $url = Mage::helper('iwebmedia')->getPlaceholderUrl() . $this->getValue();
        }
        return $url;
    }
}

– We just needed to change the getUrl() method to return the path to our image location, which we’ve got a helper to do so that’s only in one location.

The Helper Class

<?php
class Iweb_Media_Helper_Data extends Mage_Core_Helper_Abstract {
    const PLACEHOLDER_UPLOAD_DIR = "iwebmedia";
    
    public function getPlaceholderDir(){
        return Mage::getBaseDir('media') . DS . self::PLACEHOLDER_UPLOAD_DIR . DS;
    }
    
    public function getPlaceholderUrl(){
        return Mage::getBaseUrl('media') . '/' . self::PLACEHOLDER_UPLOAD_DIR . '/';
    }
}

The Attribute’s Backend Model

This is the class which deals with the saving of our data and image

<?php
class Iweb_Media_Model_Product_Attribute_Backend_Image extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract{        
    public function beforeSave($object){
        parent::beforeSave($object);
        
        $name = $this->_getName();
        $imageData = $object->getData($name);
        
        if(isset($imageData['delete']) && (bool) $imageData['delete']){
            return $this->_removeImage($object, $imageData['value']);
        }else{
            return $this->_uploadImage($object);
        }
    }
    
    protected function _getHelper(){
        return Mage::helper('iwebmedia');
    }
    
    protected function _getName(){
        return $this->getAttribute()->getName();
    }
    
    protected function _removeImage($object, $fileName){
        $file = $this->_getHelper()->getPlaceholderDir() . $fileName;
        $name = $this->_getName();
        
        if(file_exists($file)){
            unlink($file);
        }
        
        $object->setData($name, '');
    }
    
    protected function _uploadImage($object){
        $name = $this->_getName();
         
        if(!isset($_FILES[$name]) || (int) $_FILES[$name]['size'] <= 0){
            return;
        }
        
        $path = $this->_getHelper()->getPlaceholderDir();
        
        $uploader = new Varien_File_Uploader($_FILES[$name]);
        $uploader->setAllowedExtensions(array('jpg','jpeg','gif','png'));
        // Allow Magento to create a name for this upload!
        $uploader->setAllowRenameFiles(true);
        
        $result = $uploader->save($path);
        
        $object->setData($name, $result['file']);
    }
    
}

– We use the beforeSave() method which then uses the delete input (provided by Magento’s Varien_Data_Form_Element_Image class) to check whether we should remove the existing image or upload a new one.
– The Varien_File_Uploader class deals with the validation of the image and will throw an error in case of any failure.
– setAllowRenameFiles(true) allows the file uploader to create a new file name if the current one already exists.
$object->setData($name, $result[‘file’]); sets the new filename on the product for saving.