Are helper classes mandatory for all Magento extensions? - magento

Many extensions (including the one's I've written) include a helper class that just extend the abstract base class without adding any functionality. The helper usually looks like this:
class MyCompany_MyModule_Helper_Data extends Mage_Core_Helper_Abstract {
}
The extended class is therefore just used for things that the abstract class provides, especially for translations. On the other hand, all Block and Controller classes in Magento inherit the __() method for translations - and in an extension I'm currently developing I don't have the need to call the helper class even once.
Can I just delete the helper class and remove it from config.xml? I've tried it and the extension seems to work fine without, but due to Magento's complexity I'm always a bit worried that there are implications I'm not aware of.

If you're creating a module from scratch, helper classes aren't strictly necessary. I usually skip creating one until it's needed.
However, if any XML file uses the module attribute to specify a translation module, that attribute needs to resolve to a valid helper. For example, in this core file
<!-- File: app/code/core/Mage/Catalog/etc/system.xml -->
<tabs>
<catalog translate="label" module="catalog">
<label>Catalog</label>
<sort_order>200</sort_order>
</catalog>
</tabs>
There's module="catalog". By specifying this attribute, the Magento system code that translates the label will look something like this
Mage::helper('catalog')->__('Label');
So, removing the helper from the catalog module would break parts of Magento.
(The single part class alias catalog is automatically converted to Mage::helper('catalog/data') by Magento system code)
This "helper to group translations" feature is used in many of Magento's XML files, not just system.xml (layout, widgets, etc.). Additionally, there are some systems in Magento that will infer and/or require the existence of a helper module for translations (Access Control, external API system,etc. )
Long Story Short: If you're creating a module from scratch, feel free to leave the helper out until you start getting errors that Magento can't instantiate a helper. Never remove an existing helper from a module, and if you want to make sure you're 100% compatible with assumptions other people might make, always include a Data.php helper class.

Magento's Helper classes contain utility methods that will allow you to perform common tasks on objects and variables. http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-1-introduction-to-magento#6
Assuming that the Helper file is empty with no custom methods eg.
<?php
class MagePal_SomeModule_Helper_Data extends Mage_Core_Helper_Abstract
{
}
Then some of things that may still be affected are:
system.xml - blank screen for your module in admin -> system -> config
$this->__('') - error in your .phtml template (for internationalization/translation)
So if your helper is empty, without a system config section and no translation then it 'maybe' ok to delete.

Related

Mage_Payment_Model_Method_Abstract class override

As title suggest i want to override Mage_Payment_Model_Method_Abstract class , I know that it is abstract class. and we can easily override abstract class using local directory like app\code\local\Mage\Payment\Model\Method\Abstract.php. But i want to know is there any other option for me ? Because this option is not safe with different magento version.
Any help will be appreciated.
Thank you
'Override' is a method where you copy a class from the Magento core into the local code. For ex:
app/code/core/Mage/Rule/Model/Abstract.php
to
app/code/local/Mage/Rule/Model/Abstract.php
An override is where you tell Magento to "Use this class file instead of the other class file". Similar, but different from a rewrite. Rewrites are considered better practice because they're less likely to cause problems with upgrades and extension compatibility.
An abstract class is never instantiated, it can never be rewritten.
If you override, you need to take care of future upgrades. You can't rewrite an abstract class. The rewrite system works because Magento uses a factory pattern to instantiate model, blocks, and helpers.
The other alternative is to use a traditional class override. For ex: Copy
app/code/core/Mage/Rule/Model/Abstract.php
to
app/code/local/Mage/Rule/Model/Abstract.php
Also somewhere on the blog I read this (not in favor though) For ex: Copy
Mage_Shipping_Model_Carrier_Abstract
from
app/code/core/Mage/Shipping/Model/Carrier
to
app/code/local/Mage/Shipping/Model/Carrier
Do NOT change the class name, just change or add the methods as you need.
This is a trick. Magento loads a class from several locations, and app/code/local comes before app/code/core
Good luck!!!

Why extending controller in magento is different from model

I want to know why are the steps to extend magento controller different from model or block. Why cant a controller be extended like other magento classes are overridden? Why do we have to include the class file in the file which is extending it in case of controller?
In short: This is how Magento was designed (not to allow override the controller as with Model, Helper and Block). I mean they are free to design the whatever they want.
In long: You can always instantiate Model, Block, Helper via Factory method, usually, Mage::getModel('your/model'), Mage::getBlock('your/block') and Mage::getHelper('module/helper'). However, it is not possible to instantiate controller this way.
The factory method Mage::getModel() checks all configurations files (usually files in et/config.xml of all modules) to determine overloading. However, Controller class are determined by Router based on complex, multi-level system routing.

What is the best practices in Magento model rewrite?

