Download as pdf or txt
Download as pdf or txt
You are on page 1of 0

Magento Extension

Developers Guide























Copyright 2012 X.commerce, Inc.
All rights reserved. No part of this Guide shall be reproduced, stored in a retrieval
system, or transmitted by any means, electronic, mechanical, photocopying, recording,
or otherwise, without written permission from X.commerce, Inc. 06-01-2012
Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. iii
Table of Contents

Magento Overview......................................................................................................... 1
Overview ...................................................................................................................... 1
Code ............................................................................................................................ 2
Code Pools ............................................................................................................................ 2
Module code structure ......................................................................................................... 3
Magento Coding Standards ................................................................................................ 3
Design ......................................................................................................................... 3
Themes .................................................................................................................................. 4
Theme Fall-back ................................................................................................................... 4
Configuration ............................................................................................................... 5

An Example Magento Extension .................................................................................. 5
Extension overview ...................................................................................................... 5
Getting Started: Code Setup and Configuration .......................................................... 5
Selecting our code pool ....................................................................................................... 5
Creating our code structure ................................................................................................ 6
Creating our configuration files .......................................................................................... 8
Checking our module visibility .......................................................................................... 11
Getting Started: Design Setup ................................................................................... 12
Creating our template and layout structures .................................................................. 13
Auxiliary files ....................................................................................................................... 15
Development: The Front End ..................................................................................... 16
Preparing our database schema ...................................................................................... 17
Preparing our models to work with data and business logic ....................................... 20
Specifying our routes and request flow .......................................................................... 23
Preparing our output .......................................................................................................... 25
Preparing our helpers ........................................................................................................ 33
Adding sample data ........................................................................................................... 39
Events .................................................................................................................................. 41
Development: The Admin Panel ................................................................................ 44
Preparing Admin panel configuration .............................................................................. 44
Specifying our routes and request flow .......................................................................... 47
iv Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
Preparing our output .......................................................................................................... 53
Preparing our helpers ........................................................................................................ 69
Download the Extension ............................................................................................ 70

Appendix A: Building a Trusted Extension ............................................................... 71
Overview .................................................................................................................... 71
Extension Structure and Configuration ...................................................................... 71
Using the Database, Resources and Data ................................................................. 72
Working with Output .................................................................................................. 72
Magento Components and Coding Style ................................................................... 72

Appendix B: Magento Best Practices ........................................................................ 73
Overview .................................................................................................................... 73
Extension Structure and Configuration ...................................................................... 73
Using the Database, Resources, and Data ................................................................ 73
Working with Output .................................................................................................. 74
Magento Components and Coding Style ................................................................... 74

Appendix C: Further References ............................................................................... 76




Table of Figures
Figure 1: Magento core application structure .................................................................. 1
Figure 2: Our extension folder structure .......................................................................... 7
Figure 3: MVC design pattern for Magento ................................................................... 12
Figure 4: Frontend file/folder structure .......................................................................... 14
Figure 5: Admin panel file/folder structure ..................................................................... 15
Figure 6: Our Admin panel block structure .................................................................... 56

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 1
Magento Overview
Overview
Magento is a feature-rich eCommerce platform built on open-source technology that
provides on-line merchants with unprecedented flexibility and control over the look,
content and functionality of their eCommerce store. Magentos intuitive Administration
interface features powerful marketing, search engine optimization and catalog-
management tools to give merchants the power to create sites that are tailored to their
unique business needs.
Magento is an MVC-based application written in PHP which is divided into groups of
modules. Each module separates areas of functionality from others and helps to
minimize dependencies between itself and other modules. The following is a diagram of
the Magento core application structure:

Figure 1: Magento core application structure

2 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
Magento is an MVC-based application which means its code and design elements are
separated. Also, Magento is configuration-based, which means it uses configuration
files rather than naming conventions for its settings.
Code
All code files are grouped together based on functionality called modules, in Magento.
Modules are the core of Magento. Every action on the site, frontend or backend, goes
through a module. Modules act as containers for one or more of the following:
Settings
Database schemas
Database data
Rendering objects
Utility helpers
Data models
Action controllers.
A module can be made of all seven of these things, or just one.
Modules are further grouped into code pools, which allow for safe and easy
customization and extending of its core functionality. Using code pools, developers
ensure that native functionality can be upgraded with new releases of the core product,
and that it is protected from any changes that a merchant wants to make to the
platform.
Code Pools
Magento contains three code pools:
The core code pool contains the base Magento application. Only Magento core
product developers should change files in this code pool.
The community code pool contains files that have been extended from
the core code pool and that can apply to several different instances of Magento.
Most extension developers make their changes and additions in this code pool
because their extensions can be used by any merchant who installs their
extension.
The local code pool contains files that have been extended from the core code
pool but that will only be used by a specific instance of Magento. The local code
pool is used by merchants who want to customize their platforms, but do not
want to make their customizations available to the community at large.


Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 3
Module code structure
As mentioned above code files are grouped together based on functionality into
modules. Module can consist of the following components:
Blocks: Responsible for preparing data for display in templates
Models: Implement business logic
Resource Models: Provide an access layer to data for the extension
Controllers: Contain methods called actions which process web server requests
that correspond to a specific module.
Configuration: Module-specific XML configuration files that tell the application
how the module interacts with it
Helpers: Auxiliary classes that implement commonly used business
logic. Examples: forms, validators, formatters
Schema SQL Scripts: SQL scripts that implement schema changes to a specific
module
Data SQL Scripts: Scripts that manipulate the data for the SQL schema of a
module. Pay strict attention to this as different upgrades were added in Magento
Enterprise Edition (EE) 1.11 and Magento Community Edition (CE) 1.6
Magento Coding Standards
We consider Magento's coding standards to be required prerequisite reading for any
developers who wish to work with the platform.
Design
To exactly control the look and feel of each store in your Magento installation, Magento
allows you to create themes. Related themes are grouped together in design packages.
Each store in your Magento installation can use its own theme, or they can all share a
single theme, or some combination of each.
A design package is a collection of related themes. You can have any number of design
packages installed, but there must always be at least one. When installed, Magento has
a special package named the base package.
Themes inside a design package contain the actual files that determine the visual
output and frontend functionality of your store. A theme can belong to only one design
package. By convention, each design package must contain a default theme.
Additionally, a design package can contain any number of variations on that default
theme - called variously non-default themes or theme variants.


4 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
Themes
A Magento theme is composed of different file types (layout, template, locale) and/or
skin files (CSS, images, theme-specific J avaScript) that create the visual experience of
your store. These files reside in two main directories in your Magento file system:
app/ desi gn directory Files that control how the page templates are rendered
ski n directory Files that control the visual aspects of the theme---CSS,
images, etc.
Theme files are organized into the following subdirectories:
Layout: Contains the basic XML files that define block structure for different
pages as well as control meta information.
Template: Contains the PHTML files that contain xHTML markups and any
necessary PHP to create logic for visual presentation. Some templates are page
templates and some are block templates.
Locale: Contains simple CSV text documents organized on a per language basis
containing translation strings (as name-value pairs) for all text produced by
Magento (e.g., for interface elements and messages, not products and
categories)
Skin files are organized into the following subdirectories:
CSS: Contains the CSS files used to control visual styling of the website
Images: Contains all images used by the theme
JS: Contains theme-specific J avaScript routines and callable functions.
Theme Fall-back
Magento's theme hierarchy allows developers to localize their themes, changing or
adding only those files that are actually necessary for a custom theme. Any files that
are not customized in the new theme are pulled from the default theme and base
package.
1. If a custom theme is specified, the application looks for the requested file in:
1. app/design/frontend/custom_package/custom_theme
2. skin/frontend/custom_package/custom_theme
2. If the file is not found in the custom theme, the application moves up a level and
looks for it in:
1. app/design/frontend/custom_package/default
2. skin/frontend/custom_package/default
3. If not found in the default , the application looks for the requested file in:
1. app/design/frontend/base/default
2. skin/frontend/base/default
4. If not found, a rendering error will occur.

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 5
Both a design package and theme can be assigned on either the website level and/or
store view level through the Magento Admin panel.
Configuration
Modules are defined as being on or off in an XML configuration system located in
app/ et c/ modul es/ . Those configuration files also indicate which code pool the
module is placed in, and which modules it depends on.
Each module can specify its own settings in an XML file as well, located under the
modules et c/ directory.
An Example Magento Extension
Extension overview
We will illustrate best practices and restrictions for developing extensions using an
example "News Management" extension. This extension will allow a merchant to
manage news posts in the Admin panel (News >Manage News) and then view the
posts on the frontend using a link in the footer. If you want to skip this example, you can
see the recommendations in list format in Appendix A at the end of this document.
Getting Started: Code Setup and Configuration
Selecting our code pool
Before we start writing code, we have to prepare its structure. First we need to decide
which code pool our extension will be stored in.

Extension Best Practices
Code for extensions that are intended for community use should be stored in the communi t y code
pool.
In order to improve readability and make the relationship between templates and the module code more
clear, templates should be stored in separate folders that are named with the module namespace and
name. For example, in our extension we will create the folder structure for frontend templates so that the
folder magent ost udy will include the folder news where all our templates will be placed. And we
place the newly created folder magent ost udy into f r ont end/ base/ def aul t / t empl at e
according to the restrictions above.
For similar reasons, layouts should be named with the module namespace and name. For example, in
our extension we will name our frontend layout magent ost udy{{_news. xml }} and place it into
f r ont end/ base/ def aul t / l ayout .
Be advised that native layouts don't include a namespace in their names. For example, the layout related
to the core module Mage_Cat al og is named just cat al og. xml , not mage_cat al og. xml

6 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
Next, we need to decide on a namespace and a name for our extension. We will use a
namespace of Magent ost udy and we will name our extension News.
Creating our code structure
Now that we have chosen a code pool, namespace, and extension name let's start
creating its basic file/folder structure for our code. Whether or not you include the other
folders depends on what your extension does. For example, if your extension doesn't
need any controllers, you won't need the cont r ol l er folder.
See the following diagram for our extension folder structure:

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 7

Figure 2: Our extension folder structure


8 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
Creating our configuration files
Next, we need to let Magento know that our module exists and is active. We also need
to configure the module's content. To do this we need to create two configuration files,
an application-specific file and a module-specific file:
Initial configuration file Module configuration file
Located in app/ et c/ modul es which
already exists in native Magento
Mandatory
Is named by module namespace and
name (Magent ost udy_News. xml )
Tells Magento which code pool our
extension is stored in and whether it's
enabled or not.
Also tells Magento which modules our
extension depends on to function
properly.
Located in app/ code/ <code
pool >/ <namespace
name>/ <modul e name>/ et c/
Mandatory
Named conf i g. xml
Specifies which blocks, models,
helpers, routes, etc the
extension will contain.
Application configuration XML
Because we know our extension will be stored in the communi t y code pool and that it will
be active, the only thing that is left to decide is which modules it will depend on. We do
not plan on rewriting any existing core modules, but we do want to add our extension to
the Admin panel. To allow for this, our module will depend on the
core Mage_admi nht ml module.

Extension Best Practices
Always be sure to check your module's dependencies because a missing or incorrectly defined
dependency can cause your extension to produce fatal errors.
Only necessary dependencies should be specified because they influence the loading sequence of the
application's core modules. Unnecessary dependencies should not be included

Magentostudy_News.xml
<?xml ver si on=" 1. 0" ?>
<! - -
/ **
* Modul e i ni t i al conf i g
*
* @aut hor Magent o
*/
- - >
<conf i g>
<modul es>

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 9
<Magent ost udy_News>
<act i ve>t r ue</ act i ve>
<codePool >communi t y</ codePool >
<depends>
<Mage_admi nht ml / >
</ depends>
</ Magent ost udy_News>
</ modul es>
</ conf i g>
Module configuration XML
Now that we have set up our initial configuration, we need to set up our module-specific
configuration which will specify the structural elements (models, classes, helpers,
database tables and others) that the extension will use.
Our extension will add two pages to the frontend:
One page that will contain a list of news posts
A second page that show each individual news post.
The extension will also change the database to store data, and add the ability to
manage news posts from the Magento Admin.
Based on these needs, we will need to define several items in our configuration file. We
will revisit the different parts of this file when we discuss the implementation of the
extension's features; for now, see the code snippet below for the configuration we will
use.
config.xml
<?xml ver si on=" 1. 0" ?>
<! - -
/ **
* Modul e conf i gur at i on
*
* @aut hor Magent o
*/
- - >
<conf i g>
<modul es>
<Magent ost udy_News>
<ver si on>1. 0. 0. 0. 1</ ver si on>
</ Magent ost udy_News>
</ modul es>
<gl obal >
<model s>
<magent ost udy_news>
<cl ass>Magent ost udy_News_Model </ cl ass>
<r esour ceModel >news_r esour ce</ r esour ceModel >
</ magent ost udy_news>
<news_r esour ce>
<cl ass>Magent ost udy_News_Model _Resour ce</ cl ass>

10 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
<ent i t i es>
<news>
<t abl e>magent ost udy_news</ t abl e>
</ news>
</ ent i t i es>
</ news_r esour ce>
</ model s>
<hel per s>
<magent ost udy_news>
<cl ass>Magent ost udy_News_Hel per </ cl ass>
</ magent ost udy_news>
</ hel per s>
<bl ocks>
<magent ost udy_news>
<cl ass>Magent ost udy_News_Bl ock</ cl ass>
</ magent ost udy_news>
</ bl ocks>
<r esour ces>
<magent ost udy_news_set up>
<set up>
<modul e>Magent ost udy_News</ modul e>
<cl ass>Mage_Cor e_Model _Resour ce_Set up</ cl ass>
</ set up>
</ magent ost udy_news_set up>
</ r esour ces>
<event s>
<bef or e_news_i t em_di spl ay>
<obser ver s>
<magent ost udy_news>
<cl ass>magent ost udy_news/ obser ver </ cl ass>
<met hod>bef or eNewsDi spl ayed</ met hod>
</ magent ost udy_news>
</ obser ver s>
</ bef or e_news_i t em_di spl ay>
</ event s>
</ gl obal >
<f r ont end>
<r out er s>
<magent ost udy_news>
<use>st andar d</ use>
<ar gs>
<modul e>Magent ost udy_News</ modul e>
<f r ont Name>news</ f r ont Name>
</ ar gs>
</ magent ost udy_news>
</ r out er s>
<l ayout >
<updat es>
<magent ost udy_news>
<f i l e>magent ost udy_news. xml </ f i l e>
</ magent ost udy_news>
</ updat es>
</ l ayout >
</ f r ont end>
<Admi n>
<r out er s>
<admi nht ml >

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 11
<ar gs>
<modul es>
<Magent ost udy_News
bef or e=" Mage_admi nht ml " >Magent ost udy_News_admi nht ml </ Magent ost udy_News>
</ modul es>
</ ar gs>
</ admi nht ml >
</ r out er s>
</ Admi n>
<admi nht ml >
<l ayout >
<updat es>
<magent ost udy_news>
<f i l e>magent ost udy_news. xml </ f i l e>
</ magent ost udy_news>
</ updat es>
</ l ayout >
</ admi nht ml >
<def aul t >
<news>
<vi ew>
<enabl ed>1</ enabl ed>
<i t ems_per _page>20</ i t ems_per _page>
<days_di f f er ence>3</ days_di f f er ence>
</ vi ew>
</ news>
</ def aul t >
</ conf i g>
Checking our module visibility
At this point, we have set up our initial and module-specific configuration settings. If we
have done everything correctly, Magento should "see" our module. We can check this in
the Admin panel.
Enter the Admin panel and navigate to System >Configuration >Advanced >Disable
Modules Output to find our module named "Magentostudy_News".

Note
You may not see your module because of caching. There are two ways to resolve this:
Clear the cache every time you make a change.
Disable caching during the development process.
To clear the cache or change its settings, enter the Admin panel, navigate to System >Cache Management
and use the "Flush Magento Cache" button.
To disable the cache, select all of the cache types, select the "Disable" from the dropdown, and press "Submit".



