首页 > 代码库 > Advices and Best Practices for Magento developers
Advices and Best Practices for Magento developers
I think everyone who is interested in ecommerce development get familiar with Magento earlier or later. It’s a very popular platform, where a lot of modern programming technologies are used. Since Magento is one of the most powerful and flexible shopping cart engines, it requires a deep level of expertise to develop extensions or even do some basic changes. So we’ve decided to share our tips for Magento Developers in this article. [Continue to Part 2] You can get tons of solutions from the Internet on how to make one or another modifications for Magento functionality, but it’s worth noting that not all of them are smart, guarantee results and follow best practices. Every developer eventually gets to the experience level that allows him to follow good developing practice. I want to share my own findings with you. So lets start.
Never use app/code/local/Mage to override core files.
Instead of this always try to create your own extension to change/add/modify core logic. It saves you from errors upon further store upgrades or third party extension’s collisions. If you ever use app/code/local/Mage, then only use it for temporary changes that you will remove afterwards.
Try to avoid overriding wherever it’s possible.
Use event-listeners, helpers, or extend (not override) the core classes to form your own. It also saves your extension from conflicts with third party addons. For example, you always can use event core_block_abstract_to_html_after to inject button or some other element into html where there is no ability to inject it properly using xml layouts. There’s no reason to override .phtml files or block’s logic. For example, if you want to add/remove logic for checkout.onepage.billing block you need to create your own extension and specify your block class within xml layout.
1 2 | < block type = "your_extension/checkout_onepage_billing" name = "checkout.onepage.billing" as = "billing" template = "checkout/onepage/billing.phtml" /> |
Where
1 | class Your_Extension_Block_Checkout_Onepage_Billing extends Mage_Checkout_Block_Onepage_Billing |
Do not remove generic blocks from *.phtml files or xml layouts.
For example, you don’t need a generic block with name ‘product_additional_data‘ (product view page) and you think you are able to delete it from code. But you should not do this. Magento third party extensions usually use generic blocks to inject their own blocks there. If you have deleted it, you may spend a lot of time to find out why some extension doesn’t work.
Use Magento generic CSS classes whenever possible.
There are thousands of CSS classes, that are defined in Magento default installation and if you are going to make a new store template, you should use those classnames in your new template. It’s a good practice, because there is a lot of third party extensions that use those classnames for design integration.
Always document your own code.
As a good programmer, you should always use PHPDoc in your projects. If you were faced with problem and trying to find out the solution, it’s always easier to explore documented code. Also you should think about other programmers who may be forced to work with your code :)
Always explore core abstract classes during your work with Magento.
It helps you to make your code more effectively. For example I met many developers who write their own methods for checking a status of their extensions (enabled/disabled) but only few of them use method isModuleEnabled() fromMage_Core_Helper_Abstract
Use cache for your own blocks.
Magento allows to use cache system separately for custom blocks. Using cache for the blocks may greatly improve your extensions performance. To enable cache for the block you need to use the following part of code in your block constructor:
1 2 3 4 5 6 7 8 9 10 11 12 | class Your_Extension_Block_Blah extends Mage_Core_Block_Template { protected function _construct() { parent::_construct(); $this ->addData( array ( ‘cache_lifetime‘ => 43200, ‘cache_tags‘ => array (Mage_Catalog_Model_Product::CACHE_TAG), )); } } |
Use Magento built in log system for logging the behaviour of your extension.
It always helps to find issues faster if any. You are able to create/use your own log using the code:
1 | Mage::log( ‘There was a bug‘ , null, ‘log_filename.log‘ ); |
Don’t forget to check if logging is enabled in Admin -> System -> Configuration -> Developer -> Debug .
Use Magento built in profiler to check the performance issues.
Magento allows to display loading time for separate parts at the bottom of every page for development purposes. First, enable the profiler via System -> Configuration -> Developer -> Debug -> Profiler (yes). Second, comment out the following line in index.php
1 | #Varien_Profiler::enable(); |
Then you should see profiler on the store pages.
Use XML layouts to integrate features or extend functionality wherever it’s possible.
Magento allows to make different actions within layout XML files. As you know, it is possible to integrate your block somewhere in the design, but you can call different methods more efficiently using XML. Usually programmers forget about this feature. For example, you need to extend admin order’s grid with additional column. You can always extendMage_Adminhtml_Block_Sales_Order_Grid but it’s not the best solution because it may be overwritten within some other extension. Instead of this, you can call method AddColumn, AddColumnAfter or some other directly from xml layout. Take a look at the example below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | < adminhtml_sales_order_grid > < reference name = "sales_order.grid" > < action method = "addColumnAfter" > < columnId >street</ columnId > < arguments module = "yourmodule" translate = "header" > < header >Street</ header > < type >text</ type > < index >sales_flat_order_address.street</ index > </ arguments > < after >entity_id</ after > </ action > </ reference > </ adminhtml_sales_order_grid > </ layout > |
Use IDE (Integrated Development Environment).
There are many useful IDE to make Magento developing process faster, easier and more pleasant. You can try the most popular of them and choose which one is the best for you. There are many advantages of using IDE. You can inspect parent and abstract classes faster since most of IDE’s supports classes inheritance inspection. Popular IDE’s have the debugger in their toolset. It also may help you to save your time. Version control support, syntax checking, deployment management, smart snippets, refactoring, projects management and much more you can find in the modern IDE’s. As you can see, one application replaces many tools you have used before. All you need, is to find a convenient IDE for you and customise every detail. To be continued… Part 2. P.S. It would be great to see your own findings of Magento development in the comments.
Local or community code pool.
Pretty often we face with the discussion about choosing a proper code pool. So, let’s talk about the difference. Local pool has the highest load priority and code in this pool can’t be overridden as easy as in community or core pools. But depending on the Magento ideology, local pool was primarily designed for local changes. If you own a website and make modifications for that website, then your modifications are classified as local and your changes should be made in the app/code/local folder. Also, when you do some custom work on the website – local code pool is for you. However, if the extension is used by many other customers, this extension is not local but shared with a (limited) community. Therefore, the extension belongs to the community pool. Provided that you are an extension developer, you shouldn’t prevent overriding your files by other developers for the purpose of making some small changes. That can always be done by using the local pool.Where to store the JS files in Magento?
Usually developers choose one of the following paths to store JS files (we are talking about frontend): 1 | |
1 | skin /frontend/package/theme/js |
Controllers and common logic.
One of the common Magento problems is tons of logic in the controllers where it shouldn’t be. For exemple, let’s explore the core file app/code/core/Mage/Customer/controllers/AccountController.php. Look at the createPostAction() method and you will see a lot of operations there. Why not to use a helper to store this logic or some abstract class? It allows other developers to extend the logic for their own purposes easily. For example, if you need to add a new customer programmatically and you want to use a standard set of methods for this, you won’t be able to do it, because most of the logic is located in the controller. Hence, we think it would be a good practice to use more extendable structures for common logic instead of hardcoding it in the controllers.Dispatched events.
There’s yet another way to improve the quality of your extensions using dispatched events. Dispatcher is a Magento integrated system, which allows you to set some “point” with the unique name and some necessary parameters where you can integrate our logic “on the fly”. In other words, you can create your own events in your logic. Then, you or other developers are able to catch these events and connect some handlers to the events. It’s always useful to have dispatched events in the extensions, because it provides you an ability to extend your code more effectively in the future and allows other developers to interact with your logic in intelligent way. Events are usually dispatched in models and controllers. It is good to know, that it is enough to use the following construction in your code to dispatch an event: 1 | Mage::dispatchEvent( ‘the_unique_name‘ , array ( ‘var‘ => $data )); |
DB queries profiler:
Magento provides an ability for developers to track database queries. For this purpose you should use a built in DB resource profiler. It can help you to inspect database queries, detect the longest query, detect the slowest query, etc.. Here is a small example on how to use a DB profiler for your own needs : 1 2 3 4 5 | $profiler = Mage::getSingleton( ‘core/resource‘ )->getConnection( ‘core_write‘ )->getProfiler(); foreach ( $profiler ->getQueryProfiles() as $query ) { $queryTime [] = $query ->getElapsedSecs(); // Get the query execution time $queryRaw [] = $query ->getQuery(); // Get the query text } |