Following the Magento tutorial I realised I dont understand casing in magentos XML files. I can't work out when something should start with an uppercase letter, when it should be camel cased and when the string should be all lowercase. for example
<config>
<modules>...</modules>
<global>
<events>
<controller_front_init_routers>
<observers>
<Magentotutorial_configviewer_model_observer>
<type>singleton</type>
<class>Magentotutorial_Configviewer_Model_Observer</class>
<method>checkForConfigRequest</method>
</Magentotutorial_configviewer_model_observer>
</observers>
</controller_front_init_routers>
</events>
</global>
I understand that after hitting the observers tag magento will look for a file called observer in the model folder of the configviewer folder within the magentotutorial folder and will then look for a class by the name held within the class tag.(Please correct me if im wrong)
What I dont understand is why the tag under observers starts with a capital and the following words are all lowercase and the class tag starts all words with a capital letter
An alternative example would be the codePool and frontName tags that are camelcased
Could someone please explain when and why capitals are and are not used.
Magentotutorial_configviewer_model_observer is just a namespace to keep things unique, say if you has multiple classes to fire off one event in one module. It does not have to be any case, the closing and opening elements just have to match, most people just generally use lower case.
For your other questions about camel casing I am not really sure, I think it may have something to do with the config defining a module rather than module config.
Magento has bizarre and inconsistent casing, modules are capitalised but only on the first letter, you can capitalise them all but it can cause real headaches because when you are calling the module you have to use camel case instead.
Related
I only need to add a method to the Mage_Core_Model_Abstract class.
For that, in my config.php I have
<models>
<mymodule>
<class>Mynamespace_Mymodule_Model</class>
</mymodule>
<core>
<rewrite>
<mage_core_model_abstract>Mynamespace_Mymodule_Model_Abstract</mage_core_model_abstract>
</rewrite>
</core>
</models>
It doesn't really work..
I know that there is a way of "overriding" by copying all the folder structure including the class file into my module, but I would like to know if there is a way to make it more fancy, within my module - something similar as above..
You can only rewrite classes that you instantiate directly, from config.xml.
The various values in config.xml are used when creating an object through a factory (e.g. Mage::getModel($class), Mage::getSingleton($class), Mage::helper($class), etc). The value of the $class argument is used to translate catalog/product into Mage_Catalog_Model_Product.
This means it's impossible to rewrite (in the Magento sense) classes that are used as superclasses, including abstract classes (by definition).
If you want to redefine any class that's used as a superclass, then you'll need to place a file in the correct place further up the include path. In this case, you'd need to make a file in app/code/local/Mage/Core/Model/Abstract.php.
I tried to override Pdf classes for making changes toInvoice/Shipment/Creditmemo pdf but it doesnt seem to reflect.
I created a module with following in the Mymodule/etc/config.xml
<config>
<modules>
<Mymodule_Printtemplates>
<version>0.1.0</version>
</Mymodule_Printtemplates>
</modules>
<global>
<models>
<sales>
<rewrite>
<order_pdf_abstract>Mymodule_Printtemplates_Model_Order_Pdf_Abstract</order_pdf_abstract>
<order_pdf_invoice>Mymodule_Printtemplates_Model_Order_Pdf_Invoice</order_pdf_invoice>
<order_pdf_creditmemo>Mymodule_Printtemplates_Model_Order_Pdf_Creditmemo</order_pdf_Creditmemo>
<order_pdf_shipment>Mymodule_Printtemplates_Model_Order_Pdf_Shipment</order_pdf_shipment>
</rewrite>
</sales>
</models>
</global>
Then I created following Model classes in Mymodule/models/
as Abstract.php, Invoice.php, Shipment.php, Creditmemo.php
abstract class Mymodule_Printtemplates_Model_Order_Pdf_Abstract extends Mage_Sales_Model_Order_Pdf_Abstract
class Mymodule_Printtemplates_Model_Order_Pdf_Invoice extends Mymodule__Printtemplates_Model_Order_Pdf_Abstract { ... functions here ...}
class Mymodule_Printtemplates_Model_Order_Pdf_Shipment extends Mymodule__Printtemplates_Model_Order_Pdf_Abstract{ ... functions here ...}
class Mymodule_Printtemplates_Model_Order_Pdf_Creditmemo extends Mymodule__Printtemplates_Model_Order_Pdf_Abstract{ ... functions here ...}
The module is enabled - I have checked it through System>Configuration>Admin>Advanced but it doesn't seem to reflect the changes
On the other-hand, if I copy paste Mage/Sales/Model/Order/Pdf/*.php into local and change, changes are reflected. I know this is not a recommended method but the method via rewriting classes doesnt seem to work.
Any help for the first method via class rewrite would be appreciated.
Thanks,
Loveleen
The real problem was a Syntax in error in etc/config.xml [see Capital C in ending tag]
Mymodule_Printtemplates_Model_Order_Pdf_Creditmemo
I used the following to debug the issue: Drop this in the bottom of your index.php, similar to Alans Module List but a quick code copy/paste approach. Remember all of Magento's XML's get combined into one XML tree.
header("Content-Type: text/xml"); die(Mage::app()->getConfig()->getNode()->asXML());
Taken from the answers of: How do I know whether my Config.xml file is working in Magento?
Here are a couple of things that I am seeing.
What are the file paths to each of your overridden files? They should be: Mymodule/Printtemplates/Model/Order/Pdf/Invoice.php, for example. The class name should match the file name.
Rewrites do not affect abstract classes, unless the abstract class is called with a factory method (not recommended). The way that a rewrite works is through the factory methods (Mage::getModel('')). Using the factory method allows Magento to look through the system to see if another class is needing to be used. However, when a class is hard-referenced (e.x. Mage_Sales_Model_Order_Pdf_Abstract), it does not go through the factory method, and thus no rewrites will occur on that.
I would consider making each of your classes extend their original class (e.x. Mage_Sales_Model_Order_Pdf_Invoice, etc). If you have extra common functions, you would possibly put those into a Helper.
To see if the code is even being called, put a known code error in the file. PHP will complain, and that tells you that your file is being loaded.
I used the following to debug the issue:
Drop this in the bottom of your index.php, similar to Alans Module List but a quick code copy/paste approach. Remember all of Magento's XML's get combined into one XML tree.
header("Content-Type: text/xml");
die(Mage::app()->getConfig()->getNode()->asXML());
Taken from the answers of: How do I know whether my Config.xml file is working in Magento?
Let's say you have a class name Space_Module_Model_LongModelName and you want to reference it as:
Mage::getModel('module/longmodelname');
This seems to work in some development environments, but doesn't seem to work in all environments. Probably has to do with a file system case sensitivity setting.
The error that you get in environments where it doesn't work is that the include() for Space/Module/Model/Longmodelname.php failed.
You have a config-node in your config.xml called global/models/yourpackage in which you save your Prefix for your class models.
When you call Mage::getModel('packagename/classname') Magento fetches this config node e.g. Company_Yourmodule_Models adds a _ and then the classname with uppercase first letter:
Company_Yourmodule_Models_Classname
if you have cAMElcaSe classnames, it is the same way. So let's say your class' name is ClassName then you have to call Mage::getModel('packagename/className') and magento resolves it to: Company_Yourmodule_Models_ClassName
Take a look at app/code/core/Mage/Core/Model/Config.php specifically getGroupedClassName(); as you'll notice uc_words is used in the method when building the $className, which will capitalize every other word in the class name string.
So your class name of LongModelName will become Longmodelname for the include.
You could easily extend this to work the way you want but since its such a main piece of Magento's factory generation personally I would not touch it in fear of breaking other 3rd party modules, and live with the non-camel case namespace.
The reason ImportExport works is because it is the module name and not a class name. I've run into the same issue before and as annoying as it is I tend to just keep class names non-Camel cased.
For sure there is possibility to use camelcase - you can see module e.g. ImportExport in Magento core. I think all is about setting correct (with camel cases) names in xmls
Four years later, another note:
If you want to use camelCased classnames in addition to filenames, make sure the following part of your {moduleName}/etc/config.xml is camelCased as well:
```xml
<global>
<models>
<ProbablyYourCompanyOrModuleName>
<ModuleName_resource>
<entities>
<!-- "longModelName" below should be CamelCased, but prob the first letter will be lowercased -->
<longModelName>
<table>your_db_table_name</table>
</longModelName>
</entities>
</ModuleName_resource>
</ProbablyYourCompanyOrModuleName>
</models>
</global>
```
The portion should be camelCased with the first letter lowercased. Otherwise, you'll get an exception of Can't retrieve entity config: yourmodule/longModelName
(see Mage_Core_Model_Resource::getTableName())
Magento, versions CE 1.4.2, 1.5.0.1, 1.5.1.0
I have had to adapt a payment module for Magento, following all recipes, config.xml, system.xml, etc/module/Mycompany_Mypaymentmodule.xml, which all work fine.
But recently, I've double checked and found an error:
in my config.xml, I had put:
<config>
<modules>
<Mage_Mycompany>
<version>0.1.0</version>
</Mage_Mycompany>
</modules>
...
That's because originally, the module was supposed to be placed inside the community-folder.
Following the guidelines, I've rewritten classes, xml's et cetera to reflect the local codepool. That too went well (except for an error that I had debugged).
However, inside the config.xml, I have renamed the modules-tag, like so:
<config>
<modules>
<Mycompany_Mypaymentmodule>
<version>0.1.0</version>
</Mycompany_Mypaymentmodule>
</modules>
The strange thing is that Magento now keeps asking me for the old Helper-class-file when I go to the Payment Methods in the backend, resulting in:
Fatal error: Class 'Mage_Mycompany_Helper_Data' not found in path\to\app\Mage.php on line 520
In other words, Magento keeps asking for a helper class of my old, pre-renamed module, which of course is nowhere to be found.
I've done an extensive search in all files, but nowhere is the string Mage_Mycompany to be found, so my guess is Magento is trying to load this helper class out of a database table. Of course, I've cleared the cache and rebuilt all indexes multiple times, and removed all cache files. I also checked practically all database tables, but to no avail.
Second, when I create the helper class by hand in app/code/community/Mage/Mycompany/Helper/Data.php, all goes well, which to me sounds strange, because the class itself should not be called (since it is never mentioned in any config.xml).
I must be missing something, and perhaps the class name is generated on the fly, but I really do not know how to avoid it or to fix it... so any help is appreciated!
Step one, of course, is to clear your cache.
If clearing cache doesn't work.
Step 2: The data helper class is used to translate strings for a module. That is, each data helper has a method
$helper->__('Translate this symbol');
that will translate a string per that module's helper file.
Throughout the system, there are several XML files where you may want certain nodes to be translated. The syntax looks something like this.
<dhl translate="label" module="usa">
<label>The Label</label>
</dhl>
Here you're telling magento to translate the "label" node enclosed in dhl, and to use the usa module to do it. That is, use the helper instantiated like
$Mage::getModel('usa/data');
//same thing as above, helpers default to data
Mage::getModel('usa');
to translate the label
$helper->__('The Label');
My guess is one of your XML files still has your old module configure for translation
<sometag module="mycompany" translate="someothertag" />
which makes magento look for a helper that's no longer there, and boom, there's your error.
Tha Data helper is loaded when you call the translation helper, ie: Mage::helper('modulename')->__("some string to translate").
In your config .xml, have you declared the module's helper class?:
<config>
...
<global>
...
<helpers>
<yourmodule>
<class>Yourcompanyname_Yourmodule_Helper</class>
</yourmodule>
</helpers>
...
</global>
...
</config>
I am trying to create an event dispatcher in Magento (which should be called after a product gets added to cart).
What I've done so far:
I Googled this and found this link. I followed the instructions specified in this link. I configured the config.xml file and created a Observer.php filder under mymodule/model folder. But, I can't see any result from this.
(The code for config.xml and Observer.php file that i used in my example can be found under http://goo.gl/O7dBy, my custom module name is Crossdata and package name is MyModule - am i doing it wrong?)
Any other link with simple helloworld event dispatcher example would be helpful.
Thanks,
Balan
Looking at your code downloaded from http://goo.gl/O7dBy you define:
<events>
<add_to_cart_after>
<observers>
<add_to_cart_after>
<class>dispatcher/observer</class>
<method>hookToAddToCartAfter</method>
</add_to_cart_after>
</observers>
</add_to_cart_after>
</events>
and define the model alias of dispatcher as:
<models>
<dispatcher>
<class>MyPackage_Crossdata_Dispatcher_Model</class>
</dispatcher>
</models>
The resulting class name would be MyPackage_Crossdata_Model_Dispatcher_Model_Observer, but your observer class is named MyPackage_Crossdata_Dispatcher_Model_Observer, missing the Model in between Crossdata and Dispatcher.
I'd recommend to drop the whole dispatcher models definition above and only use the other model alias crossdata which you've already defined in config.xml:
<crossdata>
<class>MyPackage_Crossdata_Model</class>
<resourceModel>crossdata_mysql4</resourceModel>
</crossdata>
Then change the event definition to:
<add_to_cart_after>
<class>crossdata/observer</class>
<method>hookToAddToCartAfter</method>
</add_to_cart_after>
Create a file /app/code/local/MyPackage/Crossdata/Model/Observer.php and define your observer class in it:
class MyPackage_Crossdata_Model_Observer
{
public function hookToAddToCartAfter($observer)
{
// your observer code
}
}
You added a folder for Observer.php, or a file? Can you post the code you wrote for this so we can better help debug with you? That tutorial is about as simple and straightforward as they get.
In your config.xml the short name given to your blocks and models is crossdata. Yet the event uses the alias dispatcher/observer, you have not defined a name dispatcher. This probably needs to be crossdata/observer.
The Inchoo example calls it's module Inchoo_Dispatcher and the model is Inchoo_Dispatcher_Model_Observer. Your module is MyPackage_Crossdata which means the alias crossdata/observer would try to load MyPackage_Crossdata_Model_Observer. But your observer is erroneously called MyPackage_Crossdata_Dispatcher_Model_Observer.
If your pasted code is not showing here in Stack Overflow either indent it by four spaces or use the {} button to format it. That is the preferable way to show code.