The Basics Of Creating A Magento Module

Advertisement

A lot of community extensions (or modules) are available for the feature-rich open-source e-commerce solution Magento1, but what if they don’t quite work as you want them to? What if you could understand the structure of a Magento module a little better, to the point that you could modify it to suit your needs or, better yet, write your own module from scratch?

In this tutorial, we will introduce the coding of Magento in the form of a “Hello World”-style module. The goal of the module will be simply to write some information to a log file every time a product is saved. This very basic module will allow us to cover a number of interesting topics, including:

  • The app/code directories,
  • The structure and creation of a Magento module,
  • Event observers,
  • Logging.

Before We Begin

This tutorial assumes that you already have an installation of Magento up and running, either locally or on a development server, that you can add new files to. The version of Magento that you use doesn’t really matter, because we will be covering fundamental aspects that exist across all versions and editions: Community, Professional and Enterprise.

Disable the Cache

This is one of the first lessons a Magento developer should learn: disable the cache! You can do this by going to Admin Panel > System > Cache Management > Select All > Actions: Disable > Submit.

While very good at boosting performance in a production environment, the cache is a developer’s enemy. Leave it enabled at your peril! Every Magento developer I have met has on more than one occasion spent an hour or so wondering why their latest update is not showing up, only to find that Magento is still displaying the version of the website that it conveniently cached earlier that day.

The app/code Directory

The brains of Magento can be found in individual modules inside the app/code directory, which is split in to three areas: core, community and local.

Core

The app/code/core directory contains all of the functionality for products, categories, customers, payments, etc. Until you know what you are doing (and even afterwards), keep app/code/core off limits because these files should not be modified.

Magento is structured in such a way that you can alter the functionality of any of these core files without modifying them directly, which ensures that your application remains upgrade-proof. By all means, look in order to better understand how Magento works, but do not touch.

Community

As the name suggests, app/code/community is where you will find modules that have been provided by third parties (i.e. not Magento’s core team). Hundreds of modules are available through Magento Connect, and when you install them through the built-in “Package Manager,” this is where they end up.

Local

Magento ships with an empty app/code/local directory, ready for you to add bespoke modules for your own Magento installation. This is where we will be working for the duration of this tutorial.

Structuring Our Directory

Open your favorite editor, and navigate to app/code/local to add some new directories and files.

Module Namespace

The first directory we will create is a “namespace.” This can be called anything you like, but the convention is some form of the name of the company or module’s author. Magento uses “Mage” as its namespace. Here at Ampersand Commerce, we use “Ampersand.” For this tutorial, we will use “SmashingMagazine” as our namespace. So, create the directory app/code/local/SmashingMagazine.

Module Name

For the next directory, we will give our module a descriptive name. The module we are creating will write log entries each time a product is saved, so a logical name would be LogProductUpdate. Create the directory app/code/local/SmashingMagazine/LogProductUpdate.

We should now have the following directory structure for our module. These directory and file names are case-sensitive, so capitalize where appropriate.

app
  - code
      - local
          - SmashingMagazine
              - LogProductUpdate

Configuring Our Module

Next, we will begin to configure our module. The configuration files belong inside our module in a directory named etc, so let’s create that along with a new XML file: app/code/local/SmashingMagazine/LogProductUpdate/etc/config.xml. This XML file will inform Magento of the location of the files in our module, as well as many other things, such as version number and events to observe. For now, we will create a simple config.xml file, which contains comments that explain the meaning of each section.

<?xml version="1.0" encoding="UTF-8"?>

<!-- The root node for Magento module configuration -->
<config>

    <!--
        The module's node contains basic
        information about each Magento module
    -->
    <modules>

        <!--
            This must exactly match the namespace and module's folder
            names, with directory separators replaced by underscores
        -->
        <SmashingMagazine_LogProductUpdate>

            <!-- The version of our module, starting at 0.0.1 -->
            <version>0.0.1</version>

        </SmashingMagazine_LogProductUpdate>

    </modules>

</config>

Activating Our Module

The next step is to inform our Magento installation that our module exists, which we do by creating a new XML file in app/etc/modules. The name of this XML file can be anything you like, since Magento will read all XML files in this directory and will be interested only in the content. However, by convention we should give the file and module the same name. Let’s create app/etc/modules/SmashingMagazine_LogProductUpdate.xml with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <SmashingMagazine_LogProductUpdate>

            <!-- Whether our module is active: true or false -->
            <active>true</active>

            <!-- Which code pool to use: core, community or local -->
            <codePool>local</codePool>

        </SmashingMagazine_LogProductUpdate>
    </modules>
</config>

Sanity Check: Is The Module Enabled?

