Modul-Entwicklung für Magento, OXID eShop und Shopware (2013)
1. How
to
write
Custom
Modules
for
PHP-based
E-
Commerce
Systems
Roman
Z.
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. 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. Types
of
modules
• Encapsulate
graphical
(template)
changes
• Provide
additional
information
(e.g.
for
an
article
• Special
calculations
• Payment
and
shipping
• Other
interfaces
(ImpEx,
etc.)
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
de^initions
• Bought
by
eBay
in
2011
(X.commerce)
• Current
stable
version:
1.7.0.2
26. 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 ) ) {
...
}
}
27. 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
28. 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
29. 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
30. 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'
)
31. 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
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:
4.0.7
34. 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
39. Drilling
down
Example:
How
to
get
from
the
article
name
in
the
Smarty-‐Template
to
the
database
^ield?
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
^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
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. 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;
}
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. 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!