12 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
Getting Started: Design Setup
Now that we have got our code structure created and our extension configured, we will
focus on creating our design structure. While Magento follows the basic ideas of the
MVC design pattern, the "View" component is quite different from the Zend standard.
Instead of a single file that receives data from models and logic from controllers, views
in Magento are broken into Blocks, Layouts and Templates.

Figure 3: MVC design pattern for Magento
We have already prepared a structure for our blocks (See the Bl ock folder in our code
setup). Next we need to prepare the structure for our layouts and templates. We put
them in the design folder. Because of the ability to use different themes in Magento
and its fallback mechanism, all extension related theme files are placed in
base/ def aul t package for frontend and def aul t / def aul t package for

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 13
admi nht ml . This will allow extension to work correctly and independently on for theme
chosen in Admin panel.

Extension Best Practices

Extension templates and layouts should be in stored in specific packages depending on whether they apply to the
frontend or the Admin panel.
Frontend templates and layouts should be stored in the f r ont end/ base/ def aul t package.
Admin panel templates and layouts should be stored in the:
admi nht ml / def aul t / def aul t package.
In order to improve readability and make the relationship between templates and the module code more
clear, templates should be stored in separate folders that are named with the module namespace and
name. For example, in our extension we will create the folder structure for frontend templates so that the
folder magent ost udy will include the folder news where all our templates will be placed. And we
place the newly created folder magent ost udy into f r ont end/ base/ def aul t / t empl at e
according to the restrictions above.
For similar reasons, layouts should be named with the module namespace and name. For example, in
our extension we will name our frontend layout magent ost udy{{_news. xml }} and place it into
f r ont end/ base/ def aul t / l ayout .
Be advised that native layouts don't include a namespace in their names. For example, the layout related
to the core module Mage_Cat al og is named just cat al og. xml , not mage_cat al og. xml

Creating our template and layout structures
Because our module will affect both the Admin panel and the frontend, we need to
create file/folder structures for both. As with our code structure mentioned earlier, you
should create only those folders that are necessary. For example, if you have a layout
for the backend, but no templates for it, you shouldn't create a template folder for that
layout. See the following diagrams for the frontend and Admin panel structures:


14 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
Frontend file/folder structure

Figure 4: Frontend file/folder structure



Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 15
Admin panel file/folder structure

Figure 5: Admin panel file/folder structure

Auxiliary files
Along with templates and layouts, an extension might also need some additional files
such as images, J avaScript, CSS files, or other external libraries.
JavaScript (JS), Cascading Style Sheets (CSS)
JavaScript (JS)
There are two locations you can use to store J avaScript files -- in the application js
folder or in an appropriate skin folder. The application js folder should be used if the
provided code may be helpful for another extension, for example, some library. If it is an
extension-specific J avaScript it should be placed in the skin folder.

Extension Best Practices

There are two locations you can use to store J avaScript files -- in the application j s folder or an appropriate
ski n folder.
If you use the global j s folder, your J avaScript will need to be stored in a second nested folder that is
named according to the module or library to which the j s applies. For example, any J avaScript for our
extension would be stored in: j s/ magent ost udy_news. Similarly, any J avaScript that customizes
an external library would be stored in j s/ <l i br ar y name>.

16 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
Using the global approach, you can store J avaScript for the Admin panel in the same js folder for your
module (j s/ magent ost udy_news).
If you use the ski n folder, your frontend J avaScript should be stored in
ski n/ f r ont end/ base/ def aul t / j s/ <namespace>_<name>. In our case,
ski n/ f r ont end/ base/ def aul t / j s/ magent ost udy_news
Using the skin approach, Admin panel J avaScript should be stored in
ski n/ admi nht ml / def aul t / def aul t / j s/ <namespace>_<name>. In our case,
ski n/ admi nht ml / def aul t / def aul t / j s/ magent ost udy_news
Extension-specific J avaScript files should not overwrite any native file.
Cascading Styl e Sheets (CSS)

Extension Best Practices

Extension-specific CSS files should be stored in css folders within an appropriate ski n folder depending on
whether they apply to the frontend or the Admin panel.
Frontend css: ski n/ f r ont end/ base/ def aul t / css. In our case,
ski n/ f r ont end/ base/ def aul t / css/ magent ost udy_news. css
Admin panel css: ski n/ admi nht ml / def aul t / def aul t / css. In our case,
ski n/ admi nht ml / def aul t / def aul t / css/ magent ost udy_news. css
Extension-specific CSS files should not overwrite any native files.

Media and External Libraries

Extension Best Practices
Images and other media files should be stored in the medi a folder
External libraries needed by an extension should be stored in the l i b folder
External libraries should be open source.
Development: The Front End
Now that we have created our module's structure and configured it, we can begin our
frontend development. As previously mentioned, our extension will consist of two
frontend pages. One will list all of our news posts; the second will display the content of
individual posts from the list.
Let's focus on our list of posts and get that to show up on the frontend. Our list of news
posts will be accessible via a footer link or a direct URL. Here's what we will need to do:
Add tables to our database schema to store our news posts
Prepare models to interact with the database and the news post data

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 17
Specify routes between our pages
Prepare output for our pages
Prepare auxiliary helpers for additional data manipulation
Add some sample data and test our results
Preparing our database schema
Starting from Magento Enterprise Edition (EE) 1.11 and Magento Community Edition
(CE) 1.6 you can use data folder for install/upgrade scripts which manipulate data and
sql folder for scripts that alter database schema. This feature allows to separate
database structure from data.
Magento does not work directly with raw SQL. Instead, it uses aliases that refer to the
SQL itself. For example, the core database table sal es_f l at _or der _i t emis
referred to with the alias sal es/ or der _i t em. Before we add any new tables or alter
existing ones in our schema, we need to configure their aliases in the module config
xml. Our extension will use a table named magent ost udy_news.

Extension Best Practices
Name database tables by module namespace and name to make the relationship between the code and
the database clearer.