We now have a fully functional module that is enabled in Magento. It doesn’t do anything, but it is a valid module. This is our first opportunity to see whether we have correctly configured everything so far. If we log into the Magento admin panel and navigate to System > Configuration > Advanced > Advanced and view the “Disable Modules Output” listing, we should see our SmashingMagazine_LogProductUpdate module listed as enabled. If it is not listed, then something has gone wrong, so carefully run through the steps up to this point again. This is usually when new Magento developers discover the cache!

Our module’s structure now looks like this:

app
  - code
      - local
          - SmashingMagazine
              - LogProductUpdate
                  - etc
                      - config.xml

  - etc
      - modules
          - SmashingMagazine_LogProductUpdate.xml

Defining An Event Observer

Event observers are extremely powerful and are one of the cleanest ways to extend Magento’s functionality without having to rewrite or override any core methods or classes. We want to observe the event that Magento dispatches just after a product is saved, so the code for the event we are interested in is catalog_product_save_after. Determining which event code to use when defining a new observer requires a basic understanding of Magento’s model layer, which is beyond the scope of this tutorial. Don’t worry, though: we’ll cover it another time!

We now need to modify our config.xml to include the event observer definition:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <SmashingMagazine_LogProductUpdate>
            <version>0.0.1</version>
        </SmashingMagazine_LogProductUpdate>
    </modules>

    <!-- Configure our module's behavior in the global scope -->
    <global>

        <!-- Defining an event observer -->
        <events>

            <!-- The code of the event we want to observe -->
            <catalog_product_save_after>

                <!-- Defining an observer for this event -->
                <observers>

                    <!--
                        Unique identifier within the
                        catalog_product_save_after node.
                        By convention, we write the module's
                        name in lowercase.
                    -->
                    <smashingmagazine_logproductupdate>

                        <!-- The model to be instantiated -->
                        <class>smashingmagazine_logproductupdate/observer</class>

                        <!-- The method of the class to be called -->
                        <method>logUpdate</method>

                        <!-- The type of class to instantiate -->
                        <type>singleton</type>

                    </smashingmagazine_logproductupdate>

                </observers>

            </catalog_product_save_after>

        </events>

    </global>

</config>

Configuring Our Model’s Directory

In the event observer defined above, we made reference to a model that we have not yet created. We need to inform Magento where to find models in our module by updating config.xml with the following:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <SmashingMagazine_LogProductUpdate>
            <version>0.0.1</version>
        </SmashingMagazine_LogProductUpdate>
    </modules>

    <!-- Configure our module's behavior in the global scope -->
    <global>

        <!-- Defining models -->
        <models>

            <!--
                Unique identifier in the model's node.
                By convention, we put the module's name in lowercase.
            -->
            <smashingmagazine_logproductupdate>

                <!--
                    The path to our models directory, with directory
                    separators replaced by underscores
                -->
                <class>SmashingMagazine_LogProductUpdate_Model</class>

            </smashingmagazine_logproductupdate>

        </models>

        <events>
            <catalog_product_save_after>
                <observers>
                    <smashingmagazine_logproductupdate>
                        <class>smashingmagazine_logproductupdate/observer</class>
                        <method>logUpdate</method>
                        <type>singleton</type>
                    </smashingmagazine_logproductupdate>
                </observers>
            </catalog_product_save_after>
        </events>

    </global>

</config>

Creating An Observer Model

We will now create the model to be instantiated when the event is dispatched. Create a new PHP file in app/code/local/SmashingMagazine/LogProductUpdate/Model/Observer.php with the following content:

<?php
/**
 * Our class name should follow the directory structure of
 * our Observer.php model, starting from the namespace,
 * replacing directory separators with underscores.
 * i.e. app/code/local/SmashingMagazine/
 *                     LogProductUpdate/Model/Observer.php
 */
class SmashingMagazine_LogProductUpdate_Model_Observer
{
    /**
     * Magento passes a Varien_Event_Observer object as
     * the first parameter of dispatched events.
     */
    public function logUpdate(Varien_Event_Observer $observer)
    {
        // Retrieve the product being updated from the event observer
        $product = $observer->getEvent()->getProduct();

        // Write a new line to var/log/product-updates.log
        $name = $product->getName();
        $sku = $product->getSku();
        Mage::log(
            "{$name} ({$sku}) updated",
            null,
            'product-updates.log'
        );
    }
}

We’re done! Try it out.

The directory structure for our completed module should now look like this:

app
  - code
      - local
          - SmashingMagazine
              - LogProductUpdate
                  - Model
                      - Observer.php

                  - etc
                      - config.xml

  - etc
      - modules
          - SmashingMagazine_LogProductUpdate.xml

Now that our module is complete, it’s time to try it out! Log into the Magento admin panel, create or update a product in your catalog, and then check the var/log folder to see your product-updates.log file populated.

