Creating Magento extensions can be an extremely challenging and time-consuming task depending on several factors such as your knowledge of Magento internals, overall development skills, and the complexity of the extension functionality itself. Having a deep insight into Magento internals, its structure, and accompanying tips and tricks will provide you with a strong foundation for clean and unobtrusive Magento extension development.
The word unobtrusive should be a constant thought throughout your entire development process. The reason is simple; given the massiveness of the Magento platform, it is way too easy to build extensions that clash with other third-party extensions. This is usually a beginner's flaw, which we will hopefully avoid once we have finished reading this article. The examples listed in this article are targeted towards Magento Community Edition 184.108.40.206. Version 220.127.116.11 is the last stable release at the time of writing this writing.
Throughout this article we will be referencing our URL examples as if they are executing on the magento.loc domain. You are free to set your local Apache virtual host and host file to any domain you prefer, as long as you keep this in mind. If you're hearing about virtual host terminology for the first time, please refer to the Apache Virtual Host documentation at http://httpd.apache.org/docs/2.4/vhosts/.
Here is a quick summary on each of those files and folders:
- .htaccess: This file is a directory-level configuration file supported by several web servers, most notably the Apache web server. It controls mod_rewrite for fancy URLs and sets configuration server variables (such as memory limit) and PHP maximum execution time.
- .htaccess.sample: This is basically a .htaccess template file used for creating new stores within subfolders.
- api.php: This is primarily used for the Magento REST API, but can be used for SOAP and XML-RPC API server functionality as well.
- app: This is where you will find Magento core code files for the backend and for the frontend. This folder is basically the heart of the Magento platform. Later on, we will dive into this folder for more details, given that this is the folder that you as an extension developer will spend most of your time on.
- cron.php: This file, when triggered via URL or via console PHP, will trigger certain Magento cron jobs logic.
- cron.sh: This file is a Unix shell script version of cron.php.
- downloader: This folder is used by the Magento Connect Manager, which is the functionality you access from the Magento administration area by navigating to System | Magento Connect | Magento Connect Manager.
- errors: This folder is a host for a slightly separate Magento functionality, the one that jumps in with error handling when your Magento store gets an exception during code execution.
- favicon.ico: This is your standard 16 x 16 px website icon.
- get.php: This file hosts a feature that allows core media files to be stored and served from the database. With the Database File Storage system in place, Magento would redirect requests for media files to get.php.
- includes: This folder is used by the Mage_Compiler extension whose functionality can be accessed via Magento administration System | Tools | Compilation. The idea behind the Magento compiler feature is that you end up with PHP system that pulls all of its classes from one folder, thus, giving it a massive performance boost.
- index.php: This is a main entry point to your application, the main loader file for Magento, and the file that initializes everything. Every request for every Magento page goes through this file.
- index.php.sample: This file is just a backup copy of the index.php file.
- lib: This folder holds the core Magento PHP libraries, such as 3DSecure, Google Checkout, phpseclib, Zend, and a few others, some of which are from Magento itself.
- LICENSE*: These are the Magento licence files in various formats (LICENSE_AFL.txt, LICENSE.html, and LICENSE.txt).
- mage: This is a Magento Connect command-line tool. It allows you to add/remove channels, install and uninstall packages (extensions), and various other package related tasks.
- media: This folder contains all of the media files, mostly just images from various products, categories, and CMS pages.
- php.ini.sample: This file is a sample php.ini file for PHP CGI/FastCGI installations. Sample files are not actually used by Magento application.
- pkginfo: This folder contains text files that largely operate as debug files to inform us about changes when extensions are upgraded in any way.
- RELEASE_NOTES.txt: This file contains the release notes and changes for various Magento versions, starting from version 18.104.22.168 and later.
- shell: This folder contains several PHP-based shell tools, such as compiler, indexer, and logger.
- var: This folder contains sessions, logs, reports, configuration cache, lock files for application processes, and possible various other files distributed among individual subfolders. During development, you can freely select all the subfolders and delete them, as Magento will recreate all of them on the next page request. From a standpoint of Magento extension developer, you might find yourself looking into the var/log and var/report folders every now and then.
The folder code is a placeholder for what is called a codePool in Magento. Usually, there are three code pool's in Magento, that is, three subfolders: community, core, and local.
The formula for your extension code location should be something like app/code/community/YourNamespace/YourModuleName/ or app/code/local/YourNamespace/YourModuleName/.
There is a simple rule as to whether to chose community or local codePool:
- Choose the community codePool for extensions that you plan to share across projects, or possibly upload to Magento Connect
- Choose the local codePool for extensions that are specific for the project you are working on and won't be shared with the public
For example, let's imagine that our company name is Foggyline and the extension we are building is called Happy Hour. As we wish to share our extension with the community, we can put it into a folder such as app/code/community/Foggyline/HappyHour/.
The theme system
There is one important thing to know about Magento themes; they have a fallback mechanism, for example, if someone in the administration interface sets the configuration to use a theme called hello from the default package; and if the theme is missing, for example, the app/design/frontend/default/hello/template/catalog/product/view.phtml file in its structure, Magento will use app/design/frontend/default/default/template/catalog/product/view.phtml from the default theme; and if that file is missing as well, Magento will fall back to the base package for the app/design/frontend/base/default/template/catalog/product/view.phtml file.
All your layout and view files should go under the /app/design/frontend/defaultdefault/default directory.
Secondly, you should never overwrite the existing .xml layout or template .phtml file from within the /app/design/frontend/default/default directory, rather create your own. For example, imagine you are doing some product image switcher extension, and you conclude that you need to do some modifications to the app/design/frontend/default/default/template/catalog/product/view/media.phtml file. A more valid approach would be to create a proper XML layout update file with handles rewriting the media.phtml usage to let's say media_product_image_switcher.phtml.
The model, resource, and collection
A model represents the data for the better part, and to certain extent a business logic of your application. Models in Magento take the Object Relational Mapping (ORM) approach, thus, having the developer to strictly deal with objects while their data is then automatically persisted to database. If you are hearing about ORM for the first time, please take some time to familiarize yourself with the concept; you can find a good starting material about it at http://en.wikipedia.org/wiki/Object-relational_mapping. Theoretically, you could write and execute raw SQL queries in Magento. However, doing so is not advised, especially if you plan on distributing your extensions.
There are two types of models in Magento:
- Basic Data Model: This is a simpler model type, sort of like Active Record pattern based model. If you're hearing about Active Record for the first time, please take some time to familiarize yourself with the concept; you can find a good starting material about it at https://en.wikipedia.org/wiki/Active_record_pattern.
- EAV (Entity-Attribute-Value) Data Model: This is a complex model type, which enables you to dynamically create new attributes on an entity. As EAV Data Model is significantly more complex than Basic Data Model and Basic Data Model will suffice for most of the time, we will focus on Basic Data Model and everything important surrounding it. Each data model you plan to persist to database, that means models that present an entity, needs to have four files in order for it to work fully:
- The model file: This extends the Mage_Core_Model_Abstract class. This represents single entity, its properties (fields), and possible business logic within it.
- The model resource file: This extends the Mage_Core_Model_Resource_Db_Abstract class. This is your connection to database; think of it as the thing that saves your entity properties (fields) database.
- The model collection file: This extends the Mage_Core_Model_Resource_Db_Collection_Abstract class. This is your collection of several entities, a collection that can be filtered, sorted, and manipulated.
- The installation script file: In its simplest definition this is the PHP file through which you, in and object-oriented way, create your database table(s).
The default Magento installation comes with several built in shipping methods available: Flat Rate, Table Rates, Free Shipping UPS, USPS, FedEx, DHL. For some merchants this is more than enough, for others you are free to build an additional custom Shipping extension with support for one or more shipping methods. Be careful about the terminology here. Shipping method resides within shipping extension. A single extension can define one or more shipping methods. In this article we will learn how to create our own shipping method.
There are two, unofficially divided, types of shipping methods:
- Static, where shipping cost rates are based on a predefined set of rules. For example, you can create a shipping method called 5+ and make it available to the customer for selection under the checkout only if he added more than five products to the cart.
- Dynamic, where retrieval of shipping cost rates comes from various shipping providers. For example, you have a web service called ABC Shipping that exposes a SOAP web service API which accepts products weight, length, height, width, shipping address and returns the calculated shipping cost which you can then show to your customer.
Experienced developers would probably expect one or more PHP interfaces to handle the implementation of new shipping methods. Same goes for Magento, implementing a new shipping method is done via an interface and via proper configuration.
The default Magento installation comes with several built-in payment methods available: PayPal, Saved CC, Check/Money Order, Zero Subtotal Checkout, Bank Transfer Payment, Cash On Delivery payment, Purchase Order, and Authorize.Net. For some merchants this is more than enough. Various additional payment extensions can be found on Magento Connect. For those that do not yet exist, you are free to build an additional custom payment extension with support for one or more payment methods. Building a payment extension is usually a non-trivial task that requires a lot of focus.
There are several unofficially divided types of payment method implementations such as redirect payment, hosted (on-site) payment, and an embedded iframe. Two of them stand out as the most commonly used ones:
- Redirect payment: During the checkout, once the customer reaches the final ORDER REVIEW step, he/she clicks on the Place Order button. Magento then redirects the customer to specific payment provider website where customer is supposed to provide the credit card information and execute the actual payment. What's specific about this is that prior to redirection, Magento needs to create the order in the system and it does so by assigning this new order a Pending status. Later if customer provides the valid credit card information on the payment provider website, customer gets redirected back to Magento success page. The main concept to grasp here is that customer might just close the payment provider website and never return to your store, leaving your order indefinitely in
Pendingstatus. The great thing about this redirect type of payment method providers (gateways) is that they are relatively easy to implement in Magento.
- Hosted (on-site) payment: Unlike redirect payment, there is no redirection here. Everything is handled on the Magento store. During the checkout, once the customer reaches the Payment Information step, he/she is presented with a form for providing the credit card information. After which, when he/she clicks on the Place Order button in the last ORDER REVIEW checkout step, Magento then internally calls the appropriate payment provider web service, passing it the billing information. Depending on the web service response, Magento then internally sets the order status to either Processing or some other. For example, this payment provider web service can be a standard SOAP service with a few methods such as orderSubmit. Additionally, we don't even have to use a real payment provider, we can just make a "dummy" payment implementation like built-in Check/Money Order payment. You will often find that most of the merchants prefer this type of payment method, as they believe that redirecting the customer to third-party site might negatively affect their sale. Obviously, with this payment method there is more overhead for you as a developer to handle the implementation. On top of that there are security concerns of handling the credit card data on Magento side, in which case PCI compliance is obligatory. If this is your first time hearing about PCI compliance, please see https://www.pcisecuritystandards.org for more information about it. This type of payment method is slightly more challenging to implement than the redirect payment method.
Magento Connect is one of the world's largest eCommerce application marketplace where you can find various extensions to customize and enhance your Magento store.
It allows Magento community members and partners to share their open source or commercial contributions for Magento with the community.
You can access Magento Connect marketplace at http://www.magentocommerce.com/magento-connect url.
Publishing your extension to Magento Connect is a three-step process made of:
More of which we will talk later in the article.
Only community members and partners have the ability to publish their contributions.
Becoming a community member is simple, just register as a user on official Magento website https://www.magentocommerce.com. Member account is a requirement for further packaging and publishing of your extension.
This article provided us with a brief description of the extensions in Magento, payment methods, shipping methods, and how to package and distribute your extension over Magento Connect—a Magento extension marketplace.
Resources for Article:
- Categories and Attributes in Magento: Part 2 [Article]
- Integrating Twitter with Magento [Article]
- Magento Fundamentals for Developers [Article]