We continue to share our experience with Magento developers by publishing the next set of Best Practices in Magento coding. If you missed our previous article, here it is.
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):
js
or
skin/frontend/package/theme/js
Actually, you should think twice at this point. As we’ve told above, one of the major Magento ideas is modularity. Therefore, as a good developer you should allow third party developers to make small changes/customizations without a need to edit your code wherever it’s possible. If your JS files are located in the skins folder, other developers are always able to change something by copying JS files into their own theme’s folder. But if you use the root JS directory, they won’t be able to do that.
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:
Mage::dispatchEvent('the_unique_name', array('var' => $data));
As the second argument, you should pass the data, that you want to send to the observer’s method (some id or some object instance for example).
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 :
$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 }
We would be glad to read your suggestions in the comments, so feel free to post them :)