Diese Präsentation wurde erfolgreich gemeldet.

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

1

Teilen

Wird geladen in …3
×
1 von 50
1 von 50

Weitere Verwandte Inhalte

Ähnliche Bücher

Kostenlos mit einer 14-tägigen Testversion von Scribd

Alle anzeigen

Ähnliche Hörbücher

Kostenlos mit einer 14-tägigen Testversion von Scribd

Alle anzeigen

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

×