config.xml specifying module's database table
<ent i t i es>
<news>
<t abl e>magent ost udy_news</ t abl e>
</ news>
</ ent i t i es>
Configuring our database schema script
Magento alters the database schema using PHP scripts that modify the SQL structure
using special adapter methods. These scripts are configured within the <r esour ces>
node in our conf i g. xml file. Each script is stored in a nested folder that is referred to
by the first child in the <r esour ces> node (in our case,
magent ost udy_news_set up. A third node, <set up>, defines which class our install
script will use for our extension. Different modules might require extended setup
classes -- for example, the sales setup class will automatically add sales aliases for
database tables related to sales so you don't need to add them manually. For our
extension, since we are only adding a new table, we don't need to do anything specific
in the setup class. We will use the native core class.


18 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
config.xml (specifying setup class)

<r esour ces>
<magent ost udy_news_set up>
<set up>
<modul e>Magent ost udy_News</ modul e>
<cl ass>Mage_Cor e_Model _Resour ce_Set up</ cl ass>
</ set up>
</ magent ost udy_news_set up>
</ r esour ces>
Writing our schema install script
Next, we need to write our schema installation PHP script. Before we start, we need to
decide whcih data we will store in the database. For our extension, we will store the
following:
Title
Author
Content
Image
Date when news was published
Date when news was created on Magento instance
News unique identifier
Our list of news posts will be ordered by the publ i shed_at field, so to increase
performance, we will create a database index on this field.
Before looking at our database alteration snippet, here are some restrictions and
recommendations that you should observe when working with databases and data
manipulation:

Extension Best Practices

Do not create references from core database tables to extension ones, because this could break native
Magento functionality.
Do not alter database structure on the fly. All changes should be applied via database install or upgrade
scripts.
Use database indexes when creating tables, because this can significantly improve database (and
overall) performance. More than one index can be created for a table.
Data and structure upgrades should be processed via Adapter methods; raw SQL is not recommended.
Usage of adapter methods will make an extension independent of concrete database realization.
If your extension stores some data such as statistics, the best approach is to create necessary logic
using database storage instead of the file system.
Separate data upgrades from schema upgrades. Pay strict attention to this because different upgrades were
added in Magento Enterprise Edition (EE) 1.11 and Magento Community Edition (CE) 1.6.



Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 19
install-1.0.0.0.1.php

<?php
/ **
* News i nst al l at i on scr i pt
*
* @aut hor Magent o
*/

/ **
* @var $i nst al l er Mage_Cor e_Model _Resour ce_Set up
*/
$i nst al l er = $t hi s;

/ **
* Cr eat i ng t abl e magent ost udy_news
*/
$t abl e = $i nst al l er - >get Connect i on( )
- >newTabl e( $i nst al l er - >get Tabl e( ' magent ost udy_news/ news' ) )
- >addCol umn( ' news_i d' , Var i en_Db_Ddl _Tabl e: : TYPE_I NTEGER, nul l , ar r ay(
' unsi gned' => t r ue,
' i dent i t y' => t r ue,
' nul l abl e' => f al se,
' pr i mar y' => t r ue,
) , ' Ent i t y i d' )
- >addCol umn( ' t i t l e' , Var i en_Db_Ddl _Tabl e: : TYPE_TEXT, 255, ar r ay(
' nul l abl e' => t r ue,
) , ' Ti t l e' )
- >addCol umn( ' aut hor ' , Var i en_Db_Ddl _Tabl e: : TYPE_TEXT, 63, ar r ay(
' nul l abl e' => t r ue,
' def aul t ' => nul l ,
) , ' Aut hor ' )
- >addCol umn( ' cont ent ' , Var i en_Db_Ddl _Tabl e: : TYPE_TEXT, ' 2M' , ar r ay(
' nul l abl e' => t r ue,
' def aul t ' => nul l ,
) , ' Cont ent ' )
- >addCol umn( ' i mage' , Var i en_Db_Ddl _Tabl e: : TYPE_TEXT, nul l , ar r ay(
' nul l abl e' => t r ue,
' def aul t ' => nul l ,
) , ' News i mage medi a pat h' )
- >addCol umn( ' publ i shed_at ' , Var i en_Db_Ddl _Tabl e: : TYPE_DATE, nul l , ar r ay(
' nul l abl e' => t r ue,
' def aul t ' => nul l ,
) , ' Wor l d publ i sh dat e' )
- >addCol umn( ' cr eat ed_at ' , Var i en_Db_Ddl _Tabl e: : TYPE_TI MESTAMP, nul l ,
ar r ay(
' nul l abl e' => t r ue,
' def aul t ' => nul l ,
) , ' Cr eat i on Ti me' )
- >addI ndex( $i nst al l er - >get I dxName(
$i nst al l er - >get Tabl e( ' magent ost udy_news/ news' ) ,
ar r ay( ' publ i shed_at ' ) ,
Var i en_Db_Adapt er _I nt er f ace: : I NDEX_TYPE_I NDEX
) ,
ar r ay( ' publ i shed_at ' ) ,
ar r ay( ' t ype' => Var i en_Db_Adapt er _I nt er f ace: : I NDEX_TYPE_I NDEX)

20 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
)
- >set Comment ( ' News i t em' ) ;

$i nst al l er - >get Connect i on( ) - >cr eat eTabl e( $t abl e) ;
Preparing our models to work with data and business logic
There are two model types in Magento:
Domain Models are responsible for implementing business logic and
manipulating combinations of data from resource models, APIs and other
sources before the data is inserted or updated in the database. If you are working
with databases, domain models depend on resource models.
Resource Models perform low-level SQL actions. They act as an abstraction
layer between domain models and the database.
Defining our models
Before implementing our models, we need to define them in conf i g. xml . Our model
and resource model use classes whose names begin with the value in the <cl ass>
node. (This value is not an actual model name, but rather the prefix used to specify our
models). Similarly, our resource models use a prefix of
Magent ost udy_News_Model _Resour ce.
config.xml (models section)
<model s>
<magent ost udy_news>
<cl ass>Magent ost udy_News_Model </ cl ass>
<r esour ceModel >news_r esour ce</ r esour ceModel >
</ magent ost udy_news>
<news_r esour ce>
<cl ass>Magent ost udy_News_Model _Resour ce</ cl ass>
<ent i t i es>
<news>
<t abl e>magent ost udy_news</ t abl e>
</ news>
</ ent i t i es>
</ news_r esour ce>
</ model s>
Implementing our model

Extension Best Practices

Data should be escaped before inserting it into the database. This is extremely important for security
because it helps to avoid SQL-injections.
The extension should be responsible for validating incoming data such as user entries, API call
responses, etc.

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 21
Magento's abstract core model already implements basic methods. By extending our
model from this one, well be able to use basic methods such as load, save, and delete.
We will use our model to update the created field if the post is new. For this, we need to
create class Magent ost udy/ News/ Model / News. php.
Magentostudy_News_Model_News
<?php
/ **
* News i t emmodel
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Model _News ext ends Mage_Cor e_Model _Abst r act
{
/ **
* Def i ne r esour ce model
*/
pr ot ect ed f unct i on _const r uct ( )
{
$t hi s- >_i ni t ( ' magent ost udy_news/ news' ) ;
}

/ **
* I f obj ect i s new adds cr eat i on dat e
*
* @r et ur n Magent ost udy_News_Model _News
*/
pr ot ect ed f unct i on _bef or eSave( )
{
par ent : : _bef or eSave( ) ;
i f ( $t hi s- >i sObj ect New( ) ) {
$t hi s- >set Dat a( ' cr eat ed_at ' , Var i en_Dat e: : now( ) ) ;
}
r et ur n $t hi s;
}
}
Implementing our resource model and collection

Extension Best Practices

Be sure to use the correct connection for queries. If you want only select records use read connection,
otherwise use write connection. Pay attention that all queries like SELECT FOR UPDATE also need
write permission, so write connection should be used. Pay attention to queries combined into
transactions if only one query needs write permissions, all queries in the transaction should use write
connection
Database query manipulations should be placed in resource models only. Resource models are the best
place for SQL.
Use Zend style SQL queries because they make SQL queries more readable and provides object-
oriented approach, which allows modifying them in other modules.
Our plan is to load, save, or delete individual posts and to display a collection of posts
on the frontend. As with our domain models, we do not need to implement basic

22 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
actions; we only need to specify the resource we want to work with to return its data. In
our collection, we will implement a method for sorting news posts and limiting their
count.
We will add two files: Magent ost udy/ News/ Model / Resour ce/ News. php for our
individual posts and
Magent ost udy/ News/ Model / Resour ce/ News/ Col l ect i on. php for our collection
of all posts.
Magentostudy_News_Model_Resource_News
<?php
/ **
* News i t emr esour ce model
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Model _Resour ce_News ext ends
Mage_Cor e_Model _Resour ce_Db_Abst r act
{
/ **
* I ni t i al i ze connect i on and def i ne mai n t abl e and pr i mar y key
*/
pr ot ect ed f unct i on _const r uct ( )
{
$t hi s- >_i ni t ( ' magent ost udy_news/ news' , ' news_i d' ) ;
}
}

Magentostudy_News_Model_Resource_News_Collection
<?php
/ **
* News col l ect i on
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Model _Resour ce_News_Col l ect i on ext ends
Mage_Cor e_Model _Resour ce_Db_Col l ect i on_Abst r act
{
/ **
* Def i ne col l ect i on model
*/
pr ot ect ed f unct i on _const r uct ( )
{
$t hi s- >_i ni t ( ' magent ost udy_news/ news' ) ;
}

/ **
* Pr epar e f or di spl ayi ng i n l i st
*
* @par ami nt eger $page
* @r et ur n Magent ost udy_News_Model _Resour ce_News_Col l ect i on
*/
publ i c f unct i on pr epar eFor Li st ( $page)

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 23
{
$t hi s- >set PageSi ze( Mage: : hel per ( ' magent ost udy_news' ) -
>get NewsPer Page( ) ) ;
$t hi s- >set Cur Page( $page) - >set Or der ( ' publ i shed_at ' ,
Var i en_Dat a_Col l ect i on: : SORT_ORDER_DESC) ;
r et ur n $t hi s;
}
}
Specifying our routes and request flow
In MVC architecture, controllers are responsible for routes and request flow. Our news
extension will use a controller that will make our pages accessible by URLs on the
frontend.
Configuring our routes
Before implementing our controller, we need to configure our routes in conf i g. xml .
Here, the f r ont Name node specifies that our controller will be accessible through the
frontend URL ht t p: / / <st or e- URL>/ i ndex. php/ news.
config.xml (specifying routes)
<f r ont end>
<r out er s>
<magent ost udy_news>
<use>st andar d</ use>
<ar gs>
<modul e>Magent ost udy_News</ modul e>
<f r ont Name>news</ f r ont Name>
</ ar gs>
</ magent ost udy_news>
</ r out er s>
Implementing our controller
According to our plan, our controller needs two actions: a news list and a single post
view. i ndexAct i on is default controller action and will be responsible for the news list.
The action vi ewAct i on will be responsible for the individual news posts. Before
implementing our controller, lets consider some restrictions and recommendations for
writing controllers in Magento extensions:


24 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.

Extension Best Practices
Do not use PHP global variables like $_SERVER, $_GET, $_POST. There are special Magento
methods to interact with this data that should be used instead. For example, you can use the
get Request ( ) function in a controller method to get request data.
Do not work directly with the PHP $_GLOBAL variable Magento provides an alternative solution to
avoid usage of $_GLOBAL - Mage: : r egi st er ( ) , Mage: : r egi st r y( ) ,
Mage: : unr egi st er ( ) .
Override controllers only if you do not have another more flexible solution.
If you plan to just add new action(s) without using methods or variables from the parent, use an abstract
class for the parent. This will help keep your extension compatible with others.
According to the Zend Framework MVC best practices, the controller component of an application "must
be as skinny as possible". It is strongly recommended to encapsulate all business logic into models and
helpers; avoid implementing business logic in a controller action.
Now, lets add our controller
Magent ost udy/ News/ cont r ol l er / I ndexCont r ol l er . php
Magentostudy_News_IndexController
<?php
/ **
* News f r ont end cont r ol l er
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_I ndexCont r ol l er ext ends
Mage_Cor e_Cont r ol l er _Fr ont _Act i on
{
/ **
* Pr e di spat ch act i on t hat al l ows t o r edi r ect t o no r out e page i n case
of di sabl ed ext ensi on t hr ough Admi n panel
*/
publ i c f unct i on pr eDi spat ch( )
{
par ent : : pr eDi spat ch( ) ;

i f ( ! Mage: : hel per ( ' magent ost udy_news' ) - >i sEnabl ed( ) ) {
$t hi s- >set Fl ag( ' ' , ' no- di spat ch' , t r ue) ;
$t hi s- >_r edi r ect ( ' noRout e' ) ;
}
}

/ **
* I ndex act i on
*/
publ i c f unct i on i ndexAct i on( )
{
$t hi s- >l oadLayout ( ) ;

$l i st Bl ock = $t hi s- >get Layout ( ) - >get Bl ock( ' news. l i st ' ) ;

i f ( $l i st Bl ock) {
$cur r ent Page = abs( i nt val ( $t hi s- >get Request ( ) - >get Par am( ' p' ) ) ) ;

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 25
i f ( $cur r ent Page < 1) {
$cur r ent Page = 1;
}
$l i st Bl ock- >set Cur r ent Page( $cur r ent Page) ;
}

$t hi s- >r ender Layout ( ) ;
}

/ **
* News vi ew act i on
*/
publ i c f unct i on vi ewAct i on( )
{
$newsI d = $t hi s- >get Request ( ) - >get Par am( ' i d' ) ;
i f ( ! $newsI d) {
r et ur n $t hi s- >_f or war d( ' noRout e' ) ;
}

/ ** @var $model Magent ost udy_News_Model _News */
$model = Mage: : get Model ( ' magent ost udy_news/ news' ) ;
$model - >l oad( $newsI d) ;

i f ( ! $model - >get I d( ) ) {
r et ur n $t hi s- >_f or war d( ' noRout e' ) ;
}

Mage: : r egi st er ( ' news_i t em' , $model ) ;

Mage: : di spat chEvent ( ' bef or e_news_i t em_di spl ay' , ar r ay( ' news_i t em' =>
$model ) ) ;

$t hi s- >l oadLayout ( ) ;
$i t emBl ock = $t hi s- >get Layout ( ) - >get Bl ock( ' news. i t em' ) ;
i f ( $i t emBl ock) {
$l i st Bl ock = $t hi s- >get Layout ( ) - >get Bl ock( ' news. l i st ' ) ;
i f ( $l i st Bl ock) {
$page = ( i nt ) $l i st Bl ock- >get Cur r ent Page( ) ? ( i nt ) $l i st Bl ock-
>get Cur r ent Page( ) : 1;
} el se {
$page = 1;
}
$i t emBl ock- >set Page( $page) ;
}
$t hi s- >r ender Layout ( ) ;
}
}
Preparing our output
Configuring our output
Before implementing output components, will need to configure our layouts and blocks
in our conf i g. xml file.

26 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
config.xml (specifying frontend layout)

<l ayout >
<updat es>
<magent ost udy_news>
<f i l e>magent ost udy_news. xml </ f i l e>
</ magent ost udy_news>
</ updat es>
</ l ayout >

config.xml (specifying blocks)
<bl ocks>
<magent ost udy_news>
<cl ass>Magent ost udy_News_Bl ock</ cl ass>
</ magent ost udy_news>
</ bl ocks>
Implementing our layout
As shown above, each of our controller's actions loads and renders a layout. This
layout does not exist yet, so next we will create it.

Extension Best Practice
It's not recommended to remove native blocks in custom layouts. Add new blocks instead.

Magentostudy_news.xml

<?xml ver si on=" 1. 0" ?>
<! - -
/ **
* Magent o f r ont end l ayout
*
* @aut hor Magent o
*/
- - >
<l ayout ver si on=" 0. 1. 0" >
<def aul t >
<r ef er ence name=" f oot er _l i nks" >
<act i on met hod=" addLi nk" t r ansl at e=" l abel t i t l e"
modul e=" magent ost udy_news" i f conf i g=" news/ vi ew/ enabl ed" >
<l abel >News</ l abel >
<ur l >news</ ur l >
<t i t l e>News</ t i t l e>
<pr epar e>t r ue</ pr epar e>
</ act i on>
</ r ef er ence>
</ def aul t >

<magent ost udy_news_i ndex_i ndex t r ansl at e=" l abel " >
<l abel >News Page</ l abel >

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 27
<r ef er ence name=" r oot " >
<act i on met hod=" set Templ at e" >
<t empl at e>page/ 2col umns- r i ght . pht ml </ t empl at e>
</ act i on>
<act i on met hod=" set Header Ti t l e" t r ansl at e=" t i t l e"
modul e=" magent ost udy_news" >
<t i t l e>Si t e News</ t i t l e>
</ act i on>
</ r ef er ence>
<r ef er ence name=" cont ent " >
<bl ock t ype=" magent ost udy_news/ l i st " name=" news. l i st "
t empl at e=" magent ost udy/ news/ l i st . pht ml " >
<bl ock t ype=" page/ ht ml _pager " name=" news. l i st . pager "
as=" news_l i st _pager " / >
</ bl ock>
</ r ef er ence>
</ magent ost udy_news_i ndex_i ndex>

<magent ost udy_news_i ndex_vi ew t r ansl at e=" l abel " >
<l abel >News I t emPage</ l abel >
<r ef er ence name=" r oot " >
<act i on met hod=" set Templ at e" >
<t empl at e>page/ 2col umns- r i ght . pht ml </ t empl at e>
</ act i on>
</ r ef er ence>
<r ef er ence name=" cont ent " >
<bl ock t ype=" magent ost udy_news/ news" name=" news. i t em"
t empl at e=" magent ost udy/ news/ i t em. pht ml " / >
</ r ef er ence>
</ magent ost udy_news_i ndex_vi ew>
</ l ayout >
Implementing our blocks
In our layout above, we add three view blocks: one for our footer link, a second for our
list of news posts and, a third for our individual posts. We do not need to add anything
more for our footer link block because it is a native Magento block and we are simply
adding our link to it. However, we will need to create classes for our list and item
blocks, Magent ost udy/ News/ Bl ock/ Li st . php and
Magent ost udy/ News/ Bl ock/ I t em. php.
Magentostudy_News_Block_List

<?php
/ **
* News Li st bl ock
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_Li st ext ends Mage_Cor e_Bl ock_Templ at e
{
/ **
* News col l ect i on
*

28 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
* @var Magent ost udy_News_Model _Resour ce_News_Col l ect i on
*/
pr ot ect ed $_newsCol l ect i on = nul l ;

/ **
* Ret r i eve news col l ect i on
*
* @r et ur n Magent ost udy_News_Model _Resour ce_News_Col l ect i on
*/
pr ot ect ed f unct i on _get Col l ect i on( )
{
r et ur n Mage: : get Resour ceModel ( ' magent ost udy_news/ news_col l ect i on' ) ;
}

/ **
* Ret r i eve pr epar ed news col l ect i on
*
* @r et ur n Magent ost udy_News_Model _Resour ce_News_Col l ect i on
*/
publ i c f unct i on get Col l ect i on( )
{
i f ( i s_nul l ( $t hi s- >_newsCol l ect i on) ) {
$t hi s- >_newsCol l ect i on = $t hi s- >_get Col l ect i on( ) ;
$t hi s- >_newsCol l ect i on- >pr epar eFor Li st ( $t hi s- >get Cur r ent Page( ) ) ;
}

r et ur n $t hi s- >_newsCol l ect i on;
}

/ **
* Ret ur n URL t o i t em' s vi ew page
*
* @par amMagent ost udy_News_Model _News $newsI t em
* @r et ur n st r i ng
*/
publ i c f unct i on get I t emUr l ( $newsI t em)
{
r et ur n $t hi s- >get Ur l ( ' */ */ vi ew' , ar r ay( ' i d' => $newsI t em- >get I d( ) ) ) ;
}

/ **
* Fet ch t he cur r ent page f or t he news l i st
*
* @r et ur n i nt
*/
publ i c f unct i on get Cur r ent Page( )
{
r et ur n $t hi s- >get Dat a( ' cur r ent _page' ) ? $t hi s-
>get Dat a( ' cur r ent _page' ) : 1;
}

/ **
* Get a pager
*
* @r et ur n st r i ng| nul l
*/
publ i c f unct i on get Pager ( )

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 29
{
$pager = $t hi s- >get Chi l d( ' news_l i st _pager ' ) ;
i f ( $pager ) {
$newsPer Page = Mage: : hel per ( ' magent ost udy_news' ) -
>get NewsPer Page( ) ;

$pager - >set Avai l abl eLi mi t ( ar r ay( $newsPer Page => $newsPer Page) ) ;
$pager - >set Tot al Num( $t hi s- >get Col l ect i on( ) - >get Si ze( ) ) ;
$pager - >set Col l ect i on( $t hi s- >get Col l ect i on( ) ) ;
$pager - >set ShowPer Page( t r ue) ;

r et ur n $pager - >t oHt ml ( ) ;
}

r et ur n nul l ;
}

/ **
* Ret ur n URL f or r esi zed News I t emi mage
*
* @par amMagent ost udy_News_Model _News $i t em
* @par ami nt eger $wi dt h
* @r et ur n st r i ng| f al se
*/
publ i c f unct i on get I mageUr l ( $i t em, $wi dt h)
{
r et ur n Mage: : hel per ( ' magent ost udy_news/ i mage' ) - >r esi ze( $i t em,
$wi dt h) ;
}
}

Magentostudy_News_Block_News

<?php
/ **
* News I t embl ock
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_I t emext ends Mage_Cor e_Bl ock_Templ at e
{
/ **
* Cur r ent news i t emi nst ance
*
* @var Magent ost udy_News_Model _News
*/
pr ot ect ed $_i t em;

/ **
* Ret ur n par amet er s f or back ur l
*
* @par amar r ay $addi t i onal Par ams
* @r et ur n ar r ay
*/
pr ot ect ed f unct i on _get BackUr l Quer yPar ams( $addi t i onal Par ams = ar r ay( ) )
{

30 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
r et ur n ar r ay_mer ge( ar r ay( ' p' => $t hi s- >get Page( ) ) ,
$addi t i onal Par ams) ;
}

/ **
* Ret ur n URL t o t he news l i st page
*
* @r et ur n st r i ng
*/
publ i c f unct i on get BackUr l ( )
{
r et ur n $t hi s- >get Ur l ( ' */ ' , ar r ay( ' _quer y' => $t hi s-
>_get BackUr l Quer yPar ams( ) ) ) ;
}

/ **
* Ret ur n URL f or r esi zed News I t emi mage
*
* @par amMagent ost udy_News_Model _News $i t em
* @par ami nt eger $wi dt h
* @r et ur n st r i ng| f al se
*/
publ i c f unct i on get I mageUr l ( $i t em, $wi dt h)
{
r et ur n Mage: : hel per ( ' magent ost udy_news/ i mage' ) - >r esi ze( $i t em,
$wi dt h) ;
}
}
These blocks illustrate some Magento best practices and restrictions which you should
consider when developing your extensions:

Extension Best Practices

Use special Magento methods for URL generation such as Mage: : get URL( ) . Using these methods
allows us to generate URLs based on different criteria such as security options.
Line 51 in Magent ost udy_News_Bl ock_Li st shows an example of how to use get URL( ) to
generate a URL for the individual news view.

Frontend blocks should be cached, wherever possible to optimize frontend performance.
All blocks except special dynamic content should be cached using native Magento cache functionality -
methods Mage: : app( ) - >saveCache( ) and Mage: : app( ) - >loadCache().
Use logical caching. For example, store values that don't change during calls to different class methods
in protected class variables and use these values instead of loading new values or making new
calculations.
In our case, we have a good example of logical caching. Take a look at block
Magent ost udy_News_Bl ock_Li st . Here we manipulate a collection of news, but in
the get Col l ect i on method, we do not instantiate and apply filters to the collection every time. We can do this
one time and then save the collection into a protected variable - $_newsCol l ect i on -- for further use.



Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 31
Implementing our templates
Our templates are already configured in our layout files so we will start implementing
them. Before we begin, lets consider some restrictions and recommendations for
writing templates in Magento extensions:

Extension Best Practices
Core templates files cannot be physically overridden in the extension package. Use layout functionality to
extend frontend views.
All phrases must be enclosed with translation tags and methods so that they can be translated according
to the store locale. (This applies to all output, including phrases that appear in controllers, blocks and
helpers.)
All data shown in templates should be preliminarily escaped with the escapeHt ml , st r i pTags
methods to avoid possible XSS injections.
Templates shouldn't contain business logic. Move all business logic to models, blocks, and helpers.
In our layout we've specified two templates - magent ost udy/ news/ l i st . pht ml and
magent ost udy/ news/ i t em. pht ml for list of news and separate news post
respectively.
list.phtml

<?php
/ **
* News t empl at e f or i t ems l i st
*
* @aut hor Magent o
*/

/ **
* @var $t hi s Magent ost udy_News_Bl ock_Li st
* @see Magent ost udy_News_Bl ock_Li st
*/
?>
<di v i d=" news_l i st _messages" ><?php echo $t hi s- >get MessagesBl ock( ) -
>get Gr oupedHt ml ( ) ?></ di v>
<di v>
<h1><?php echo Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Si t e News' ) ?></ h1>
</ di v>

<di v>
<?php f or each ( $t hi s- >get Col l ect i on( ) as $newsI t em) : ?>
<di v i d=" i t em_<?php echo $newsI t em- >get I d( ) ?>" >
<h2>
<a hr ef =" <?php echo $t hi s- >get I t emUr l ( $newsI t em) ?>" >
<?php echo $t hi s- >escapeHt ml ( $newsI t em- >get Ti t l e( ) ) ?>
</ a>
</ h2>

<di v>

32 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
<?php echo $t hi s- >f or mat Dat e( $newsI t em- >get Ti mePubl i shed( ) ,
' medi um' ) ?> |
<?php echo $t hi s- >escapeHt ml ( $newsI t em- >get Aut hor ( ) ) ?>
</ di v>

<?php i f ( $i mageUr l = $t hi s- >get I mageUr l ( $newsI t em, 100) ) : ?>
<p><i mg sr c=" <?php echo $i mageUr l ?>" al t =" <?php echo $t hi s-
>escapeHt ml ( $newsI t em- >get Ti t l e( ) ) ; ?>" / ></ p>
<?php endi f ; ?>
</ di v>
<?php endf or each; ?>
</ di v>

<?php echo $t hi s- >get Pager ( ) ?>

item.phtml
<?php
/ **
* News t empl at e f or separ at e i t em
*
* @aut hor Magent o
*/

/ **
* @var $t hi s Magent ost udy_News_Bl ock_I t em
* @see Magent ost udy_News_Bl ock_I t em
*/
?>
<?php $_newsI t em= $t hi s- >hel per ( ' magent ost udy_news' ) - >get NewsI t emI nst ance( ) ;
?>
<di v i d=" news_i t em_messages" ><?php echo $t hi s- >get MessagesBl ock( ) -
>get Gr oupedHt ml ( ) ?></ di v>

<di v>
<h1><?php echo $t hi s- >escapeHt ml ( $_newsI t em- >get Ti t l e( ) ) ?></ h1>

<di v>
<?php echo $t hi s- >f or mat Dat e( $_newsI t em- >get Ti mePubl i shed( ) ,
Mage_Cor e_Model _Local e: : FORMAT_TYPE_MEDI UM) ?> |
<?php echo $t hi s- >escapeHt ml ( $_newsI t em- >get Aut hor ( ) ) ?>
</ di v>
</ di v>

<di v>
<?php i f ( $i mageUr l = $t hi s- >get I mageUr l ( $_newsI t em, 400) ) : ?>
<p><i mg sr c=" <?php echo $i mageUr l ?>" al t =" <?php echo $t hi s-
>escapeHt ml ( $_newsI t em- >get Ti t l e( ) ) ?>" / ></ p>
<?php endi f ; ?>

<di v><?php echo $_newsI t em- >get Cont ent ( ) ?></ di v>

<di v>
<a hr ef =" <?php echo $t hi s- >get BackUr l ( ) ?>" >
<?php echo Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Ret ur n t o
l i st ' ) ?>
</ a>

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 33
</ di v>
</ di v>
Preparing our helpers
As you may have seen in previous code snippets there are many helper calls. Helpers
are auxiliary classes that implement commonly used business logic.
In our extension we will have two frontend helpers:
A data helper used for translation and other interactions with the stores
configuration
An image helper that provides functionality to work with images (uploading,
resizing, removing, etc.)

Extension Best Practices
An extension should have its own helper for translations, to allow different phrase translations in different
modules and to make the module independent from others.
Do not hardcode pre-defined values directly into methods. Use class constants, protected class
variables, or store configuration to allow for changing values without code changes.
In our case, we will use store configuration to allow certain values to be changed. We won't hard-code the number
of posts per page or the number of days a post should be considered recent.
Configuring our helpers
Before implementing our helpers, we need toconfigure them in our conf i g. xml file.
config.xml (specifying helpers)

<hel per s>
<magent ost udy_news>
<cl ass>Magent ost udy_News_Hel per </ cl ass>
</ magent ost udy_news>
</ hel per s>
Implementing our helpers
Now we'll add our two helpers:
Magent ost udy/ News/ Hel per / Dat a. php
Magent ost udy/ News/ Hel per / I mage. php
Magentostudy_News_Helper_Data

<?php
/ **

34 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
* News Dat a hel per
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Hel per _Dat a ext ends Mage_Cor e_Hel per _Dat a
{
/ **
* Pat h t o st or e conf i g i f f r ont end out put i s enabl ed
*
* @var st r i ng
*/
const XML_PATH_ENABLED = ' news/ vi ew/ enabl ed' ;

/ **
* Pat h t o st or e conf i g wher e count of news post s per page i s st or ed
*
* @var st r i ng
*/
const XML_PATH_I TEMS_PER_PAGE = ' news/ vi ew/ i t ems_per _page' ;

/ **
* Pat h t o st or e conf i g wher e count of days whi l e news i s st i l l r ecent l y
added i s st or ed
*
* @var st r i ng
*/
const XML_PATH_DAYS_DI FFERENCE = ' news/ vi ew/ days_di f f er ence' ;

/ **
* News I t emi nst ance f or l azy l oadi ng
*
* @var Magent ost udy_News_Model _News
*/
pr ot ect ed $_newsI t emI nst ance;

/ **
* Checks whet her news can be di spl ayed i n t he f r ont end
*
* @par ami nt eger | st r i ng| Mage_Cor e_Model _St or e $st or e
* @r et ur n bool ean
*/
publ i c f unct i on i sEnabl ed( $st or e = nul l )
{
r et ur n Mage: : get St or eConf i gFl ag( sel f : : XML_PATH_ENABLED, $st or e) ;
}

/ **
* Ret ur n t he number of i t ems per page
*
* @par ami nt eger | st r i ng| Mage_Cor e_Model _St or e $st or e
* @r et ur n i nt
*/
publ i c f unct i on get NewsPer Page( $st or e = nul l )
{
r et ur n abs( ( i nt ) Mage: : get St or eConf i g( sel f : : XML_PATH_I TEMS_PER_PAGE,
$st or e) ) ;
}

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 35

/ **
* Ret ur n di f f er ence i n days whi l e news i s r ecent l y added
*
* @par ami nt eger | st r i ng| Mage_Cor e_Model _St or e $st or e
* @r et ur n i nt
*/
publ i c f unct i on get DaysDi f f er ence( $st or e = nul l )
{
r et ur n abs( ( i nt ) Mage: : get St or eConf i g( sel f : : XML_PATH_DAYS_DI FFERENCE,
$st or e) ) ;
}

/ **
* Ret ur n cur r ent news i t emi nst ance f r omt he Regi st r y
*
* @r et ur n Magent ost udy_News_Model _News
*/
publ i c f unct i on get NewsI t emI nst ance( )
{
i f ( ! $t hi s- >_newsI t emI nst ance) {
$t hi s- >_newsI t emI nst ance = Mage: : r egi st r y( ' news_i t em' ) ;

i f ( ! $t hi s- >_newsI t emI nst ance) {
Mage: : t hr owExcept i on( $t hi s- >__( ' News i t emi nst ance does not
exi st i n Regi st r y' ) ) ;
}
}

r et ur n $t hi s- >_newsI t emI nst ance;
}
}
Our mage helper works with physical files, so take a look at Magento registered
methods that avoid direct work with physical files paths:

Extension Best Practices
If you are working with physical files, use Magento's registered methods (for example, method
Mage: : get BaseDi r ( ) ) to get links to them.


Magentostudy_News_Helper_Image

<?php
/ **
* News I mage Hel per
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Hel per _I mage ext ends Mage_Cor e_Hel per _Abst r act
{
/ **

36 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
* Medi a pat h t o ext ensi on i mahes
*
* @var st r i ng
*/
const MEDI A_PATH = ' news' ;

/ **
* Maxi mumsi ze f or i mage i n byt es
* Def aul t val ue i s 1M
*
* @var i nt
*/
const MAX_FI LE_SI ZE = 1048576;

/ **
* Mani mumi mage hei ght i n pi xel s
*
* @var i nt
*/
const MI N_HEI GHT = 50;

/ **
* Maxi mumi mage hei ght i n pi xel s
*
* @var i nt
*/
const MAX_HEI GHT = 800;

/ **
* Mani mumi mage wi dt h i n pi xel s
*
* @var i nt
*/
const MI N_WI DTH = 50;

/ **
* Maxi mumi mage wi dt h i n pi xel s
*
* @var i nt
*/
const MAX_WI DTH = 800;

/ **
* Ar r ay of i mage si ze l i mi t at i on
*
* @var ar r ay
*/
pr ot ect ed $_i mageSi ze = ar r ay(
' mi nhei ght ' => sel f : : MI N_HEI GHT,
' mi nwi dt h' => sel f : : MI N_WI DTH,
' maxhei ght ' => sel f : : MAX_HEI GHT,
' maxwi dt h' => sel f : : MAX_WI DTH,
) ;

/ **
* Ar r ay of al l owed f i l e ext ensi ons
*

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 37
* @var ar r ay
*/
pr ot ect ed $_al l owedExt ensi ons = ar r ay( ' j pg' , ' gi f ' , ' png' ) ;

/ **
* Ret ur n t he base medi a di r ect or y f or News I t emi mages
*
* @r et ur n st r i ng
*/
publ i c f unct i on get BaseDi r ( )
{
r et ur n Mage: : get BaseDi r ( ' medi a' ) . DS . sel f : : MEDI A_PATH;
}

/ **
* Ret ur n t he Base URL f or News I t emi mages
*
* @r et ur n st r i ng
*/
publ i c f unct i on get BaseUr l ( )
{
r et ur n Mage: : get BaseUr l ( ' medi a' ) . ' / ' . sel f : : MEDI A_PATH;
}

/ **
* Remove news i t emi mage by i mage f i l ename
*
* @par amst r i ng $i mageFi l e
* @r et ur n bool
*/
publ i c f unct i on r emoveI mage( $i mageFi l e)
{
$i o = new Var i en_I o_Fi l e( ) ;
$i o- >open( ar r ay( ' pat h' => $t hi s- >get BaseDi r ( ) ) ) ;
i f ( $i o- >f i l eExi st s( $i mageFi l e) ) {
r et ur n $i o- >r m( $i mageFi l e) ;
}
r et ur n f al se;
}

/ **
* Upl oad i mage and r et ur n upl oaded i mage f i l e name or f al se
*
* @t hr ows Mage_Cor e_Except i on
* @par amst r i ng $scope t he r equest key f or f i l e
* @r et ur n bool | st r i ng
*/
publ i c f unct i on upl oadI mage( $scope)
{
$adapt er = new Zend_Fi l e_Tr ansf er _Adapt er _Ht t p( ) ;
$adapt er - >addVal i dat or ( ' I mageSi ze' , t r ue, $t hi s- >_i mageSi ze) ;
$adapt er - >addVal i dat or ( ' Si ze' , t r ue, sel f : : MAX_FI LE_SI ZE) ;
i f ( $adapt er - >i sUpl oaded( $scope) ) {
/ / val i dat e i mage
i f ( ! $adapt er - >i sVal i d( $scope) ) {
Mage: : t hr owExcept i on( Mage: : hel per ( ' magent ost udy_news' ) -
>__( ' Upl oaded i mage i s not val i d' ) ) ;

38 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
}
$upl oad = new Var i en_Fi l e_Upl oader ( $scope) ;
$upl oad- >set Al l owCr eat eFol der s( t r ue) ;
$upl oad- >set Al l owedExt ensi ons( $t hi s- >_al l owedExt ensi ons) ;
$upl oad- >set Al l owRenameFi l es( t r ue) ;
$upl oad- >set Fi l esDi sper si on( f al se) ;
i f ( $upl oad- >save( $t hi s- >get BaseDi r ( ) ) ) {
r et ur n $upl oad- >get Upl oadedFi l eName( ) ;
}
}
r et ur n f al se;
}

/ **
* Ret ur n URL f or r esi zed News I t emI mage
*
* @par amMagent ost udy_News_Model _I t em$i t em
* @par ami nt eger $wi dt h
* @par ami nt eger $hei ght
* @r et ur n bool | st r i ng
*/
publ i c f unct i on r esi ze( Magent ost udy_News_Model _News $i t em, $wi dt h,
$hei ght = nul l )
{
i f ( ! $i t em- >get I mage( ) ) {
r et ur n f al se;
}

i f ( $wi dt h < sel f : : MI N_WI DTH | | $wi dt h > sel f : : MAX_WI DTH) {
r et ur n f al se;
}
$wi dt h = ( i nt ) $wi dt h;

i f ( ! i s_nul l ( $hei ght ) ) {
i f ( $hei ght < sel f : : MI N_HEI GHT | | $hei ght > sel f : : MAX_HEI GHT) {
r et ur n f al se;
}
$hei ght = ( i nt ) $hei ght ;
}

$i mageFi l e = $i t em- >get I mage( ) ;
$cacheDi r = $t hi s- >get BaseDi r ( ) . DS . ' cache' . DS . $wi dt h;
$cacheUr l = $t hi s- >get BaseUr l ( ) . ' / ' . ' cache' . ' / ' . $wi dt h .
' / ' ;

$i o = new Var i en_I o_Fi l e( ) ;
$i o- >checkAndCr eat eFol der ( $cacheDi r ) ;
$i o- >open( ar r ay( ' pat h' => $cacheDi r ) ) ;
i f ( $i o- >f i l eExi st s( $i mageFi l e) ) {
r et ur n $cacheUr l . $i mageFi l e;
}

t r y {
$i mage = new Var i en_I mage( $t hi s- >get BaseDi r ( ) . DS . $i mageFi l e) ;
$i mage- >r esi ze( $wi dt h, $hei ght ) ;
$i mage- >save( $cacheDi r . DS . $i mageFi l e) ;
r et ur n $cacheUr l . $i mageFi l e;

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 39
} cat ch ( Except i on $e) {
Mage: : l ogExcept i on( $e) ;
r et ur n f al se;
}
}

/ **
* Removes f ol der wi t h cached i mages
*
* @r et ur n bool ean
*/
publ i c f unct i on f l ushI magesCache( )
{
$cacheDi r = $t hi s- >get BaseDi r ( ) . DS . ' cache' . DS ;
$i o = new Var i en_I o_Fi l e( ) ;
i f ( $i o- >f i l eExi st s( $cacheDi r , f al se) ) {
r et ur n $i o- >r mdi r ( $cacheDi r , t r ue) ;
}
r et ur n t r ue;
}
}
Adding sample data
Now, we are ready to view our extension on the frontend. Before we can see anything,
we will need to add some sample data to the database. We will use a data install script
for this: dat a/ magent ost udy_news_set up/ dat a- i nst al l - 1. 0. 0. 0. 1. php. We
do not need to add anything to conf i g. xml because we have already specified
everything we needed when we configured our database schema installation scripts
earlier.
data-install-1.0.0.0.1.php

<?php
/ **
* News dat a i nst al l at i on scr i pt
*
* @aut hor Magent o
*/

/ **
* @var $i nst al l er Mage_Cor e_Model _Resour ce_Set up
*/
$i nst al l er = $t hi s;

/ **
* @var $model Magent ost udy_News_Model _News
*/
$model = Mage: : get Model ( ' magent ost udy_news/ news' ) ;

/ / Set up dat a r ows
$dat aRows = ar r ay(
ar r ay(

40 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
' t i t l e' => ' Magent o Devel oper Cer t i f i cat i on Exams Now
Avai l abl e Wor l dwi de' ,
' aut hor ' => ' Bet h Gomez' ,
' publ i shed_at ' => ' 2011- 12- 22' ,
' cont ent ' => ' <p>I n Oct ober , Magent o l aunched t he bet a ver si on
of t he Magent o Cer t i f i ed Devel oper exam. Dozens of exper i enced Magent o
devel oper s f l ocked t o t he X. commer ce I nnovat e 2011 Conf er ence &ndash; and t o
sever al ot her bet a examl ocat i ons ar ound t he wor l d &ndash; t o t ake t he exam.
Many of t hemear ned passi ng gr ades, becomi ng t he wor l d&r squo; s f i r st Magent o
Cer t i f i ed Devel oper s. <br / ><br / >Wi t h t he successf ul bet a behi nd us, we ar e
exci t ed t o announce t he gl obal l aunch of our Cer t i f i cat i on pr ogr am.
<st r ong>Now, devel oper s can t ake t he Magent o Cer t i f i ed Devel oper examat over
5, 000 Pr omet r i c Test i ng Cent er s wor l dwi de. </ st r ong><br / ><br / >Fi nd out how
t o r egi st er , pr epar e f or , and t ake t he cer t i f i cat i on examon t he Magent o U
Cer t i f i cat i on websi t e. <br / ><br / ><st r ong>What you shoul d know about Magent o
Devel oper Cer t i f i cat i on: </ st r ong><br / ><br / ></ p>
<ul >
<l i >Magent o Devel oper Cer t i f i cat i on i s t he f i r st and onl y Magent o- sponsor ed
and appr oved pr of essi onal cer t i f i cat i on pr ogr am. </ l i >
<l i >Magent o Devel oper Cer t i f i cat i on Exams wer e devel oped by a t eamof exper t s
f r omacr oss t he Magent o ecosyst emt o accur at el y t est and ver i f y r eal - wor l d
devel opment ski l l s. </ l i >
<l i >Devel oper s who pass t he examcan di f f er ent i at e t hemsel ves i n t he
mar ket pl ace by usi ng t he Magent o Devel oper Cer t i f i cat i on badge on t hei r
r esume/ CV, and &ndash; st ar t i ng i n ear l y 2012 &ndash; by l i st i ng t hemsel ves
i n t he Magent o Cer t i f i cat i on di r ect or y, a key r esour ce f or f i ndi ng and
ver i f yi ng Magent o Cer t i f i ed Devel oper s. </ l i >
</ ul >
<p><br / >We&r squo; ve made i t easy f or devel oper s t o pur chase voucher s,
downl oad st udy gui des, and r egi st er t o t ake t he exam. Vi si t t he Magent o U
Cer t i f i cat i on websi t e t o l ear n mor e about Magent o Devel oper Cer t i f i cat i on and
how i t can hel p your busi ness. </ p>' ,
) ,

ar r ay(
' t i t l e' => ' I nt r oduci ng Magent o Ent er pr i se Pr emi um! ' ,
' aut hor ' => ' Pedr amYashar el ' ,
' publ i shed_at ' => ' 2011- 11- 23' ,
' cont ent ' => ' <p>We have j ust l aunched t he Magent o Ent er pr i se
Pr emi umpackage, t he ul t i mat e packaged sol ut i on f or l ar ge- scal e eCommer ce
i mpl ement at i ons. Thi s package has been t ai l or ed speci f i cal l y f or l ar ge- scal e
eCommer ce i mpl ement at i ons t hat need t he scal e, exper t i se and suppor t
necessar y t o r un a hi gh vol ume busi ness. <br / ><br / >Her e ar e t he component s
we ar e pl eased t o of f er , as par t of t hi s new, pr emi umsol ut i on: <br / ><br
/ ></ p>
<ul >
<l i >Mul t i pl e Magent o Ent er pr i se l i censes - 2 pr oduct i on and 1 devel opment
l i cense</ l i >
<l i >Pl at i numl evel SLA Magent o Suppor t wi t h l i ve 24x7 phone suppor t </ l i >
<l i >Magent o Exper t Consul t i ng - ar chi t ect ur al advi sor y and compr ehensi ve code
r evi ew dedi cat ed t o your busi ness needs</ l i >
<l i >Tr ai ni ng cour se &l dquo; eCommer ce wi t h Magent o&r dquo; </ l i >
</ ul >
<p><br / >Wi t h t hi s new package, mer chant s get t he advant age of t he best - i n-
cl ass f eat ur es of Magent o Ent er pr i se, such as mul t i - st or e f r ont s wi t h a
si ngl e Admi n i nt er f ace, per si st ent shoppi ng car t , RMA, pr i vat e sal es,
mar ket i ng and mer chandi si ng t ool s and so much mor e, al l wi t h t he added

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 41
suppor t , consul t i ng, t r ai ni ng and scal abi l i t y t o meet t he needs of your
eCommer ce busi ness. <br / ><br / >We ar e ver y exci t ed t o of f er t hi s and i nvi t e
you t o l ear n mor e about t hi s new, pr emi umof f er i ng. </ p>'
) ,

ar r ay(
' t i t l e' => ' Magent o Suppor t s Facebook Open Gr aph 2. 0! ' ,
' aut hor ' => ' Bar uch Tol edano' ,
' publ i shed_at ' => ' 2011- 10- 18' ,
' cont ent ' => ' <p>The advant age of Facebook as a mar ket i ng t ool
f or your onl i ne st or e j ust became a l ot mor e power f ul . Magent o has i nt r oduced
suppor t f or t he new <st r ong>&l dquo; Want &r dquo; </ st r ong> and
<st r ong>&l dquo; Own&r dquo; </ st r ong> Facebook but t ons, dr i vi ng soci al based
t r af f i c f or al l Magent o onl i ne st or es. The soci al but t ons can be easi l y
i nst al l ed on pr oduct and cat al og pages and ar e pr ovi ded as a Magent o <a
t i t l e=" cor e" hr ef =" ht t p: / / www. magent ocommer ce. com/ magent o-
connect / Magent o+Cor e/ ext ensi on/ 8041/ soci al _f acebook" t ar get =" _bl ank" >cor e</ a>
ext ensi on f or Magent o Communi t y and Ent er pr i se. <br / ><br / >Cust omer s can now
expr ess t hemsel ves bet t er t han ever by addi ng i t ems t hey &l dquo; Want &r dquo;
on t hei r Facebook pages f or ever yone t o see and buy f or t hem) . Wi sh l i st s and
Facebook pr of i l es can now be cl osel y l i nked. <br / >&nbsp; <br / >Wi t h t he
&l dquo; Own&r dquo; but t on mar ket i ng goes or gani c as consumer s showcase i t ems
t hey ar e pr oud t o own. Your cust omer s become an ext ensi on of your mar ket i ng
ef f or t s as t hey ar e now abl e t o answer quest i ons, wr i t e r evi ews and pr ovi de
r ecommendat i ons on t he pr oduct s t hey own. <br / ><br / >Magent o i s t he f i r st
eCommer ce pl at f or mt o of f er i nt egr at i on f or t he &l dquo; Want &r dquo; and
&l dquo; Own&r dquo; but t ons wi t h t he Facebook Open Gr aph 2. 0 ext ensi on. Gi ve
your pr oduct s and your busi ness t he l at est Facebook connect i on. </ p>'
) ,
) ;

/ / Gener at e news i t ems
f or each ( $dat aRows as $dat a) {
$model - >set Dat a( $dat a) - >set Or i gDat a( ) - >save( ) ;
}
Events
By specifying an event in our code we mark a place where we want any listener to join
the process and perform some manipulations. In Magento we have the concept of the
Observer which is an analog for the Listener in other programming languages. When
some event fires, the system looks for every observer registered for the event and calls
its predefined (in conf i g. xml ) method.
The Observer pattern is a powerful tool for plugging in customizations in key flow areas
without overriding core classes and their methods. You can find more information about
this and other patterns in the Magento Knowledge Base
(http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-
_module_development_in_magento/customizing_magento_using_event-
observer_method)

42 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.

Extension Best Practices
Core module rewrites should be minimized.
In many situations the Observer pattern can be used to completely avoid any rewrites.
To illustrate how to use events, we will use an observer to monitor whether or not
individual news posts have been viewed. If a new post has been created within 3 days
(by default), our observer will add a block with a message to inform the user that news
was recently added.
This is just an illustration of how to use event-observer functionality in Magento. Same
feature may be done more easily in modules code without the use of observer at all.
Configuring our event
Before we start implementing our observer model, we need to configure our event in
conf i g. xml .
config.xml (events section)
<event s>
<bef or e_news_i t em_di spl ay>
<obser ver s>
<magent ost udy_news>
<cl ass>magent ost udy_news/ obser ver </ cl ass>
<met hod>bef or eNewsDi spl ayed</ met hod>
</ magent ost udy_news>
</ obser ver s>
</ bef or e_news_i t em_di spl ay>
</ event s>
Here you will find predefined method bef or eNewsDi spl ayed in the method
node. This method will be called when the bef or e_news_i t em_di spl ay event
occurs. Any other module may register on this event and perform additional data
manipulations.
Dispatching our event
Now that we have configured our event, we need to dispatch it in our code at the
appropriate place. In our case we will fire it in the i ndexCont r ol l er vi ewAct i on
method. Take a look at lines 62-75 in the code snippet above. First, we fire the event
and provide a parameter, and then we load and render the layout. Using this sequence
allows us to perform additional actions before displaying a news post. If we want to add
an event after a post is shown, we need to add the Mage: : di spat chEvent after
rendering the layout.


Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 43
Magentostudy_News_IndexController::viewAction()

Mage: : di spat chEvent ( ' bef or e_news_i t em_di spl ay' , ar r ay( ' news_i t em' =>
$model ) ) ;

$t hi s- >l oadLayout ( ) ;
$i t emBl ock = $t hi s- >get Layout ( ) - >get Bl ock( ' news. i t em' ) ;
i f ( $i t emBl ock) {
$l i st Bl ock = $t hi s- >get Layout ( ) - >get Bl ock( ' news. l i st ' ) ;
i f ( $l i st Bl ock) {
$page = ( i nt ) $l i st Bl ock- >get Cur r ent Page( ) ? ( i nt ) $l i st Bl ock-
>get Cur r ent Page( ) : 1;
} el se {
$page = 1;
}
$i t emBl ock- >set Page( $page) ;
}
$t hi s- >r ender Layout ( ) ;
Implementing our observer logic
Now we have everything we need to work with our event; all that is left is to implement
our observer to catch it. The observer is a model, so we will add it here:
Magent ost udy/ News/ Model / Obser ver . php
Magentostudy_News_Model_Observer

<?php
/ **
* News modul e obser ver
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Model _Obser ver
{
/ **
* Event bef or e show news i t emon f r ont end
* I f speci f i ed new post was added r ecent l y ( t er mi s def i ned i n conf i g)
we' l l see message about t hi s on f r ont end.
*
* @par amVar i en_Event _Obser ver $obser ver
*/
publ i c f unct i on bef or eNewsDi spl ayed( Var i en_Event _Obser ver $obser ver )
{
$newsI t em= $obser ver - >get Event ( ) - >get NewsI t em( ) ;
$cur r ent Dat e = Mage: : app( ) - >get Local e( ) - >dat e( ) ;
$newsCr eat edAt = Mage: : app( ) - >get Local e( ) - >dat e( st r t ot i me( $newsI t em-
>get Cr eat edAt ( ) ) ) ;
$daysDi f f er ence = $cur r ent Dat e- >sub( $newsCr eat edAt ) - >get Ti mest amp( ) /
( 60 * 60 * 24) ;
i f ( $daysDi f f er ence < Mage: : hel per ( ' magent ost udy_news' ) -
>get DaysDi f f er ence( ) ) {
Mage: : get Si ngl et on( ' cor e/ sessi on' ) -
>addSuccess( Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Recent l y added' ) ) ;
}

44 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
}
}
Development: The Admin Panel
Unlike the frontend which can have many layouts and themes, the Admin interface
structure stays constant across all themes.
Magento makes it easy to implement the most-used operations performed in the Admin
interface which are displaying lists of items and organizing user forms. Another helpful
feature the Admin interface provides is a centralized list of all system configuration
options available for editing. You do not need to write much code to organize config
options; Magento takes care of them on its own.
As previously mentioned, our extension Admin interface will allow us to create, edit,
save and delete news posts. To provide for this functionality, we will create a menu item
to access a list of posts and individual news posts respectively. Also we will add
configuration fields for enabling news posts on the frontend, setting the number of posts
per page, and setting the number of days a post is considered recent (see the section
"Development : The Front End - Preparing our helpers" ).
Similar to our frontend, we need to prepare some Magento components to implement
Admin panel functionality. We will need to implement following:
Specify Admin panel configuration
Specify routes for our pages
Prepare output for our pages
Prepare auxiliary helpers for additional data manipulation
Before we start implementation of our code, consider this note about structure:

Extension Best Practices
If your extension works both with the frontend and the Admin panel, place controllers and blocks related
to Admin functionality into a subfolder called admi nht ml to clarify block and controller scope.
Preparing Admin panel configuration
Before implementing any Admin-related features, we need to specify user permissions
for them.

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 45

Extension Best Practices
ACL restrictions should be implemented in both the admi nht ml . xml configuration file and the Admin
controller.
The admi nht ml . xml configuration file will define our menu items and their placement
as well as implement ACL instructions for them. This file will be located in the
module's et c folder with the other module-specific configuration files.
adminhtml.xml

<?xml ver si on=" 1. 0" ?>
<! - -
/ **
* Magent o Admi n conf i g
*
* @aut hor Magent o
*/
- - >
<conf i g>
<menu>
<news t r ansl at e=" t i t l e" modul e=" magent ost udy_news" >
<t i t l e>News</ t i t l e>
<sor t _or der >65</ sor t _or der >
<chi l dr en>
<manage t r ansl at e=" t i t l e" modul e=" magent ost udy_news" >
<t i t l e>Manage News</ t i t l e>
<act i on>admi nht ml / news</ act i on>
<sor t _or der >50</ sor t _or der >
</ manage>
</ chi l dr en>
</ news>
</ menu>

<acl >
<r esour ces>
<Admi n>
<chi l dr en>
<news t r ansl at e=" t i t l e" modul e=" magent ost udy_news" >
<t i t l e>News</ t i t l e>
<sor t _or der >65</ sor t _or der >
<chi l dr en>
<manage t r ansl at e=" t i t l e" >
<t i t l e>Manage News</ t i t l e>
<sor t _or der >0</ sor t _or der >
<chi l dr en>
<save t r ansl at e=" t i t l e" >
<t i t l e>Save News</ t i t l e>
<sor t _or der >0</ sor t _or der >
</ save>
<del et e t r ansl at e=" t i t l e" >
<t i t l e>Del et e News</ t i t l e>
<sor t _or der >10</ sor t _or der >

46 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
</ del et e>
</ chi l dr en>
</ manage>
</ chi l dr en>
</ news>
<syst em>
<chi l dr en>
<conf i g>
<chi l dr en>
<news t r ansl at e=" t i t l e"
modul e=" magent ost udy_news" >
<t i t l e>News Management </ t i t l e>
</ news>
</ chi l dr en>
</ conf i g>
</ chi l dr en>
</ syst em>
</ chi l dr en>
</ Admi n>
</ r esour ces>
</ acl >
</ conf i g>
As previously mentioned, we would also like to configure some store-related values
such as the number of posts per page. For this, we will create a separate file named
syst em. xml and store it in the module et c folder. After implementing this file, our
fields will appear in System >Configuration >General >News. Tab, label, and field
sequence can be specified via this syst em. xml file as well.
system.xml

<?xml ver si on=" 1. 0" ?>
<! - -
/ **
* Magent o Admi n conf i gur at i on sect i on conf i g
* @aut hor Magent o
*/
- - >
<conf i g>
<sect i ons>
<news>
<cl ass>separ at or - t op</ cl ass>
<l abel >News</ l abel >
<t ab>gener al </ t ab>
<f r ont end_t ype>t ext </ f r ont end_t ype>
<sor t _or der >500</ sor t _or der >
<show_i n_def aul t >1</ show_i n_def aul t >
<show_i n_websi t e>1</ show_i n_websi t e>
<show_i n_st or e>1</ show_i n_st or e>

<gr oups>
<vi ew t r ansl at e=" l abel " >
<l abel >News Vi ew Set t i ngs</ l abel >
<f r ont end_t ype>t ext </ f r ont end_t ype>

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 47
<sor t _or der >10</ sor t _or der >
<show_i n_def aul t >1</ show_i n_def aul t >
<show_i n_websi t e>1</ show_i n_websi t e>
<show_i n_st or e>1</ show_i n_st or e>
<f i el ds>
<enabl ed t r ansl at e=" l abel " >
<l abel >Enabl e News On Fr ont end</ l abel >
<f r ont end_t ype>sel ect </ f r ont end_t ype>

<sour ce_model >admi nht ml / syst em_conf i g_sour ce_yesno</ sour ce_model >
<sor t _or der >10</ sor t _or der >
<show_i n_def aul t >1</ show_i n_def aul t >
<show_i n_websi t e>1</ show_i n_websi t e>
<show_i n_st or e>1</ show_i n_st or e>
</ enabl ed>
<i t ems_per _page t r ansl at e=" l abel " >
<l abel >News Per Page</ l abel >
<comment >Empt y val ue i s t he same as def aul t
20. </ comment >
<sor t _or der >30</ sor t _or der >
<depends><enabl ed>1</ enabl ed></ depends>
<show_i n_def aul t >1</ show_i n_def aul t >
<show_i n_websi t e>1</ show_i n_websi t e>
<show_i n_st or e>1</ show_i n_st or e>
</ i t ems_per _page>
<days_di f f er ence t r ansl at e=" l abel " >
<l abel >Number of days si nce a post has been
mar ked as r ecent l y added</ l abel >
<comment >Empt y val ue i s t he same as def aul t
3. </ comment >
<sor t _or der >50</ sor t _or der >
<depends><enabl ed>1</ enabl ed></ depends>
<show_i n_def aul t >1</ show_i n_def aul t >
<show_i n_websi t e>1</ show_i n_websi t e>
<show_i n_st or e>1</ show_i n_st or e>
</ days_di f f er ence>
</ f i el ds>
</ vi ew>
</ gr oups>
</ news>
</ sect i ons>
</ conf i g>
Specifying our routes and request flow
Configuring our routes
Before implementing our controller, we need to configure our Admin routes
in conf i g. xml .


48 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
config.xml (specifying routes)

<Admi n>
<r out er s>
<admi nht ml >
<ar gs>
<modul es>
<Magent ost udy_News
bef or e=" Mage_admi nht ml " >Magent ost udy_News_admi nht ml </ Magent ost udy_News>
</ modul es>
</ ar gs>
</ admi nht ml >
</ r out er s>
</ Admi n>
Implementing our controller
According to our plan, we need the following actions for the Admin interface:
List of news posts
New news post
Edit news post
Save news post
Delete news post
Also, we need to implement gr i dAct i on to make our extension similar to other lists in
the Admin interface and the _i sAl l owed method to handle ACL instructions.
We'll add our controller
Magent ost udy/ News/ cont r ol l er / admi nht ml / NewsCont r ol l er . php
Magentostudy_News_adminhtml_NewsController

<?php
/ **
* News cont r ol l er
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_admi nht ml _NewsCont r ol l er ext ends
Mage_admi nht ml _Cont r ol l er _Act i on
{
/ **
* I ni t act i ons
*
* @r et ur n Magent ost udy_News_admi nht ml _NewsCont r ol l er
*/
pr ot ect ed f unct i on _i ni t Act i on( )
{
/ / l oad l ayout , set act i ve menu and br eadcr umbs
$t hi s- >l oadLayout ( )

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 49
- >_set Act i veMenu( ' news/ manage' )
- >_addBr eadcr umb(
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News' ) ,
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News' )
)
- >_addBr eadcr umb(
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Manage News' ) ,
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Manage News' )
)
;
r et ur n $t hi s;
}

/ **
* I ndex act i on
*/
publ i c f unct i on i ndexAct i on( )
{
$t hi s- >_t i t l e( $t hi s- >__( ' News' ) )
- >_t i t l e( $t hi s- >__( ' Manage News' ) ) ;

$t hi s- >_i ni t Act i on( ) ;
$t hi s- >r ender Layout ( ) ;
}

/ **
* Cr eat e new News i t em
*/
publ i c f unct i on newAct i on( )
{
/ / t he same f or mi s used t o cr eat e and edi t
$t hi s- >_f or war d( ' edi t ' ) ;
}

/ **
* Edi t News i t em
*/
publ i c f unct i on edi t Act i on( )
{
$t hi s- >_t i t l e( $t hi s- >__( ' News' ) )
- >_t i t l e( $t hi s- >__( ' Manage News' ) ) ;

/ / 1. i nst ance news model
/ * @var $model Magent ost udy_News_Model _I t em*/
$model = Mage: : get Model ( ' magent ost udy_news/ news' ) ;

/ / 2. i f I D exi st s, check i t and l oad dat a
$newsI d = $t hi s- >get Request ( ) - >get Par am( ' i d' ) ;
i f ( $newsI d) {
$model - >l oad( $newsI d) ;

i f ( ! $model - >get I d( ) ) {
$t hi s- >_get Sessi on( ) - >addEr r or (
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News i t emdoes not
exi st . ' )
) ;
r et ur n $t hi s- >_r edi r ect ( ' */ */ ' ) ;

50 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
}
/ / pr epar e t i t l e
$t hi s- >_t i t l e( $model - >get Ti t l e( ) ) ;
$br eadCr umb = Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Edi t I t em' ) ;
} el se {
$t hi s- >_t i t l e( Mage: : hel per ( ' magent ost udy_news' ) - >__( ' New I t em' ) ) ;
$br eadCr umb = Mage: : hel per ( ' magent ost udy_news' ) - >__( ' New I t em' ) ;
}

/ / I ni t br eadcr umbs
$t hi s- >_i ni t Act i on( ) - >_addBr eadcr umb( $br eadCr umb, $br eadCr umb) ;

/ / 3. Set ent er ed dat a i f t her e was an er r or dur i ng save
$dat a = Mage: : get Si ngl et on( ' admi nht ml / sessi on' ) - >get For mDat a( t r ue) ;
i f ( ! empt y( $dat a) ) {
$model - >addDat a( $dat a) ;
}

/ / 4. Regi st er model t o use l at er i n bl ocks
Mage: : r egi st er ( ' news_i t em' , $model ) ;

/ / 5. r ender l ayout
$t hi s- >r ender Layout ( ) ;
}

/ **
* Save act i on
*/
publ i c f unct i on saveAct i on( )
{
$r edi r ect Pat h = ' */ *' ;
$r edi r ect Par ams = ar r ay( ) ;

/ / check i f dat a sent
$dat a = $t hi s- >get Request ( ) - >get Post ( ) ;
i f ( $dat a) {
$dat a = $t hi s- >_f i l t er Post Dat a( $dat a) ;
/ / i ni t model and set dat a
/ * @var $model Magent ost udy_News_Model _I t em*/
$model = Mage: : get Model ( ' magent ost udy_news/ news' ) ;

/ / i f news i t emexi st s, t r y t o l oad i t
$newsI d = $t hi s- >get Request ( ) - >get Par am( ' news_i d' ) ;
i f ( $newsI d) {
$model - >l oad( $newsI d) ;
}
/ / save i mage dat a and r emove f r omdat a ar r ay
i f ( i sset ( $dat a[ ' i mage' ] ) ) {
$i mageDat a = $dat a[ ' i mage' ] ;
unset ( $dat a[ ' i mage' ] ) ;
} el se {
$i mageDat a = ar r ay( ) ;
}
$model - >addDat a( $dat a) ;

t r y {
$hasEr r or = f al se;

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 51
/ * @var $i mageHel per Magent ost udy_News_Hel per _I mage */
$i mageHel per = Mage: : hel per ( ' magent ost udy_news/ i mage' ) ;
/ / r emove i mage

i f ( i sset ( $i mageDat a[ ' del et e' ] ) && $model - >get I mage( ) ) {
$i mageHel per - >r emoveI mage( $model - >get I mage( ) ) ;
$model - >set I mage( nul l ) ;
}

/ / upl oad new i mage
$i mageFi l e = $i mageHel per - >upl oadI mage( ' i mage' ) ;
i f ( $i mageFi l e) {
i f ( $model - >get I mage( ) ) {
$i mageHel per - >r emoveI mage( $model - >get I mage( ) ) ;
}
$model - >set I mage( $i mageFi l e) ;
}
/ / save t he dat a
$model - >save( ) ;

/ / di spl ay success message
$t hi s- >_get Sessi on( ) - >addSuccess(
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' The news i t emhas
been saved. ' )
) ;

/ / check i f ' Save and Cont i nue'
i f ( $t hi s- >get Request ( ) - >get Par am( ' back' ) ) {
$r edi r ect Pat h = ' */ */ edi t ' ;
$r edi r ect Par ams = ar r ay( ' i d' => $model - >get I d( ) ) ;
}
} cat ch ( Mage_Cor e_Except i on $e) {
$hasEr r or = t r ue;
$t hi s- >_get Sessi on( ) - >addEr r or ( $e- >get Message( ) ) ;
} cat ch ( Except i on $e) {
$hasEr r or = t r ue;
$t hi s- >_get Sessi on( ) - >addExcept i on( $e,
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' An er r or occur r ed
whi l e savi ng t he news i t em. ' )
) ;
}

i f ( $hasEr r or ) {
$t hi s- >_get Sessi on( ) - >set For mDat a( $dat a) ;
$r edi r ect Pat h = ' */ */ edi t ' ;
$r edi r ect Par ams = ar r ay( ' i d' => $t hi s- >get Request ( ) -
>get Par am( ' i d' ) ) ;
}
}

$t hi s- >_r edi r ect ( $r edi r ect Pat h, $r edi r ect Par ams) ;
}

/ **
* Del et e act i on
*/
publ i c f unct i on del et eAct i on( )

52 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
{
/ / check i f we know what shoul d be del et ed
$i t emI d = $t hi s- >get Request ( ) - >get Par am( ' i d' ) ;
i f ( $i t emI d) {
t r y {
/ / i ni t model and del et e
/ ** @var $model Magent ost udy_News_Model _I t em*/
$model = Mage: : get Model ( ' magent ost udy_news/ news' ) ;
$model - >l oad( $i t emI d) ;
i f ( ! $model - >get I d( ) ) {
Mage: : t hr owExcept i on( Mage: : hel per ( ' magent ost udy_news' ) -
>__( ' Unabl e t o f i nd a news i t em. ' ) ) ;
}
$model - >del et e( ) ;

/ / di spl ay success message
$t hi s- >_get Sessi on( ) - >addSuccess(
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' The news i t emhas
been del et ed. ' )
) ;
} cat ch ( Mage_Cor e_Except i on $e) {
$t hi s- >_get Sessi on( ) - >addEr r or ( $e- >get Message( ) ) ;
} cat ch ( Except i on $e) {
$t hi s- >_get Sessi on( ) - >addExcept i on( $e,
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' An er r or occur r ed
whi l e del et i ng t he news i t em. ' )
) ;
}
}

/ / go t o gr i d
$t hi s- >_r edi r ect ( ' */ */ ' ) ;
}

/ **
* Check t he per mi ssi on t o r un i t
*
* @r et ur n bool ean
*/
pr ot ect ed f unct i on _i sAl l owed( )
{
swi t ch ( $t hi s- >get Request ( ) - >get Act i onName( ) ) {
case ' new' :
case ' save' :
r et ur n Mage: : get Si ngl et on( ' Admi n/ sessi on' ) -
>i sAl l owed( ' news/ manage/ save' ) ;
br eak;
case ' del et e' :
r et ur n Mage: : get Si ngl et on( ' Admi n/ sessi on' ) -
>i sAl l owed( ' news/ manage/ del et e' ) ;
br eak;
def aul t :
r et ur n Mage: : get Si ngl et on( ' Admi n/ sessi on' ) -
>i sAl l owed( ' news/ manage' ) ;
br eak;
}
}

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 53

/ **
* Fi l t er i ng post ed dat a. Conver t i ng l ocal i zed dat a i f needed
*
* @par amar r ay
* @r et ur n ar r ay
*/
pr ot ect ed f unct i on _f i l t er Post Dat a( $dat a)
{
$dat a = $t hi s- >_f i l t er Dat es( $dat a, ar r ay( ' t i me_publ i shed' ) ) ;
r et ur n $dat a;
}

/ **
* Gr i d aj ax act i on
*/
publ i c f unct i on gr i dAct i on( )
{
$t hi s- >l oadLayout ( ) ;
$t hi s- >r ender Layout ( ) ;
}

/ **
* Fl ush News Post s I mages Cache act i on
*/
publ i c f unct i on f l ushAct i on( )
{
i f ( Mage: : hel per ( ' magent ost udy_news/ i mage' ) - >f l ushI magesCache( ) ) {
$t hi s- >_get Sessi on( ) - >addSuccess( ' Cache successf ul l y f l ushed' ) ;
} el se {
$t hi s- >_get Sessi on( ) - >addEr r or ( ' Ther e was er r or dur i ng f l ushi ng
cache' ) ;
}
$t hi s- >_f or war d( ' i ndex' ) ;
}
}
Preparing our output
As mentioned above, if we do not need a particular piece of output we should not add it.
In our case, all we need for the Admin are layout and blocks
Configuring our output
Similarly to the frontend, we need to configure our output before we implement it. We
specified the blocks for this when we configured our frontend blocks earlier, so we will
just configure our admi nht ml layout in conf i g. xml .
config.xml (specifying adminhtml layout)

<admi nht ml >
<l ayout >
<updat es>

54 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
<magent ost udy_news>
<f i l e>magent ost udy_news. xml </ f i l e>
</ magent ost udy_news>
</ updat es>
</ l ayout >
</ admi nht ml >
Implementing our layout
As shown above, our controller's actions load and render a layout. This layout doesn't
exist yet, so next we'll create it.
Magentostudy_news.xml

<?xml ver si on=" 1. 0" ?>
<! - -
/ **
* Magent o backend l ayout
*
* @aut hor Magent o
*/
- - >
<l ayout >
<admi nht ml _news_i ndex>
<r ef er ence name=" cont ent " >
<bl ock t ype=" magent ost udy_news/ admi nht ml _news" name=" news" / >
</ r ef er ence>
</ admi nht ml _news_i ndex>

<admi nht ml _news_gr i d>
<bl ock t ype=" magent ost udy_news/ admi nht ml _news_gr i d" name=" r oot " / >
</ admi nht ml _news_gr i d>

<admi nht ml _news_new>
<updat e handl e=" admi nht ml _news_edi t " / >
</ admi nht ml _news_new>

<admi nht ml _news_edi t >
<updat e handl e=" edi t or " / >
<r ef er ence name=" cont ent " >
<bl ock t ype=" magent ost udy_news/ admi nht ml _news_edi t "
name=" news_edi t " / >
</ r ef er ence>
<r ef er ence name=" l ef t " >
<bl ock t ype=" magent ost udy_news/ admi nht ml _news_edi t _t abs"
name=" news_edi t _t abs" >
<bl ock t ype=" magent ost udy_news/ admi nht ml _news_edi t _t ab_mai n"
name=" news_edi t _t ab_mai n" / >
<bl ock
t ype=" magent ost udy_news/ admi nht ml _news_edi t _t ab_cont ent "
name=" news_edi t _t ab_cont ent " / >
<bl ock t ype=" magent ost udy_news/ admi nht ml _news_edi t _t ab_i mage"
name=" news_edi t _t ab_i mage" / >

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 55
<act i on
met hod=" addTab" ><name>mai n_sect i on</ name><bl ock>news_edi t _t ab_mai n</ bl ock></ a
ct i on>
<act i on
met hod=" addTab" ><name>cont ent _sect i on</ name><bl ock>news_edi t _t ab_cont ent </ bl o
ck></ act i on>
<act i on
met hod=" addTab" ><name>i mage_sect i on</ name><bl ock>news_edi t _t ab_i mage</ bl ock><
/ act i on>
</ bl ock>
</ r ef er ence>
</ admi nht ml _news_edi t >
</ l ayout >
Implementing our blocks
As mentioned above, the Admin panel has a similar structure for all of its components.
The blocks structure is also similar; they all use a grid that is connected by edit forms,
each of which has different tabs.
To illustrate our Admin panel blocks structure, observe the following schema (Figure 6):

56 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.

Figure 6: Our Admin panel block structure
We will use the following blocks:
admi nht ml _news - grid container
admi nht ml _news_gr i d - grid
admi nht ml _news_edi t - edit form container (the same forms are used for
creating a new post and editing an existing post)

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 57
admi nht ml _news_edi t _f or m- edit form
admi nht ml _news_edi t _t abs - edit form tabs
admi nht ml _news_edi t _f or m_el ement _i mage - specific form element to
work with images
admi nht ml _news_edi t _t ab_cont ent - edit form content tab
admi nht ml _news_edi t _t ab_i mage - edit form image tab
admi nht ml _news_edi t _t ab_mai n - edit form main tab
Here's our Admin panel block implementation:
Magentostudy_News_Block_adminhtml_News

<?php
/ **
* News Li st Admi n gr i d cont ai ner
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_admi nht ml _News ext ends
Mage_admi nht ml _Bl ock_Wi dget _Gr i d_Cont ai ner
{
/ **
* Bl ock const r uct or
*/
publ i c f unct i on __const r uct ( )
{
$t hi s- >_bl ockGr oup = ' magent ost udy_news' ;
$t hi s- >_cont r ol l er = ' admi nht ml _news' ;
$t hi s- >_header Text = Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Manage
News' ) ;

par ent : : __const r uct ( ) ;

i f ( Mage: : hel per ( ' magent ost udy_news/ Admi n' ) - >i sAct i onAl l owed( ' save' ) )
{
$t hi s- >_updat eBut t on( ' add' , ' l abel ' ,
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Add New News' ) ) ;
} el se {
$t hi s- >_r emoveBut t on( ' add' ) ;
}
$t hi s- >addBut t on(
' news_f l ush_i mages_cache' ,
ar r ay(
' l abel ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Fl ush
I mages Cache' ) ,
' oncl i ck' => ' set Locat i on( \ ' ' . $t hi s- >get Ur l ( ' */ */ f l ush' )
. ' \ ' ) ' ,
)
) ;

}
}


58 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.

Magentostudy_News_Block_adminhtml_News_Edit

<?php
/ **
* News Li st Admi n edi t f or mcont ai ner
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_admi nht ml _News_Edi t ext ends
Mage_admi nht ml _Bl ock_Wi dget _For m_Cont ai ner
{
/ **
* I ni t i al i ze edi t f or mcont ai ner
*
*/
publ i c f unct i on __const r uct ( )
{
$t hi s- >_obj ect I d = ' i d' ;
$t hi s- >_bl ockGr oup = ' magent ost udy_news' ;
$t hi s- >_cont r ol l er = ' admi nht ml _news' ;

par ent : : __const r uct ( ) ;

i f ( Mage: : hel per ( ' magent ost udy_news/ Admi n' ) - >i sAct i onAl l owed( ' save' ) )
{
$t hi s- >_updat eBut t on( ' save' , ' l abel ' ,
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Save News I t em' ) ) ;
$t hi s- >_addBut t on( ' saveandcont i nue' , ar r ay(
' l abel ' => Mage: : hel per ( ' admi nht ml ' ) - >__( ' Save and Cont i nue
Edi t ' ) ,
' oncl i ck' => ' saveAndCont i nueEdi t ( ) ' ,
' cl ass' => ' save' ,
) , - 100) ;
} el se {
$t hi s- >_r emoveBut t on( ' save' ) ;
}

i f ( Mage: : hel per ( ' magent ost udy_news/ Admi n' ) -
>i sAct i onAl l owed( ' del et e' ) ) {
$t hi s- >_updat eBut t on( ' del et e' , ' l abel ' ,
Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Del et e News I t em' ) ) ;
} el se {
$t hi s- >_r emoveBut t on( ' del et e' ) ;
}

$t hi s- >_f or mScr i pt s[ ] = "
f unct i on t oggl eEdi t or ( ) {
i f ( t i nyMCE. get I nst anceByI d( ' page_cont ent ' ) == nul l ) {
t i nyMCE. execCommand( ' mceAddCont r ol ' , f al se,
' page_cont ent ' ) ;
} el se {
t i nyMCE. execCommand( ' mceRemoveCont r ol ' , f al se,
' page_cont ent ' ) ;
}
}

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 59

f unct i on saveAndCont i nueEdi t ( ) {
edi t For m. submi t ( $( ' edi t _f or m' ) . act i on+' back/ edi t / ' ) ;
}
" ;
}

/ **
* Ret r i eve t ext f or header el ement dependi ng on l oaded page
*
* @r et ur n st r i ng
*/
publ i c f unct i on get Header Text ( )
{
$model = Mage: : hel per ( ' magent ost udy_news' ) - >get NewsI t emI nst ance( ) ;
i f ( $model - >get I d( ) ) {
r et ur n Mage: : hel per ( ' magent ost udy_news' ) - >__( " Edi t News I t em
' %s' " ,
$t hi s- >escapeHt ml ( $model - >get Ti t l e( ) ) ) ;
} el se {
r et ur n Mage: : hel per ( ' magent ost udy_news' ) - >__( ' New News I t em' ) ;
}
}
}

Magentostudy_News_Block_adminhtml_News_Grid

<?php
/ **
* News Li st Admi n gr i d
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_admi nht ml _News_Gr i d ext ends
Mage_admi nht ml _Bl ock_Wi dget _Gr i d
{
/ **
* I ni t Gr i d def aul t pr oper t i es
*
*/
publ i c f unct i on __const r uct ( )
{
par ent : : __const r uct ( ) ;
$t hi s- >set I d( ' news_l i st _gr i d' ) ;
$t hi s- >set Def aul t Sor t ( ' cr eat ed_at ' ) ;
$t hi s- >set Def aul t Di r ( ' DESC' ) ;
$t hi s- >set SavePar amet er sI nSessi on( t r ue) ;
$t hi s- >set UseAj ax( t r ue) ;
}

/ **
* Pr epar e col l ect i on f or Gr i d
*
* @r et ur n Magent ost udy_News_Bl ock_admi nht ml _Gr i d
*/
pr ot ect ed f unct i on _pr epar eCol l ect i on( )

60 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
{
$col l ect i on = Mage: : get Model ( ' magent ost udy_news/ news' ) -
>get Resour ceCol l ect i on( ) ;

$t hi s- >set Col l ect i on( $col l ect i on) ;
r et ur n par ent : : _pr epar eCol l ect i on( ) ;
}

/ **
* Pr epar e Gr i d col umns
*
* @r et ur n Mage_admi nht ml _Bl ock_Cat al og_Sear ch_Gr i d
*/
pr ot ect ed f unct i on _pr epar eCol umns( )
{
$t hi s- >addCol umn( ' news_i d' , ar r ay(
' header ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' I D' ) ,
' wi dt h' => ' 50px' ,
' i ndex' => ' news_i d' ,
) ) ;

$t hi s- >addCol umn( ' t i t l e' , ar r ay(
' header ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News
Ti t l e' ) ,
' i ndex' => ' t i t l e' ,
) ) ;

$t hi s- >addCol umn( ' aut hor ' , ar r ay(
' header ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Aut hor ' ) ,
' i ndex' => ' aut hor ' ,
) ) ;

$t hi s- >addCol umn( ' publ i shed_at ' , ar r ay(
' header ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Publ i shed
On' ) ,
' sor t abl e' => t r ue,
' wi dt h' => ' 170px' ,
' i ndex' => ' publ i shed_at ' ,
' t ype' => ' dat e' ,
) ) ;

$t hi s- >addCol umn( ' cr eat ed_at ' , ar r ay(
' header ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Cr eat ed' ) ,
' sor t abl e' => t r ue,
' wi dt h' => ' 170px' ,
' i ndex' => ' cr eat ed_at ' ,
' t ype' => ' dat et i me' ,
) ) ;

$t hi s- >addCol umn( ' act i on' ,
ar r ay(
' header ' => Mage: : hel per ( ' magent ost udy_news' ) -
>__( ' Act i on' ) ,
' wi dt h' => ' 100px' ,
' t ype' => ' act i on' ,
' get t er ' => ' get I d' ,
' act i ons' => ar r ay( ar r ay(

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 61
' capt i on' => Mage: : hel per ( ' magent ost udy_news' ) -
>__( ' Edi t ' ) ,
' ur l ' => ar r ay( ' base' => ' */ */ edi t ' ) ,
' f i el d' => ' i d'
) ) ,
' f i l t er ' => f al se,
' sor t abl e' => f al se,
' i ndex' => ' news' ,
) ) ;

r et ur n par ent : : _pr epar eCol umns( ) ;
}

/ **
* Ret ur n r ow URL f or j s event handl er s
*
* @r et ur n st r i ng
*/
publ i c f unct i on get RowUr l ( $r ow)
{
r et ur n $t hi s- >get Ur l ( ' */ */ edi t ' , ar r ay( ' i d' => $r ow- >get I d( ) ) ) ;
}

/ **
* Gr i d ur l get t er
*
* @r et ur n st r i ng cur r ent gr i d ur l
*/
publ i c f unct i on get Gr i dUr l ( )
{
r et ur n $t hi s- >get Ur l ( ' */ */ gr i d' , ar r ay( ' _cur r ent ' => t r ue) ) ;
}
}

Magentostudy_News_Block_adminhtml_News_Edit_Form

<?php
/ **
* News Li st Admi n edi t f or mbl ock
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_admi nht ml _News_Edi t _For mext ends
Mage_admi nht ml _Bl ock_Wi dget _For m
{
/ **
* Pr epar e f or mact i on
*
* @r et ur n Magent ost udy_News_Bl ock_admi nht ml _News_Edi t _For m
*/
pr ot ect ed f unct i on _pr epar eFor m( )
{
$f or m= new Var i en_Dat a_For m( ar r ay(
' i d' => ' edi t _f or m' ,
' act i on' => $t hi s- >get Ur l ( ' */ */ save' ) ,
' met hod' => ' post ' ,

62 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
' enct ype' => ' mul t i par t / f or m- dat a'
) ) ;

$f or m- >set UseCont ai ner ( t r ue) ;
$t hi s- >set For m( $f or m) ;
r et ur n par ent : : _pr epar eFor m( ) ;
}
}

Magentostudy_News_Block_adminhtml_News_Edit_Tabs

<?php
/ **
* News Li st Admi n edi t f or mt abs bl ock
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_admi nht ml _News_Edi t _Tabs ext ends
Mage_admi nht ml _Bl ock_Wi dget _Tabs
{
/ **
* I ni t i al i ze t abs and def i ne t abs bl ock set t i ngs
*
*/
publ i c f unct i on __const r uct ( )
{
par ent : : __const r uct ( ) ;
$t hi s- >set I d( ' page_t abs' ) ;
$t hi s- >set Dest El ement I d( ' edi t _f or m' ) ;
$t hi s- >set Ti t l e( Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News I t em
I nf o' ) ) ;
}
}

Magentostudy_News_Block_adminhtml_News_Edit_Form_Elemen
t_Image

<?php
/ **
* Cust omi mage f or mel ement t hat gener at es cor r ect t humbnai l i mage URL
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_admi nht ml _News_Edi t _For m_El ement _I mage ext ends
Var i en_Dat a_For m_El ement _I mage
{
/ **
* Get i mage pr evi ew ur l
*
* @r et ur n st r i ng
*/
pr ot ect ed f unct i on _get Ur l ( )
{
$ur l = f al se;

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 63
i f ( $t hi s- >get Val ue( ) ) {
$ur l = Mage: : hel per ( ' magent ost udy_news/ i mage' ) - >get BaseUr l ( ) .
' / ' . $t hi s- >get Val ue( ) ;
}
r et ur n $ur l ;
}
}

Magentostudy_News_Block_adminhtml_News_Edit_Tab_Content

<?php
/ **
* News Li st Admi n edi t f or mcont ent t ab
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_admi nht ml _News_Edi t _Tab_Cont ent
ext ends Mage_admi nht ml _Bl ock_Wi dget _For m
i mpl ement s Mage_admi nht ml _Bl ock_Wi dget _Tab_I nt er f ace
{
/ **
* Load WYSI WYG on demand and pr epar e l ayout
*
* @r et ur n Magent ost udy_News_Bl ock_admi nht ml _News_Edi t _Tab_Cont ent
*/
pr ot ect ed f unct i on _pr epar eLayout ( )
{
par ent : : _pr epar eLayout ( ) ;
i f ( Mage: : get Si ngl et on( ' cms/ wysi wyg_conf i g' ) - >i sEnabl ed( ) ) {
$t hi s- >get Layout ( ) - >get Bl ock( ' head' ) - >set CanLoadTi nyMce( t r ue) ;
}
r et ur n $t hi s;
}

/ **
* Pr epar es t ab f or m
*
* @r et ur n Mage_admi nht ml _Bl ock_Wi dget _For m
*/
pr ot ect ed f unct i on _pr epar eFor m( )
{
$model = Mage: : hel per ( ' magent ost udy_news' ) - >get NewsI t emI nst ance( ) ;

/ **
* Checki ng i f user have per mi ssi ons t o save i nf or mat i on
*/
i f ( Mage: : hel per ( ' magent ost udy_news/ Admi n' ) - >i sAct i onAl l owed( ' save' ) )
{
$i sEl ement Di sabl ed = f al se;
} el se {
$i sEl ement Di sabl ed = t r ue;
}

$f or m= new Var i en_Dat a_For m( ) ;

$f or m- >set Ht ml I dPr ef i x( ' news_cont ent _' ) ;

64 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.

$f i el dset = $f or m- >addFi el dset ( ' cont ent _f i el dset ' , ar r ay(
' l egend' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Cont ent ' ) ,
' cl ass' => ' f i el dset - wi de'
) ) ;

$wysi wygConf i g = Mage: : get Si ngl et on( ' cms/ wysi wyg_conf i g' ) -
>get Conf i g( ar r ay(
' t ab_i d' => $t hi s- >get TabI d( )
) ) ;

$cont ent Fi el d = $f i el dset - >addFi el d( ' cont ent ' , ' edi t or ' , ar r ay(
' name' => ' cont ent ' ,
' st yl e' => ' hei ght : 36em; ' ,
' r equi r ed' => t r ue,
' di sabl ed' => $i sEl ement Di sabl ed,
' conf i g' => $wysi wygConf i g
) ) ;

/ / Set t i ng cust omr ender er f or cont ent f i el d t o r emove l abel col umn
$r ender er = $t hi s- >get Layout ( ) -
>cr eat eBl ock( ' admi nht ml / wi dget _f or m_r ender er _f i el dset _el ement ' )
- >set Templ at e( ' cms/ page/ edi t / f or m/ r ender er / cont ent . pht ml ' ) ;
$cont ent Fi el d- >set Render er ( $r ender er ) ;

$f or m- >set Val ues( $model - >get Dat a( ) ) ;
$t hi s- >set For m( $f or m) ;

Mage: : di spat chEvent ( ' admi nht ml _news_edi t _t ab_cont ent _pr epar e_f or m' ,
ar r ay( ' f or m' => $f or m) ) ;

r et ur n par ent : : _pr epar eFor m( ) ;
}

/ **
* Pr epar e l abel f or t ab
*
* @r et ur n st r i ng
*/
publ i c f unct i on get TabLabel ( )
{
r et ur n Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Cont ent ' ) ;
}

/ **
* Pr epar e t i t l e f or t ab
*
* @r et ur n st r i ng
*/
publ i c f unct i on get TabTi t l e( )
{
r et ur n Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Cont ent ' ) ;
}

/ **
* Ret ur ns st at us f l ag about t hi s t ab can be shown or not
*

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 65
* @r et ur n t r ue
*/
publ i c f unct i on canShowTab( )
{
r et ur n t r ue;
}

/ **
* Ret ur ns st at us f l ag about t hi s t ab hi dden or not
*
* @r et ur n t r ue
*/
publ i c f unct i on i sHi dden( )
{
r et ur n f al se;
}
}

Magentostudy_News_Block_adminhtml_News_Edit_Tab_Image

<?php
/ **
* News Li st Admi n edi t f or mi mage t ab
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_admi nht ml _News_Edi t _Tab_I mage
ext ends Mage_admi nht ml _Bl ock_Wi dget _For m
i mpl ement s Mage_admi nht ml _Bl ock_Wi dget _Tab_I nt er f ace
{
/ **
* Pr epar e f or mel ement s
*
* @r et ur n Mage_admi nht ml _Bl ock_Wi dget _For m
*/
pr ot ect ed f unct i on _pr epar eFor m( )
{
/ **
* Checki ng i f user have per mi ssi ons t o save i nf or mat i on
*/
i f ( Mage: : hel per ( ' magent ost udy_news/ Admi n' ) - >i sAct i onAl l owed( ' save' ) )
{
$i sEl ement Di sabl ed = f al se;
} el se {
$i sEl ement Di sabl ed = t r ue;
}

$f or m= new Var i en_Dat a_For m( ) ;

$f or m- >set Ht ml I dPr ef i x( ' news_i mage_' ) ;

$model = Mage: : hel per ( ' magent ost udy_news' ) - >get NewsI t emI nst ance( ) ;


$f i el dset = $f or m- >addFi el dset ( ' i mage_f i el dset ' , ar r ay(

66 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
' l egend' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' I mage
Thumbnai l ' ) , ' cl ass' => ' f i el dset - wi de'
) ) ;

$t hi s- >_addEl ement Types( $f i el dset ) ;

$f i el dset - >addFi el d( ' i mage' , ' i mage' , ar r ay(
' name' => ' i mage' ,
' l abel ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' I mage' ) ,
' t i t l e' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' I mage' ) ,
' r equi r ed' => f al se,
' di sabl ed' => $i sEl ement Di sabl ed
) ) ;

Mage: : di spat chEvent ( ' admi nht ml _news_edi t _t ab_i mage_pr epar e_f or m' ,
ar r ay( ' f or m' => $f or m) ) ;

$f or m- >set Val ues( $model - >get Dat a( ) ) ;
$t hi s- >set For m( $f or m) ;

r et ur n par ent : : _pr epar eFor m( ) ;
}

/ **
* Pr epar e l abel f or t ab
*
* @r et ur n st r i ng
*/
publ i c f unct i on get TabLabel ( )
{
r et ur n Mage: : hel per ( ' magent ost udy_news' ) - >__( ' I mage Thumbnai l ' ) ;
}

/ **
* Pr epar e t i t l e f or t ab
*
* @r et ur n st r i ng
*/
publ i c f unct i on get TabTi t l e( )
{
r et ur n Mage: : hel per ( ' magent ost udy_news' ) - >__( ' I mage Thumbnai l ' ) ;
}

/ **
* Ret ur ns st at us f l ag about t hi s t ab can be showen or not
*
* @r et ur n t r ue
*/
publ i c f unct i on canShowTab( )
{
r et ur n t r ue;
}

/ **
* Ret ur ns st at us f l ag about t hi s t ab hi dden or not
*
* @r et ur n t r ue

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 67
*/
publ i c f unct i on i sHi dden( )
{
r et ur n f al se;
}

/ **
* Ret r i eve pr edef i ned addi t i onal el ement t ypes
*
* @r et ur n ar r ay
*/
pr ot ect ed f unct i on _get Addi t i onal El ement Types( )
{
r et ur n ar r ay(
' i mage' => Mage: : get Conf i g( ) -
>get Bl ockCl assName( ' magent ost udy_news/ admi nht ml _news_edi t _f or m_el ement _i mage'
)
) ;
}
}

Magentostudy_News_Block_adminhtml_News_Edit_Tab_Main

<?php
/ **
* News Li st Admi n edi t f or mmai n t ab
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Bl ock_admi nht ml _News_Edi t _Tab_Mai n
ext ends Mage_admi nht ml _Bl ock_Wi dget _For m
i mpl ement s Mage_admi nht ml _Bl ock_Wi dget _Tab_I nt er f ace
{
/ **
* Pr epar e f or mel ement s f or t ab
*
* @r et ur n Mage_admi nht ml _Bl ock_Wi dget _For m
*/
pr ot ect ed f unct i on _pr epar eFor m( )
{
$model = Mage: : hel per ( ' magent ost udy_news' ) - >get NewsI t emI nst ance( ) ;

/ **
* Checki ng i f user have per mi ssi ons t o save i nf or mat i on
*/
i f ( Mage: : hel per ( ' magent ost udy_news/ Admi n' ) - >i sAct i onAl l owed( ' save' ) )
{
$i sEl ement Di sabl ed = f al se;
} el se {
$i sEl ement Di sabl ed = t r ue;
}

$f or m= new Var i en_Dat a_For m( ) ;

$f or m- >set Ht ml I dPr ef i x( ' news_mai n_' ) ;


68 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
$f i el dset = $f or m- >addFi el dset ( ' base_f i el dset ' , ar r ay(
' l egend' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News I t em
I nf o' )
) ) ;

i f ( $model - >get I d( ) ) {
$f i el dset - >addFi el d( ' news_i d' , ' hi dden' , ar r ay(
' name' => ' news_i d' ,
) ) ;
}

$f i el dset - >addFi el d( ' t i t l e' , ' t ext ' , ar r ay(
' name' => ' t i t l e' ,
' l abel ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News
Ti t l e' ) ,
' t i t l e' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News
Ti t l e' ) ,
' r equi r ed' => t r ue,
' di sabl ed' => $i sEl ement Di sabl ed
) ) ;

$f i el dset - >addFi el d( ' aut hor ' , ' t ext ' , ar r ay(
' name' => ' aut hor ' ,
' l abel ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Aut hor ' ) ,
' t i t l e' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Aut hor ' ) ,
' r equi r ed' => t r ue,
' di sabl ed' => $i sEl ement Di sabl ed
) ) ;

$f i el dset - >addFi el d( ' publ i shed_at ' , ' dat e' , ar r ay(
' name' => ' publ i shed_at ' ,
' f or mat ' => Mage: : app( ) - >get Local e( ) -
>get Dat eFor mat ( Mage_Cor e_Model _Local e: : FORMAT_TYPE_SHORT) ,
' i mage' => $t hi s- >get Ski nUr l ( ' i mages/ gr i d- cal . gi f ' ) ,
' l abel ' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Publ i shi ng
Dat e' ) ,
' t i t l e' => Mage: : hel per ( ' magent ost udy_news' ) - >__( ' Publ i shi ng
Dat e' ) ,
' r equi r ed' => t r ue
) ) ;

Mage: : di spat chEvent ( ' admi nht ml _news_edi t _t ab_mai n_pr epar e_f or m' ,
ar r ay( ' f or m' => $f or m) ) ;

$f or m- >set Val ues( $model - >get Dat a( ) ) ;
$t hi s- >set For m( $f or m) ;

r et ur n par ent : : _pr epar eFor m( ) ;
}

/ **
* Pr epar e l abel f or t ab
*
* @r et ur n st r i ng
*/
publ i c f unct i on get TabLabel ( )
{

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 69
r et ur n Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News I nf o' ) ;
}

/ **
* Pr epar e t i t l e f or t ab
*
* @r et ur n st r i ng
*/
publ i c f unct i on get TabTi t l e( )
{
r et ur n Mage: : hel per ( ' magent ost udy_news' ) - >__( ' News I nf o' ) ;
}

/ **
* Ret ur ns st at us f l ag about t hi s t ab can be shown or not
*
* @r et ur n t r ue
*/
publ i c f unct i on canShowTab( )
{
r et ur n t r ue;
}

/ **
* Ret ur ns st at us f l ag about t hi s t ab hi dden or not
*
* @r et ur n t r ue
*/
publ i c f unct i on i sHi dden( )
{
r et ur n f al se;
}
}
Preparing our helpers
As mentioned in the frontend helpers section, helpers are auxiliary classes that
implement commonly used business logic. In the case of our Admin panel, we'll use
helpers to check permissions.
We have one helper, Admi n. php, with the following code:
Magentostudy_News_Helper_Admin

<?php
/ **
* News Admi n hel per
*
* @aut hor Magent o
*/
cl ass Magent ost udy_News_Hel per _Admi n ext ends Mage_Cor e_Hel per _Abst r act
{
/ **
* Check per mi ssi on f or passed act i on

70 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
*
* @par amst r i ng $act i on
* @r et ur n bool
*/
publ i c f unct i on i sAct i onAl l owed( $act i on)
{
r et ur n Mage: : get Si ngl et on( ' Admi n/ sessi on' ) - >i sAl l owed( ' news/ manage/ '
. $act i on) ;
}
}
Download the Extension
You can download the extension we created in the process of documenting its steps
from the following location:
Most recent archived version: Magentostudy_News.zip
[http://info.magento.com/rs/magentocommerce/images/Magentostudy_News.zip]
Version to install via Magento Connect: Magentostudy_News-1.0.0.0.1.tgz
[http://info.magento.com/rs/magentocommerce/images/Magentostudy_News-
1.0.0.0.1.tgz]


Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 71
Appendix A: Building a Trusted
Extension
Overview
Magento is a feature-rich eCommerce platform built on open-source technology that
provides online merchants with unprecedented flexibility and control over the look,
content, and functionality of their eCommerce store. To allow for such flexibility,
extension developers must follow the following guidelines. Those extensions that do
not follow these guidelines might not be accepted for certification.
Extension Structure and Configuration
1. Code for extensions that are intended for community use should be stored in
the communi t y code pool.
2. Frontend templates and layouts should be stored in the
f r ont end/ base/ def aul t package.
3. Admin panel templates and layouts should be stored in the:
admi nht ml / def aul t / def aul t package.
4. There are two locations that can be used to store J avaScript files -- in the
application j s folder or an appropriate ski n folder. If you use the application j s
folder, J avaScript will need to be stored in a second nested folder that is named
according to the module or library to which the js applies. This is independent of
scope (frontend or Admin). If you use the ski n folder, frontend J avaScript
should be stored in
ski n/ f r ont end/ base/ def aul t / j s/ <namespace>_<name> , Admin panel
J avaScript should be stored in
skin/adminhtml/default/default/js/<namespace>_<name>.
5. Extension-specific CSS files should be stored in css folders within an
appropriate ski n folder depending on whether they apply to the frontend or the
Admin panel.
o Frontend CSS: ski n/ f r ont end/ base/ def aul t / css.
o Admin panel CSS: ski n/ admi nht ml / def aul t / def aul t / css.
6. Extension-specific J avaScript and CSS files should not overwrite any native files.
7. Images and other media files should be stored in the medi a folder. If you supply
media files within the extension package, they will need to be stored in an
appropriate ski n folder, otherwise they will not be found by the code.
8. Always be sure to check your module's dependencies, because a missing or
incorrectly defined dependency could cause your extension to produce fatal
errors. Only necessary dependencies should be specified, as they influence the

72 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
loading sequence of the application's core modules. Unnecessary dependences
should not be included.
9. The configuration file and the Admin controller should implement ACL
restrictions.
Using the Database, Resources, and Data
1. Do not create references from core database tables to extension ones because
this can break native Magento functionality.
2. Data should be escaped before inserting it into the database. This is extremely
important for security because it helps to avoid SQL-injections.
3. The extension should be responsible for validating incoming data such as user
entries, API call responses, etc.
4. Be sure to use the correct connection for queries. If you want only select records
use read connection, otherwise use write connection. Pay attention that all
queries like SELECT FOR UPDATE also need write permission, so write
connection should be used. Pay attention to queries combined into transactions
if only one query needs write permissions, all queries in the transaction should
use write connection.
5. It is forbidden to alter database structure on the fly. All changes should be
applied via install scripts. If the extension needs some temporary database
tables, they should be preliminarily created via install scripts and cleaned in
appropriate situations.
Working with Output
1. Core templates files cannot be physically overridden in the extension package.
Use layout functionality to extend frontend views.
2. All phrases must be enclosed with translation tags and methods so that they will
be translated according to the store locale.
3. All data shown in templates should be preliminarily escaped with the
appropriate methods (for example escapeHt ml , st r i pTags) to avoid possible
XSS injections.
Magento Components and Coding Style
1. Do not use PHP global variables like $_SERVER, $_GET, $_POST. There are
special Magento methods to interact with this data that should be used instead.
2. An extension should have its own helper for translations, to allow different phrase
translations in different modules and to make the module independent from
others.
3. Do not work directly with PHP $_GLOBAL variable, Magento provides alternative
solution to avoid usage of $_GLOBAL - Mage: : r egi st er ( ) ,
Mage: : r egi st r y( ) , Mage: : unr egi st er ( ) .

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 73
Appendix B: Magento Best Practices
Overview
Magento is a feature-rich eCommerce platform built on open-source technology that
provides online merchants with unprecedented flexibility and control over the look,
content and functionality of their eCommerce store. To ensure that extensions are
compatible, flexible, clear, secure, and performance optimized, developers should follow
the best practices specified below.
Extension Structure and Configuration
1. In order to improve readability and make the relationship between templates and
the module code more clear, templates should be stored in separate folders that
are named with the module namespace and name.
2. For similar reasons, layouts should be named with the module namespace and
name. Note, however, that native layouts don't include a namespace in their
names.
3. If your extension works both with frontend and Admin panel, place controllers
and blocks related to Admin functionality into a sub folder admi nht ml to clarify
their scope.
4. External libraries needed by an extension should be stored in the l i b folder and
should be open source.
Using the Database, Resources, and Data
1. In order to improve readability and make the relationship between database
tables and code more clearly, database tables should be named by module
namespace and name.
2. Use database indexes when creating tables because this can significantly
improve database (and overall) performance. More than one index can be
created for a table.
3. Data and structure upgrades should be processed via Adapter methods; raw
SQL is not recommended. Usage of adapter methods will make an extension
independent of concrete database realization.
4. If the extension stores some data such as statistics, the best approach is to
create the necessary logic using database storage instead of the file system.
5. Separate data upgrades from schema upgrades. Pay strict attention to this
because different upgrades were added in Magento Enterprise Edition (EE) 1.11
and Magento Community Edition (CE) 1.6.
6. Database query manipulations should be placed in resource models only.
Resource models act as an abstraction layer between domain models and the
database so they are the best place for SQL.

74 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
7. Use Zend style SQL queries because they make SQL queries more readable and
provide an object-oriented approach, which allows modifying them in other
modules.
Working with Output
1. It is not recommended to remove native blocks in custom layouts. The best way
is to add new blocks.
2. Frontend Blocks should be cached, wherever possible, to optimize frontend
performance. All blocks except special dynamic content should be cached using
native Magento cache functionality. Use logical caching when possible.
3. Templates should not contain business logic. Move all business logic to models,
blocks, and helpers.
Magento Components and Coding Style
1. Override controllers only if you do not have another more flexible solution.
2. If you plan to just add new action(s) without using methods or variables from the
parent, use an abstract class for the parent. This will help keep your extension
compatible with others.
3. According to the Zend Framework MVC best practices, the controller component
of an application "must be as skinny as possible." It is strongly recommended to
encapsulate all business logic into models and helpers; avoid implementing
business logic in a controller action.
4. Do not hardcode pre-defined values directly into methods. Use class constants,
protected class variables, or store configuration to allow for changing values
without code changes.
5. Core module rewrites should be minimized. In many situations the Observer
pattern can be used to completely avoid any rewrites.
6. Do not use the version of Magento in extension logic to change flow of the logic.
If it is needed universal extension for several versions of Magento, specific
module version should be checked. This has been explained in more detail
below:
Consider that the extension is being developed to support different versions of
Magento, for example CE 1.5 and CE 1.6. According to Magento versions code
changes, the extension should use different algorithms, and major Magento
version (1.5.0.0 or 1.6.0.1) shouldnt be checked. Each module has its version
that is identical for Magento CE, EE and Go (after merge codebase) and should
be used in such cases.

For example, the extension works with Sales module. The database structure
was changed in EE 1.6, but extension wants to work properly on new and old
versions, so it has two algorithms that depend on Magento version. Currently,
extension developers are checking this like in the code snippet below:

Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc. 75




i f ( Mage: : get Ver si on( ) >= 1. 6) {
. . . al gor i t hm1
} el se {
. . . al gor i t hm2
}

But this is incorrect because EE 1.6 and CE 1.6 have the identical value as the
result of the call function Mage::getVersion. The sales module version should be
checked to decide which algorithm should be used.


76 Magento Extension Developers Guide, v. 1.0 2012 X.commerce, Inc.
Appendix C: Further References

Designer's Guide to Magento
o http://info.magento.com/rs/magentocommerce/images/MagentoDesignGui
de.pdf

How to Package Magento Connect Extensions

o http://info.magento.com/rs/magentocommerce/images/packagingmagento
connectextensions6%200.pdf

Alan Storm: Magento Articles for Professional Developers
o http://alanstorm.com/category/magento#magento_for_php_developers

Inchoo. Magento Articles
o http://inchoo.net/category/ecommerce/magento/

You might also like