If nothing appears or the directory does not exist, ensure that the correct permissions are set to allow Magento to write to this directory, and that logging is enabled in Admin Panel > System > Configuration > Developer > Log Settings > Enabled.

This basic tutorial is meant to give you an overall understanding of how Magento modules work. After completing this tutorial, spend some time exploring the Magento modules in app/code/core and see if you now have a better idea of how it all works.

Feel free to view or download the source code2 (Github).

We welcome any questions and would love to hear any feedback in the comments area below.

Footnotes

  1. 1 http://ampersandcommerce.com/what-is-magento/
  2. 2 https://github.com/josephmcdermott/SmashingMagazine-MagentoFirstModule

↑ Back to top Tweet itShare on Facebook

Advertising
  1. 1

    In 1.7.x the model definition in config.xml needs to use only the module name, without the namespace, like this: <logproductupdate>

    But anyway, thanks a lot for this article, it helped me most from those I could find;)

    0
  2. 52

    Grateful to you……… helped a lot

    0
  3. 103

    Thank you so much for this tutorial.

    0
  4. 154

    The amount of “developers” complaining that Magento sucks because they lack the knowledge and developer skills to actually learn a new framework that ins’t as simple as WordPress boggles my mind… If you can’t dedicate the time to learning a complex and powerful enterprise ecommerce platform, then don’t use a complex and powerful enterprise class ecommerce platform for your dinky mom and pop websites for your aunt’s friend. This isn’t something you use to learn on a new client like a WordPress theme you downloaded and cut/paste some elements around and call yourself a developer, which is what 90% of the people complaining on here are exactly.

    0
    • 205

      Buddy, it isn’t about “learning a new framework”. The community edition of Magento has real problems and bugs that hinder development. The caching system is a fucking nightmare, and magento doesn’t have real name spacing. I’m not even going to talk about the verbosity of the “configuration based mvc” that it claims is so powerful. It lacks real name spacing, so all the configuration is proprietary bullshit that has to be memorized, otherwise creating an extension is a frustrating nightmare. These are real problems, so the bullshit about “developers not wanting to learn complex frameworks” is exactly that, bullshit.

      6
  5. 256

    This is by far the best article regarding basic magento structure and theory there is on the internet. The diagrams for file structure really helped.

    0
  6. 307

    Hi,
    Followed all instructions and everything is visible in backend in delivery methods. However this method is not showing in front end. Any ideas? Do I need to enable compilation?

    1
  7. 358

    Stephen Richards

    July 1, 2014 3:46 pm

    Hi,

    It may be worth placing a side note in the tutorial to check Magentos ‘var/log’ directory or specify the full Magento path as I spent 20 minutes re-doing the tutorial looking in the OS /var/log :)

    For an experienced Magnento user it may be obvious that Magento would write to magento/var/log but as I come from a Linux background, I assume /var/log when I read var/log ;)

    Ste,

    0
    • 409

      Stephen Richards

      July 1, 2014 3:49 pm

      “or specify the full Magento path”

      You did do that so ignore that comment I made previously :)

      0
  8. 460

    Glad to know this,
    Now i have a basic idea on working flow of Events.
    ‘Sometimes simple clarifications gives global knowledge ‘ :)

    0
  9. 511

    This approach does not work with 1.9.0.1 the module will never show up in advanced admin settings.

    1
  10. 562

    Great Help …!!!

    i want some change in total price of each group calculation
    i want to calculate each grouped product price as

    sub total 1 = product 1 price x quantity x custom value
    can you tell me how to do this ?

    thank you in advance

    0
  11. 613

    Great article gave me a good idea on every basic steps in magento module development.It works fine for me what is there in the described code.i tried to rewrite the code with my own package and module name, it want work.most probably i followed each and every line of the coding.one thing i want to figure it out is, What is “” tag in the config.xml after tag.It will be great pleasure if you can help me to figure out my error.
    Thank you.

    0
  12. 664

    Great article gave me a good idea on every basic steps in magento module development.It works fine for me what is there in the described code.i tried to rewrite the code with my own package and module name, it want work.most probably i followed each and every line of the coding.one thing i want to figure it out is, What is “catalog_product_save_after” tag in the config.xml It will be great pleasure if you can help me to figure out my error.
    Thank you.

    0
  13. 715

    Thanks Joseph,

    A very useful Article.

    Can you throw some light on how to put your extensions on the magento market place after development?

    Regards.

    0
  14. 766

    Where can I get a list of all the events?

    I checked here http://www.magentocommerce.com/wiki/5_-_modules_and_development/reference/magento_events , but surprisingly the event catalog_product_save_after is not defined in this list!.

    Thanks.

    0

↑ Back to top