With millions of lines of code, an unconventional approach to MVC framework architecture, and unique concepts such as layout XML, Magento can be intimidating for the new developer and even difficult for experienced Magento developers. This talk aims to help developers find answers in the codebase by breaking down the technologies, design patterns, and module structure into intuitive chunks. Starting with a high level view of Magento's MVC implementation, a pre-developed module is dissected in order to demonstrate various areas of the framework as well as the application-level settings and features which can thwart (or aide!) developers.
Topics covered include the following:
* MVC theory as implemented by Magento, especially the thin-controller, fat-view concept
* Overall module architecture * Finding method definitions when grep won't work, aka "when __call() strikes"
* Identifying poor-performing code using native code profiling tools
* An infallible (well, nearly-infallible) flowchart for finding problematic code
* Essential developer preparations
2. Ben Marks
4.5 years doing Magento dev
2 years as a Magento U instructor
Happily employed at Blue Acorn in
Charleston, SC (we're hiring!)
Big fan of questions (ask away)
Who am I?
5. Who knows Magento?
Who hates Magento?
Who doesn't know Magento, but has been
told that they should hate it?
Who are you?
6. Who knows Magento?
Who hates Magento?
Who doesn't know Magento, but has been
told that they should hate it?
"Magento doesn't do anything very well" –
Harper Reed, php|tek, 2013
Who are you?
8. LOTS of business
LOTS of developer community members
LOTS of room for innovation
LOTS of flexibility
Layout XML
What makes Magento awesome?
9. LOTS of undocumented features &
conventions
LOTS of bad information out there
LOTS of architecture to scale
LOTS of flexibility
Layout XML
What makes Magento difficult?
10. Supressed error output (index.php):
Caching on by default (Admin Panel):
Disabled output (admin), disabled local code
pool (app/etc/local.xml)
Getting Started: Don't Forget!
13. Typical classname-to-path mapping, e.g.:
See app/Mage.php & lib/Varien/Autoload.php:
app/code/local/, app/code/community/, app/cod
e/core/, lib/
But... Magento is "all about options," so...
Typical Autoloading
Mage_Catalog_Model_Product_Type
Mage/Catalog/Model/Product/Type.php
14. Reading class group notation
Mage::getModel('catalog/product_type')
<config>
<global>
<models>
<catalog>
<class>Mage_Catalog_Model
Factory Methods & Class Groups
15. Allows for rewrites:
Mage::getModel('catalog/product_type')
<config>
<global>
<models>
<catalog>
<rewrite>
<product_type>New_Class
Factory Methods & Class Groups
16. Mage::getModel()
Mage::helper()*
Mage::app()->getLayout()->createBlock()
See Mage_Core_Model_Config
::getGroupedClassName()
That's the M, V, and H... but C works
differently
Factory Methods & Class Groups
20. Mage_Core_Model_Layout
Factory method for instantiating blocks
Global block registry
Effectively a singleton, accessed via:
$controller->getLayout()
Mage::app()->getLayout()
$block->getLayout()
The View: Layout Object
21. Blocks have two main workflows
Instantiation: _construct() & _prepareLayout()
Rendering:
toHtml(), _beforeToHtml(), _afterToHtml()
Blocks are generally responsible for
instantiating data models/collections –
important for view flexibility
The View: Blocks
22. Rendering is a waterfall down parent-child
relationships:
$parentBlock->getChildHtml('child');
$child->getChildHtml('etc');
//and so forth...
The View: Blocks
23. How do blocks get called in to scope for
rendering? In other words, how does stuff get
rendered?
The View: Blocks
24. Layout XML - up to the developer to use, not
use, mix as needed; keep controllers thin!
The View: Layout XML
25. Layout XML - up to the developer to use, not
use, mix as needed; keep controllers thin!
public function exampleAction()
{
$this->loadLayout()->renderLayout();
//$this->getResponse()->setBody('Hi!');
}
The View: Layout XML
26. Declared in module config.xml; all module
layout XML files are compiled always
Layout Update Handles are responsible for
limiting the directives for current scope
Full Action Name handle – the missing link
The View: Layout XML
27. <contacts_index_index />
<block /> - type, name, as, template
<reference /> - name
<remove /> - name
<update /> - handle
<action /> - method
action allows to call block public methods
The View: Layout XML
28. Layout update handles: applied via PHP;
top-level nodes in layout XML files
Block type is class group notation:
<block type="page/html_head">
<action method="addJs">
<file>example.js</file>
Mage_Page_Block_Html_Head->addJs('example.js');
The View: Layout XML
30. ...and this relationship is seen in templates as
well:
Required for rendering to work
The View: Layout XML
31. Parent-child block relationships can also be
set/unset using <action />:
<reference name="root">
<action method="unsetChild">
<child>content</child>
</action>
</reference>
Child exists, but "outside" of rendering flow
The View: Layout XML
32. Most important thing to understand:
Via layout XML any module can affect any view
through the full action name handle or other
applied handle (customer_logged_in, etc.)
Let's see some examples from catalog.xml
The View: Layout XML
33. Config XML is composed of the following:
app/etc/*.xml
app/etc/modules/*.xml
All active module config.xml
app/etc/local.xml
core_config_data table
Configuration XML
34. Confusingly accessed/evaluated/built; better
to learn it by application
Important top level nodes:
global
frontend & adminhtml
admin
default, websites, & stores; often, user-
configurable values here
Configuration XML
35. Website and store scopes are admin-
configurable, but affect config DOM
structure (System > Manage Stores)
Possible to declare same xpaths in multiple
files and in core_config_data table* (*for
default, websites, and stores)
Colliding xpath text values are overwritten
when merged
Configuration XML
36. Convenience method for reading correct
value for store scopes
Mage::getStoreConfig('foo/bar/baz');
//same as...
Mage::getConfig()->getNode(
'stores/[code]/foo/bar/baz'
);
Configuration XML
37. Sometimes it's the node name being
evaluated (e.g. module declaration); most of
the time it's the text node
Bottom line, it's all about the xpath and the
PHP which is evaluating it
Configuration XML
38. System XML is the quickest way to add user-
configurable fields to the admin panel
Default values can be set in files or added to
core_config_data via setup scripts
Let's look at Mage/Contacts/etc/system.xml
System XML
39. Magento CRUD:
Create & Update: save()
Read: load()
Delete: delete()
Data model CRUD works through resource
model (see Mage_Core_Model_Abstract)
The Model Layer: CRUD
40. Hybrid resource / data model classes
Filtering, sorting, etc. Lazy loaded.
Implement Countable &
IteratorAggregate, making it possible to do
this:
The Model Layer: Collections
41. Generally the best way to customize
Events are dispatched throughout core code
Allow to execute code uniformly (e.g. during
request dispatching) or during specific flow
of execution (catalog_product_load_after)
Observers
42. Varien_Object (lib/Varien/Object.php)
Basis of blocks and models; for
models, methods map to table columns or
attributes
get*, set*, uns*, & has*
$model->getFooBar()
reads from
$model->_data['foo_bar']
Missing code: when __call strikes
43. Caveat: nothing stops classes from defining
getters, setters, etc.
Don't var_dump() objects directly; use
Varien_Object->debug() to see
properties in _data
Missing code: when __call
strikes
44. The action and the template are the most
important aspects to deciphering layout
XML; not all blocks use template!
Find the block class via type
Check the definition to see if the method is
declared or not
A simple echo get_class($this) in the
template will suffice
Missing code: layout XML
45. Observer configuration can be found mainly
under the xpaths
global/events, frontend/events, and
adminhtml/events
Many events are dynamic
Multiple observers can be configured for the
same event
Missing code: Observers
46. When an install is not behaving as
expected, check for Mage, Varien, and Zend
namespaces outside of core or lib
Check for event observer configuration for
targeted CRUD and reques operations
Missing code: Miscellaneous
47. When content is being rendered with no
apparent source in template or entity
data, suspect translations, which can reside
in translate.csv, app/locale/, or core_translate
table; translate="" & __("Some String")
CMS pages, categories, and products all
have custom design settings (themes &
layout XML) which are stored in the
database
Missing code: Miscellaneous
48. Module code not executing.
Is config being merged? Enable developer
mode & clear cache. Error message indicates
everything is ok. 80% of all problems start
with config.*
Troubleshooting Process
49. Unexpected or missing theme-related content.
Reset the theme to default to rule out issues
from custom templates & layout XML; check
database for layout XML, template, and theme
settings. Check parent-child relationships.
Troubleshooting Process
50. Class XYZ is not behaving correctly.
Check for a config-based rewrite, an include
path override, or an event observer.
Collection class/view seems to be slow.
Ensure that the collection class is building
correct data and that models are not being
loaded iteratively.
Troubleshooting Process
51. Enable profiler in two places:
System > Configuration > Developer
index.php - uncomment Varien_Profiler::enable()
Rudimentary output; read from outside-in till
you get to the bottom-most entry with longest
execution time
Enable query profiler in config xml at
global/resources/default_setup/connection/profiler
Profiler
52. Enable TPH in admin:
System > Configuraration > Developer
Change scope from "Default"
Pretty ugly, and missing key info (such as
alias, name). Check out AOE_TemplateHints
v2.0 http://www.fabrizio-branca.de/magento-
advanced-template-hints-20.html
Template Path Hints