Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

How to Write Custom Modules for PHP-based E-Commerce Systems (2011)

5 Aufrufe

Veröffentlicht am

Explaining how to build extensions for Magento, Shopware, and OXID eShop

Veröffentlicht in: Internet
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

How to Write Custom Modules for PHP-based E-Commerce Systems (2011)

  1. 1. How to write Custom Modules for PHP-based E- Commerce Systems Dr. Roman Zenner
  2. 2. Roman Zenner •  Working as freelance trainer, author and developer since 2004 •  Has written two books on Magento •  Is in the process of writing a book on OXID eShop •  Publishes in various magazines
  3. 3. Initial thoughts •  Modularity a no-brainer in today’s ecommerce software •  There must be a way of extending classes or an event-listener system in order to integrate custom functionalities
  4. 4. Types of modules •  Encapsulate graphical (template) changes •  Provide additional information (e.g. for an article •  Special calculations •  Payment and shipping •  Other interfaces (ImpEx, etc.
  5. 5. Today‘s candidates •  Magento •  OXID eShop •  Shopware
  6. 6. http://www.flickr.com/photos/exey/3815327201
  7. 7. MVC-Model (extended)
  8. 8. Brief History •  First stable version released in spring 2008 •  Community Edition under OSL •  Professional and Enterprise Editions •  Based on Zend Framework and MySQL •  Relies heavily on EAV structure •  XML definitions •  Bought by eBay in 2011 (X.commerce) •  Current stable version: 1.6.1
  9. 9. Structure
  10. 10. Templates (1)
  11. 11. Templates (2)
  12. 12. Templates (2) <block type="page/html“ name="root" output="toHtml“ template="page/3columns.phtml"> <block type="page/html_header" name="header" as="header"> <block type="page/switch" name="store_language" as="store_language" template="page/switch/languages.phtml"/></block> </block> Template: /layout/page.xml <?php if(count($this->getStores())>1): ?> <div class="form-language“> <?php foreach ($this->getStores() as $_lang): ?> <?php $_selected = ($_lang->getId() == $this->getCurrentStoreId()) ? ' selected="selected"' : '' ?> <option value="<?php echo $_lang->getCurrentUrl() ?>"<?php echo $_selected ?>> <?php endforeach; ?> </div> <?php endif; ?> Template: /template/page/switch/languages.phtml
  13. 13. Drilling down (1) Example: How to get from the article name in the template to the database field?
  14. 14. Drilling down (2) 1.  Block: <block type="catalog/product_view" name="product.info" template="catalog/ product/view.phtml"> 2.  Template: /app/design/frontend/base/default/template/catalog/product/view.phtml 3.  Block class: Mage_Catalog_Block_Product_View 4.  Model: Mage_Catalog_Model_Product: public function getProduct() { if (!Mage::registry('product') && $this->getProductId()) { $product = Mage::getModel('catalog/product')->load($this->getProductId()); Mage::register('product', $product); } return Mage::registry('product'); }
  15. 15. Drilling down (3) 1.  Abstract class: Mage_Core_Model_Abstract 2.  Resource model: Mage_Core_Model_Mysql4_Abstract public function load($id, $field=null) { $this->_beforeLoad($id, $field); $this->_getResource()->load($this, $id, $field); $this->_afterLoad(); $this->setOrigData(); $this->_hasDataChanges = false; return $this; }
  16. 16. Modules (1)
  17. 17. Modules (2) IDE, please!
  18. 18. Brief History •  OS-Edition since late 2008. •  Based on own PHP-Framework & MySQL •  Recent version: 4.5.3
  19. 19. Features •  ADODB database abstraction layer •  Uses Smarty 2 (but Template Inheritance by Smarty 3) •  Block Inheritance •  Autoloader
  20. 20. Structure
  21. 21. Template Inheritance (1)
  22. 22. Template Inheritance (2) [{capture append="oxidBlock_content"}] [{assign var="oFirstArticle" value=$oView->getFirstArticle()}] [{/capture}] [{include file="layout/page.tpl" sidebar="Right"}] /out/azure/tpl/page/shop/start.tpl
  23. 23. Template Inheritance (3) <div id="content"> [{include file="message/errors.tpl"}] [{foreach from=$oxidBlock_content item="_block"}] [{$_block}] [{/foreach}] </div> [{include file="layout/footer.tpl"}] /out/azure/tpl/layout/page.tpl
  24. 24. Drilling down (1) Example: How to get from the article name in the Smarty-Template to the database field?
  25. 25. Drilling down (1) Example: How to get from the article name in the Smarty-Template to the database field?
  26. 26. Drilling down (2) •  Article detail page: /out/azure/tpl/page/details/inc/productmain.tpl [{block name="details_productmain_title"}] <h1 id="productTitle"><span itemprop="name"> [{$oDetailsProduct->oxarticles__oxtitle->value}] [{$oDetailsProduct->oxarticles__oxvarselect->value}]</span></h1> [{/block}] Scheme: [Object name]->[Table name]__[Field name]->value •  View controller: /views/details.php
  27. 27. Drilling down (3) public function render() { $myConfig = $this->getConfig(); $oProduct = $this->getProduct(); } public function getProduct() { $sOxid = oxConfig::getParameter( 'anid' ); $this->_oProduct = oxNew( 'oxarticle' ); if ( !$this->_oProduct->load( $sOxid ) ) { ... } }
  28. 28. Drilling down (4) public function load( $oxID) { $blRet = parent::load( $oxID); public function load( $sOXID) { //getting at least one field before lazy loading the object $this->_addField('oxid', 0); $sSelect = $this->buildSelectString( array( $this->getViewName().".oxid" => $sOXID)); return $this->_isLoaded = $this->assignRecord( $sSelect ); } /core/oxarticle.php /core/oxbase.php
  29. 29. Custom classes (1) •  Most view- and core classes can be overloaded •  Module are registered in backend •  Object instantiation via oxNew(): core/oxutilsobject.php oxArticle my_oxArticle our_oxArticle class my_oxArticle extends oxArticle class our_oxArticle extends my_oxArticle
  30. 30. Custom classes (2) •  This procedure becomes problematic when there is more than one new module wanting to extend a specific class. •  Solution: oxNew() dynamically creates transparent classes in the form of: [class-name]_parent •  This means that by means of the following structure, module classes can be chained: –  oxArticle => my_oxArticle&our_oxArticle
  31. 31. Plugins (1) •  Task: Write a module that displays the remaining time until X mas with each article. 1.  New module directory: /modules/xmas/ 2.  Publishing it via Admin:
  32. 32. Plugins (2) class xmasArticle extends xmasArticle_parent { public function getDaysLeft() { $time = mktime(0, 0, 0, 12, 25, 2011, 1) - time(); $days = floor($time/86400); return $days; } } <div>Only [{$oDetailsProduct->getDaysLeft()}] days left until Xmas!</div> /modules/xmas/xmasArticle.php /out/azure/tpl/page/details/inc/productmain.tpl
  33. 33. Brief History •  First stable version released in 2007. •  OS-Edition since October 2010. •  Since v.3.5 based on Enlight Framework (based on ZF) & MySQL •  MVC-Model •  Backend based on ExtJS 4 •  Templates based on Smarty 3 •  Recent version: 3.5.5
  34. 34. Enlight-Framework •  Basis functionalities are inherited from Zend Framework: •  Syntax and Workflow •  Request- and Response-Objects •  Action-Controller Design •  Rewritten Router / Dispatcher and View- Object optimised for performance and expandability •  Own plugin system based on events and hooks
  35. 35. Template-Structure
  36. 36. index.tpl {* Content section *} <div id="content"> <div class="inner”> {* Content top container *} {block name="frontend_index_content_top"}{/block} {* Sidebar left *} {block name='frontend_index_content_left'} {include file='frontend/index/left.tpl'} {/block} {* Main content *} {block name='frontend_index_content'}{/block} {* Sidebar right *} {block name='frontend_index_content_right'}{/block} <div class="clear">&nbsp;</div> </div> </div>
  37. 37. Template-Inheritance {extends file=”../_default/frontend/home/index.tpl} {block name=’frontend_index_content’ prepend} <h1>Hallo Welt</h1> {/block} SMARTY: Append – Prepend - Replace
  38. 38. Plugin-Directory Structure
  39. 39. Drilling down Example: How to get from the article name in the Smarty-Template to the database field?
  40. 40. Drilling down (2) •  Article detail page: templates_defaultfrontenddetailindex.tpl •  Part that displays article name in frontend •  Template-Path (frontend/detail/index.tpl) tells us where to find the corresponding controller. In this case: Shopware/Controllers/ Frontend/Detail.php – indexAction. •  Get article information from Model and assign to template •  Shopware()->Modules()->Articles() is a service locator to access the main article object that could be found at /engine/core/class/ sArticles.php •  sGetArticleById fetches a certain article by id from database and returns the result as an array for further processing
  41. 41. Plugins: Bootstrap <?php class Shopware_Plugins_Frontend_IPCDEMO_Bootstrap extends Shopware_Components_Plugin_Bootstrap { public function install() { // return true; } public static function onPostDispatch(Enlight_Event_EventArgs $args) { // Still empty } }
  42. 42. Plugins: Event public function install() { $event = $this->createEvent('Enlight_Controller_Action_PostDispatch','onPostDispatch'); $this-> subscribeEvent($event); $form = $this->Form(); $form->setElement('textarea', ’yourtext', array('label'=>’Text for left column’,'value'=>’Hello World')); $form->save(); return true; }
  43. 43. Plugins: Listener !public static function onPostDispatch(Enlight_Event_EventArgs $args) { $view = $args->getSubject()->View(); $config = Shopware()->Plugins()->Frontend()->IPCDEMO()->Config(); $view->pluginText = $config->yourtext; $view->addTemplateDir(dirname(__FILE__)."/Views/"); $view->extendsTemplate('plugin.tpl'); }
  44. 44. Plugins: Hooks <?php class Shopware_Plugins_Frontend_myHook_Bootstrap extends Shopware_Components_Plugin_Bootstrap { public function install() { $hook = $this->createHook( 'sArticles', 'sGetArticleById', 'onArticle', Enlight_Hook_HookHandler::TypeAfter, 0 ); $this->subscribeHook($hook); return true; } static function onArticle(Enlight_Hook_HookArgs $args) { } }
  45. 45. Summary • Each system employs a slightly different method of inserting custom functionalities • Layout and functional files are more or less encapsulated • No core-hacking required – still a need for testing!
  46. 46. ?
  47. 47. Thank you! Blog: romanzenner.com Skype: roman_zenner XING: xing.com/profile/Roman_Zenner Twitter: twitter.com/rzenner

×