My company is making a module for Magento to fit the needs of Brazilian business rules.
Sometimes we need to override core models to add funcionality, sometimes need to rewrite core models to change some functionality. We are in doubt wich is the best practices to do this changes. For example, when a module needs to modify some behavior that is owned by other model.
We know that the modified files need to be created under "local/mycompany/modules..." but we're running into a problem that I will describe below.
A simple example is: Our Customer model needs to add the postcode with the '99999-999' mask, with the '-' before the last three chars. That is ok, its done and working. But when we need to use this postcode to make calculations, wee need to remove the '-' char. That was made in our rewrited "Shipping/Rate/Request.php" model.
That is the point of our doubt. Which is best?
Do this rewrite inside new "Shipping" module in "local/mycompany/Shipping/Model/Rate/Request.php" or do this rewrite inside the "Customer" module directory structure?
We are confusing about the structure we need to decide.
Something important is that we won't distribute or sell the modules rewrited as separated modules.
I'll put some code here:
The postcode is received by our "Customer" module, with masks in input, done by Javascript.
This "Customer" module add more fields to customer database.
Here, I rewrite "Shipping/Rate/Request.php", inside the "Customer" module:
in config.xml of "Customers" module:
<shipping>
<rewrite>
<rate_request>Mycompany_Customer_Model_Shipping_Rate_Request</rate_request>
</rewrite>
</shipping>
Then the file "Mycompany/Customer/Model/Shipping/Rate/Request.php" contains the code to remove '-' char from postcode.
Our doubt is: In some cases, we need to rewrite the "Shipping/Rate/Request.php" again to modify other methods. Which is best?
Every rewrite is done inside the module that came from? Creating repeated files of the same class.
Use the same directory structure of Magento's core inside the "Mycompany" namespace and modify all that we need inside one file of each class? Like Magento's core?
I don't know if I could explain what I need.
Thanks!
It's best to keep the contents of a module within it's module folder.
If the extends you are talking about are part of a module's functionality than you should place them inside that module's folder. The path would then be local/mycompany/Mymodule/Model/Shipping/Rate/Request.php.
I would create this extra level in the dir structure to make it clearer that the rewritten Request.php comes form the Shipping module, but this is absolutely not a necessity.
The reason why this is a good practice is of course modularity. You will be much more able to add, remove and version modules that are contained within one folder. Think about the module's xml file in app/etc/modules and the config files in your module's directory. They describe what is in your module's directory and not all the rewrites that belong to it but are in different module folders.
Besides, if you have extended or rewritten the same model from multiple modules and you decide to remove or totally rewrite a module of your own, how will you know which files or parts of files will belong to it if they are scattered around the app dir.
For a more detailed view on how to create Magento modules please also have a look at http://www.magentocommerce.com/magento-connect/create_your_extension/

What should be required for createBlock

I want to create a block and add that block to my template via
$this->_addContent($this->getLayout()->createBlock("device/device"))
Right now, it is not displaying anything.
What are the points to be Noted so that my block will get rendered (what are the files to be aware off?)
Note:
COMPANY NAME: Abc
MODULE NAME: Device
Also, createBlock("device/device") returns "false"
The device/device string that is being passed to createBlock is a class alias. Class aliases give the Magento developer a way to refer to classes without using the actual class name. This indirection allows for one class to be substituted (or rewritten in Magento terminology) for another without having to change any code which instantiates and uses the class.
You start by defining the prefix for your classes in your module's config.xml file as follows (note: add this code into any existing tags, rather than just dropping it in at the bottom of the config.xml):
<config>
<global>
<blocks>
<device>
<class>Abc_Device_Block</class>
</devicer>
</blocks>
</global>
</config>
When building the class name for a block, the part of the xml is the part which comes before the / in the alias, and is substituted for the contents of the tags when generating the class name. The / is then replaced with an _ and the remaining part of the class alias is appended to the class name. So with the class alias device/device, and the above XML, the following class name will be built Abc_Device_Block_Device, which Magento will expect to find in Abc/Device/Block/Device.php. It will search folders in the order specified in the include_path, which is normally app/code/local, then app/code/community, followed by app/code/core and finally `lib.
The same basic logic also applies to model and helper classes.
Alan Storm's indispensable CommerceBug extension has a great tool for testing what model/block/helper class aliases map to in terms of class names and file locations.
The other parameters on this method are a name which can be used to refer to the block (and modify it) from layout XML files, and an array of other attributes which could be found in the layout XML.
That was an excellent answer Jim. Adding a point to it, the priority is the
Local
Community and then comes
Core if I was not wrong .

Can I override Magento Varien classes?

I know how to override Mage classes (any class within app/code/core)
My question is how to override Varien classes? (classes within lib/Varien)
If I want to override Mage_Adminhtml_Block_Page_Menu
I create a class MyCompany_Adminhtml_Block_Page_Menu under app/code/local/MyCompany/Adminhtml/Block/Page/Menu.php
I name it like:
class MyCompany_Adminhtml_Block_Page_Menu extends Mage_Adminhtml_Block_Page_Menu
Now Magento uses my class MyCompany_Adminhtml_Block_Page_Menu instead of Mage_Adminhtml_Block_Page_Menu
My question is: where should I put the new class, and how to name it, to override, for example Varien_Date (lib/Varien/Date.php)
Thanks
If you must, copy the file and path to the local codepool and make the necessary changes. There is no configuration mapping to change the class name.
Explanation: see the bootstrapping in app/Mage.php. There is a load order set for the codepools and libraries in the following order:
app/code/local/
app/code/community/
app/code/core/
lib/
Typically, Varien_Autoload is responsible for mapping classnames such as Varien_Data_Collection_Db, Mage_Core_Model_Abstract, or Zend_Db_Select to relative filenames (Varien/Data/Collection/Db.php, Mage/Core/Model/Abstract.php, and Zend/Db/Select.php respectively). These file locations are then passed to include(), which internally uses the load order set in the bootstrap. Therefore, if the file Varien/Data/Collection/Db.php is present under one of the "earlier" locations, that version of the class definition will be used.
These type of modifications may be justified, but they should be well-considered and documented, as the entire definition will be owned by you and any upgrades will need to be merged in the future. It would be good to know what you would like to change, as someone else may have a slightly less invasive option.

Resources