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.

Modul-Entwicklung für Magento, OXID eShop und Shopware (2013)

8 Aufrufe

Veröffentlicht am

Unterschiede und Gemeinsamkeiten der bekanntesten drei PHP-E-Commerce-Lösungen

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

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

Modul-Entwicklung für Magento, OXID eShop und Shopware (2013)

  1. 1. How  to  write  Custom   Modules  for  PHP-­based  E-­ Commerce  Systems   Roman  Z.  
  2. 2. Roman  Zenner   •  Working  as  freelance  trainer,  author  and   consultant  since  2004   •  Has  written  three  books  on  Magento  and   OXID  eShop   •  Is  in  the  process  of  writing  a  “cookbook”   on  OXID  eShop  with  Joscha  Krug   •  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. 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  de^initions   •  Bought  by  eBay  in  2011  (X.commerce)   •  Current  stable  version:  1.7.0.2  
  8. 8. Structure  
  9. 9. Templates  (1)  
  10. 10. Templates  (2)  
  11. 11. 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
  12. 12. Drilling  down  (1)   Example: How to get from the article name in the template to the database field?
  13. 13. 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'); }
  14. 14. 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; }
  15. 15. Modules  
  16. 16. Brief  History   •  OS-­‐Edition  since  late  2008.   •  Based  on  own  PHP-­‐Framework  &  MySQL   •  Recent  version:  4.7.3  
  17. 17. Features   •  ADODB  database  abstraction  layer   •  Uses  Smarty  2  (but  Template  Inheritance  by   Smarty  3)   •  Block  Inheritance   •  Autoloader  
  18. 18. Structure  
  19. 19. Template  Inheritance  (1)  
  20. 20. 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
  21. 21. 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
  22. 22. Drilling  down  (1)   Example:     How  to  get  from  the  article  name  in   the  Smarty-­‐Template  to  the  database  ^ield?  
  23. 23. 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: /application/controller/details.php
  24. 24. 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 ) ) { ... } }
  25. 25. 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 ); } /application/models/oxarticle.php /core/oxbase.php
  26. 26. 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
  27. 27. Custom  classes  (2)   •  This  procedure  becomes  problematic  when  there  is  more   than  one  new  module  wanting  to  extend  a  speci^ic  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  
  28. 28. 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  metadata.php  (used  to   be  via  Admin)   'extend' => array( 'oxarticle' => ‘xmas/xmasArticle' )
  29. 29. Plugins  (2)     class  xmasArticle  extends  xmasArticle_parent   {          public  function  getDaysLeft()          {                  $time  =  mktime(0,  0,  0,  12,  25,  2011,  1)  -­‐  time();                  $days  =  ^loor($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
  30. 30. 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:  4.0.7  
  31. 31. Enlight-­‐Framework   •  Basis  functionalities  are  inherited  from  Zend   Framework:     •  Syntax  and  Work^low   •  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  
  32. 32. Template-­‐Structure  
  33. 33. 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>
  34. 34. Template-­‐Inheritance   {extends file=”../_default/frontend/home/index.tpl} {block name=’frontend_index_content’ prepend} <h1>Hallo Welt</h1> {/block} SMARTY: Append – Prepend - Replace
  35. 35. Plugin-­‐Directory  Structure  
  36. 36. Drilling  down   Example:     How  to  get  from  the  article  name  in   the  Smarty-­‐Template  to  the  database  ^ield?  
  37. 37. 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  ^ind  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  
  38. 38. 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 } }
  39. 39. 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; }
  40. 40. 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'); }
  41. 41. 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) { } }
  42. 42. Summary   •   Each  system  employs  a  slightly  different  method  of          inserting  custom  functionalities   •   Layout  and  functional  ^iles  are  more  or  less   encapsulated   •   No  core-­‐hacking  required  –  still  a  need  for  testing!  
  43. 43. Thank  you!   Blog:  romanzenner.com   Skype:  roman_zenner   XING:  xing.com/pro^ile/Roman_Zenner   Twitter:  twitter.com/rzenner  
  44. 44. MVC-­‐Model  (extended)  

×