Both Mаgentо and Prestаshоp provide possibilities to create custom modules to extend CMS functionalities. In this article we will try to describe main differences between the modules which are designed for these systems on example of Customer Images Uploader module for Magento and Prestashop.
Structural differences between Mаgentо and Prestаshоp modules
In spite of the fact that the structure of the modules in both CMSs follows the MVC(Model-View-Controller) concept, they still have certain major differences:
As illustrated on fig.1, Mаgentо and Prestаshоp modules have significant structural differences. Let’s take a closer look at the structure of the modules and differences between them.
Controllers. Controllers serve as a key part of the module providing connection to the model.
Of course, implementation of controllers in Magento and Prestashop modules are different.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
class Belvg_CustomerUploadImages_ImagesController extends Mage_Core_Controller_Front_Action { const _ERROR_UPLOAD = 1; public function uploadAction() { $helper_image = Mage::helper('uploadimages/image'); $helper = Mage::helper('uploadimages'); $helper_coupon = Mage::helper('uploadimages/coupon'); $uploaded_images = Mage::getModel('uploadimages/imagesList'); $session = Mage::getSingleton('customer/session'); if (!$session->isLoggedIn() AND !$helper->isEnabledGuestUploade()) { $result = array( 'error' => TRUE, 'message' => $this->__('Please, login') ); $this->getResponse()->setBody(Zend_Json::encode($result)); return; } if ($session->isLoggedIn() AND !$helper->isEnabledCustomerUploade()) { $result = array( 'error' => TRUE, 'message' => $this->__('Please, enable upload images for customer') ); $this->getResponse()->setBody(Zend_Json::encode($result)); return; } $customer_id = ($session->isLoggedIn()) ? $session->getCustomer()->getId() : 0; $product_id = Mage::app()->getRequest()->getParam('product_id'); if (!$product_id) { $result = array( 'error' => TRUE, 'message' => $this->__('Can\'t find a product requested') ); $this->getResponse()->setBody(Zend_Json::encode($result)); return; } if (!isset($_FILES['image'])) { $result = array( 'error' => TRUE, 'message' => $this->__('No files specified. Please make sure you have selected at least one.'), ); $this->getResponse()->setBody(Zend_Json::encode($result)); return ; } $result = array( 'success' => TRUE, 'message' => 'Thank you! You uploaded image(s) file(s).' ); $titles = $this->getRequest()->getParam('title'); $email = $this->getRequest()->getParam('email'); if ($customer_id > 0) { $email = $session->getCustomer()->getEmail(); } else if (strlen($email) > 0 AND $customer_id == 0) { $customer_model = Mage::getModel('customer/customer'); $customer_model->setStore(Mage::app()->getStore()); $customer_model = $customer_model->loadByEmail($email); $customer_id = $customer_model->getId(); } $count_upload_files = 0; for ($i = 0; $i < count($_FILES['image']['name']); $i++) { if ($_FILES['image']['error'][$i] != self::_ERROR_UPLOAD AND !empty($_FILES['image']['name'][$i])) { try { $file_meta_data = $helper_image->uploadImages($i); $helper_image->resize($file_meta_data['file']); $data = array( 'customer_id' => $customer_id, 'product_id' => $product_id, 'store_id' => Mage::app()->getStore()->getId(), 'status' => '0', 'title' => $titles[$i], 'file' => $file_meta_data['file'], 'file_content' => serialize($file_meta_data), 'show_in_product' => '0', 'show_in_customer' => '0', 'created_date' => date('Y-m-d H:i:s'), 'updated_date' => date('Y-m-d H:i:s'), 'guest_email' => $email, ); Mage::getModel('uploadimages/imagesList')->setData($data)->save(); $count_upload_files++; } catch (Exception $e) { $result = array( 'error' => TRUE, 'message' => $e->getMessage() ); } } } if ($count_upload_files == 0) { $result = array( 'error' => TRUE, 'message' => $this->__('No files specified. Please make sure you have selected at least one.'), ); } if (isset($result['success']) AND $helper->doNeedAdminNotify()) { $helper->notifyAdmin($product_id); } /*if (isset($result['success']) AND $helper_coupon->isEnableCoupon()) { //$uploaded_images->approvedImages($data); Mage::getModel('uploadimages/coupon')->giveCoupon($data); }*/ $this->getResponse()->setBody(Zend_Json::encode($result)); } |
Example: Magento module controller code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
class BelvgUploadImagesUploadModuleFrontController extends ModuleFrontController { const BELVG_PREFIX = 'belvg_cu_'; const BELVG_ENABLE = 1; const BELVG_DISABLE = 2; private $_tmpDir = ''; public function __construct() { parent::__construct(); $this->_tmpDir = _PS_IMG_DIR_; //$this->_tmpDir = _PS_MODULE_DIR_ . 'belvguploadimages/images/'; if (!is_dir($this->_tmpDir . 'belvguploaded')) { mkdir($this->_tmpDir . 'belvguploaded', 0777); $this->_tmpDir .= 'belvguploaded/'; } else { $this->_tmpDir .= 'belvguploaded/'; } require_once($this->module->getLocalPath() . 'classes/ExtendedFileUploader.php'); //require_once($this->module->getLocalPath() . 'classes/UploaderImages.php'); } public function run() { $formated_data = $this->_getFormattedData(); $uploader = new ExtendedFileUploader(); $result = $uploader->handleUpload($formated_data, FALSE); $want_notify_admin = $uploader->getConfigurationParam('notify_admin'); $has_success_upload = $this->_hasSuccessUpload($result); if ($want_notify_admin == self::BELVG_ENABLE AND $has_success_upload == TRUE) { $email = $uploader->getConfigurationParam('send_to'); $template_index = $uploader->getConfigurationParam('template_' . Context::getContext()->language->id); $template = $this->_getTemplate($template_index); $this->sendEmailToAdmin($email, $template, $result['number']); } die(json_encode($result)); } /*other code*/ } |
Example: Prestashop module controller code
Http addresses, which query the controller, are also different:
http://belvg.info/demo/customeruploadimages/index.php/uploadimages/images/upload/ – The example of an http address for Magento.
http://belvg.info/demo/prestashop16/uploadimages/module/belvguploadimages/upload?action=browse&id_product=3&id_customer=0&id_shop=1 – The example of an http-address for Prestashop.
Magento Webdesign
Take your online store to the next level with BelVG Magento Webdesign
Visit the pageModels. In Magento models are represented with the classes in the Models catalog. They are divided into business-models and resource-models. It is also possible to distinguish a collection-model which is a separate type. Business-model is designed for processing data, which are retrieved from the database. However this model does not send requests to the database. It is inherited from the class Mage_Core_Model_Abstract.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Belvg_CustomerUploadImages_Model_ImagesList extends Mage_Core_Model_Abstract { protected function _construct() { $this->_init('uploadimages/imagesList'); } public function approvedImages($data) { //Mage::getModel('uploadimages/coupon')->giveCoupon($this, $data); Mage::getModel('uploadimages/coupon')->giveCoupon($data); } } |
Example: Magento business-model code
Resource-model is responsible for working with the database. It provides interface for retrieving data from the database. Resource-model is either inherited from the class Mage_Core_Model_Mysql4_Abstract or from the class Mage_Core_Model_Resource_Abstract .
1 2 3 4 5 6 7 |
class Belvg_CustomerUploadImages_Model_Mysql4_ImagesList extends Mage_Core_Model_Mysql4_Abstract { protected function _construct() { $this->_init('uploadimages/images', 'entity_id'); } } |
Example: Mаgentо resource-model code
Collections request database to retrieve multiple table rows. Collections are inherited either from the class Mage_Core_Model_Mysql4_Collection_Abstract or from the class Mage_Core_Model_Resource_Collection_Abstract.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
class Belvg_CustomerUploadImages_Model_Mysql4_ImagesList_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract { private $_approvedImages = array(); protected function _construct() { $this->_init('uploadimages/imagesList'); } protected function _alias() { if (strpos($this->getSelect()->__toString(), 'main_table')) { $alias = 'main_table'; } else { $alias = 'e'; } return $alias; } public function setSKU() { $product_collection = Mage::getModel('catalog/product')->getCollection(); $table = $product_collection->getResource()->getEntityTable(); $this->getSelect()->joinLeft( array('product' => $table), 'product.entity_id = ' . $this->_alias() . '.product_id', array('sku') ); } /*other code*/ } |
Example: Magento collection code
Prestashop model is represented with the classes from the directory prestаshоp/classes/. Although Prestаshоp classes from the directory prestаshоp/classes/ may also have a much wider application rather than using them as a model (for example, the directory prestаshоp/classes/ contains controllers), but in general, we can say that these classes are models. Catalog classes are created in the module root directory. This catalog contains models related to this module.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
class ExtendedFileUploader extends FileUploader { const BELVG_PREFIX = 'belvg_cu_'; const BELVG_ENABLE = 1; const BELVG_DISABLE = 2; /*fields*/ public function __construct(array $allowedExtensions = array(), $sizeLimit = 10485760) { $allowedExtensions = array_map('strtolower', $allowedExtensions); $this->allowedExtensions = $allowedExtensions; if (empty($this->allowedExtensions)) { $this->allowedExtensions = array('jpg', 'png'); } $this->sizeLimit = $sizeLimit; $this->module = new BelvgUploadImages(); $this->file = new ExtendedQqUploadedFileXhr(); } public function handleUpload($formated_data = array(), $flag_upload_to_product = TRUE) { $result = array(); if (!$this->file) { $result[] = array('type' => 'error', 'message' => Tools::displayError('No files were uploaded.')); } $is_valid_email = $this->_validEmail($formated_data); if (!$is_valid_email) { $email = $this->_getEmail($formated_data); $error = $email . ' - is not a valid email address.'; $result[] = array('type' => 'error', 'message' => Tools::displayError($error)); } $this->file->initFormatedData($formated_data, $flag_upload_to_product); if (empty($result)) { $result = $this->_copyImageToTmpDir(); $result['number'] = $this->_getNumberOfImagesUploaded($result); $result['length'] = count($result) - 1; } return $result; } /*other code*/ } |
Example: Prestаshоp class code
View. View is used to display information. The implementation of View in Mаgentо and Prestаshоp modules has the most significant differences. In Mаgentо the View component is comprised of the following 3 elements: Block, Template and Layout.
Block. Block is a class, which is required to output information (template). The basic class for Block is Mage_Core_Block_Template, as well as some other classes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
class Belvg_CustomerUploadImages_Block_Form extends Belvg_CustomerUploadImages_Block_Abstract { protected function _construct() { parent::_construct(); } public function getPostUrlForm() { return $this->getUrl('uploadimages/images/upload'); } public function getProductId() { $product = Mage::registry('current_product'); if ($product) { return $product->getId(); } return 0; } } |
Example: Magento block code
Magento Custom Development
Take your online store to the next level with BelVG Magento Custom Development
Visit the pageTemplate. Templates are represented with .phtml files. These files contain the html markup of that part of the page, which is rendered by the block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?php if($this->canDisplayTemplate() AND $this->getCollectionSize() > 0): ?> <?php $image_helper = $this->helper('uploadimages/image'); ?> <?php $images = $this->getImages();?> <div id="jFlowCredits"></div> <input type="hidden" id="slider_height_hidden" value="<?php echo $this->getHeightSlider();?>"/> <input type="hidden" id="slider_width_hidden" value="<?php echo $this->getWidthSlider();?>"/> <div id="container" style="width:<?php echo $this->getWidthSlider();?>;height:<?php echo $this->getHeightSlider();?>;"> <div id="mySlides"> <?php $counter = 1; ?> <?php foreach($images as $image): ?> <div id="slide"> <img style="width:<?php echo $this->getWidthSlider();?>;height:<?php echo $this->getHeightSlider();?>" src="<?php echo $image_helper->getImageUrl($image['file']);?>" alt="Slide <?php echo $counter; ?>" /> </div> <?php $counter++;?> <?php endforeach; ?> </div> <div id="myController"> <?php foreach($images as $image): ?> <span class="jFlowControl"></span> <?php endforeach; ?> </div> <span class="jFlowPrev"><div></div></span> <span class="jFlowNext"><div></div></span> </div> <?php endif; ?> |
Example: Magento template code
Layout. Layout is an .xml file that contains page structure and connects templates and blocks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0"?> <layout> <catalog_product_view> <reference name="head"> <action method="addJS" ifconfig="uploadimages/settings/enabled" value="1"><script>belvg/jquery-1.7.2.min.js</script></action> <action method="addJS" ifconfig="uploadimages/settings/enabled" value="1"><script>belvg/jqueryQw.noconflict.js</script></action> <action method="addJS" ifconfig="uploadimages/settings/enabled" value="1"><script>belvg/uploadimages/jquery.uploadfields.js</script></action> <action method="addJS" ifconfig="uploadimages/settings/enabled" value="1"><script>belvg/uploadimages/load.js</script></action> <action method="addJS" ifconfig="uploadimages/settings/enabled" value="1"><script>belvg/uploadimages/scripts/jflow.plus.js</script></action> <action method="addCSS" ifconfig="uploadimages/settings/enabled" value="1"><stylesheet>css/belvg/styles/jflow.style.css</stylesheet></action> <action method="addCSS" ifconfig="uploadimages/settings/enabled" value="1"><stylesheet>css/belvg/styles/style.css</stylesheet></action> <action method="addCSS" ifconfig="uploadimages/settings/enabled"><stylesheet>css/belvg/uploadimages.css</stylesheet></action> </reference> <reference name="content"> <block type="uploadimages/form" name="uploadimages.form" template="uploadimages/form.phtml"></block> <block type="uploadimages/slider" name="uploadimages.slider" template="uploadimages/slider.phtml"></block> </reference> </catalog_product_view> </layout> |
Example: Magento layout code
Layout and Template are located in the directory app/design/[package name]/[theme name]. Package name – this is the current package, theme name – the current theme. If package name and theme name are not specified, then the current package is base, and the current theme is theme.
There are also smarty-templates in Prestashop that contain html and smarty tags.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<div class="clearfix blockslider"> <h2 class="slider_h2">{$header}</h2> <div class="slider_body"> <div id="jFlowCredits"></div> <div id="container" style="width:{$slider_width}px;height:{$slider_height}px;"> <div id="mySlides"> {foreach $images as $image} <div id="slide"> <a href="{$image.big}" class="fancybox slide-image-fancybox"> <img src="{$image.thickbox}" alt="Slide " class="slide-image" /> </a> </div> {/foreach} </div> <div id="myController"> {foreach $images as $image} <span class="jFlowControl"></span> {/foreach} </div> {if count($images) > 1} <span class="jFlowPrev"><div></div></span> <span class="jFlowNext"><div></div></span> {/if} </div> </div> </div> |
Example: Prestashop template code
Module templates are located in the directory modules/belvguplоаdimаges/view/templates. Instead of belvguplоаdimаges there can be used directories of any other module. But there are no other similarities with Magento for implementation of the View component. Prestashop does not provide any specialized classes for template rendering. A template can be used in the module controller in special hook methods.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
public function hookDisplayRightColumnProduct($params = array()) { $html = ''; $settings = $this->_getSettings(); $logged = Context::getContext()->customer->logged; $rewrite_url = (int)(Configuration::get('PS_REWRITING_SETTINGS')); $customer = Context::getContext()->customer; $params = array( 'action' => 'browse', 'id_product' => Tools::getValue('id_product'), 'id_customer' => (Context::getContext()->customer->logged) ? Context::getContext()->customer->id : 0, 'id_shop' => Context::getContext()->shop->id ); $action_url = $this->_getControllerURL($this->name, 'upload', $params); $params = array( ); $instagram_url = $this->_getControllerURL($this->name, 'instagram', $params); $upload_for_customer = ($settings['upld_customer'] == self::BELVG_ENABLE AND $logged) ? TRUE : FALSE; $upload_for_guest = ($settings['upld_guest'] == self::BELVG_ENABLE AND !$logged) ? TRUE : FALSE; $email_required = ($settings['email_require'] == self::BELVG_ENABLE) ? TRUE : FALSE; $email_enable = (!$logged) ? TRUE : FALSE; $this->smarty->assign(array( 'filename_text' => $this->l('No file selected'), 'choosefile_text' => $this->l('Choose File'), 'alt_loading_text' => $this->l("Loading..."), 'loading_text' => $this->l("Please wait..."), 'close_text' => $this->l("close"), 'incoming_message' => $this->l("Message"), 'upload_for_customer' => $upload_for_customer, 'upload_for_guest' => $upload_for_guest, 'email_required' => $email_required, 'email_enable' => $email_enable, 'logged' => $logged, 'id_lang' => Context::getContext()->language->id, 'loading_url' => __PS_BASE_URI__ . 'modules/belvguploadimages/images/ajax-loader-tr.gif', 'action_url' => $action_url, )); $html = $this->display(__FILE__, 'views/templates/frontend/upload.tpl'); return $html; } |
Example: Using template in the module Custom Images Uploader for Prestashop
P.S. As we have illustrated by the module Customer Uploader Images, the implementation of Mаgentо and Prestаshоp modules has significant differences. But in spite of this, it is possible to create extensions for both systems, which can perform similar tasks.