Subesh Pokhrel

Magento Developers Blog

MagNote Series - Magento Log

In this blog I have always shared about what I’ve learned on Magento, which I felt is taken me one step closer to understanding Magento and Magento development. But during the course of time, I bump on some elementary things which are absolutely required. So just for those elementary things I’ve decided to create a series (MagNotes Series) , for myself as a reference or for whoever think this is helpful.
One of the most useful method of tracking how your code is working is by writing a log of things happening between your lines of codes. Magento by default has provided a very helpful static function for this purpose in final class Mage. public static function log($message, $level = null, $file = ”, $forceLog = false) $message Data you want to log. Can be string, array, object anything. $level Log message level. The detailed list of type of message level can be found on Zend_Log. Here are the list which you can use. [source lang=”php”] const EMERG = 0; // Emergency: system is unusable const ALERT = 1; // Alert: action must be taken immediately const CRIT = 2; // Critical: critical conditions const ERR = 3; // Error: error conditions const WARN = 4; // Warning: warning conditions const NOTICE = 5; // Notice: normal but significant condition const INFO = 6; // Informational: informational messages const DEBUG = 7; // Debug: debug messages [/source] By default the function uses Zend_Log::DEBUG. $file Log file name relative to var/log, if you do not provide a file name then the default value for logfile name in settings will be used. If you haven’t changed then it would be system.log. $forceLog This parameter defines if you want to override the log settings of the backend. So if you absolutely want to log your data whatever the condtion then this value should be set to true.

Ajaxify v1.0.0 : Extension to Help in Working With Ajax in Magento Released on Magento Connect.

Get Extension from Magento Connect
I have few blog posts regarding working with Ajax on Magento. http://subesh.com.np/category/ajax/. And I see many people visiting those pages to get the information on working with Ajax in Magento. Sensing the need of developer I came up with an idea of making the whole process into a module in an effort to give back to the Magento community. I’ve tried to make the module simple for now, which of course can be extended a lot to incorporate all kinds of needs. But for now, if I may say, there are roughly these two things you might want to do (Purely in Magento terms).
  1. Request to a controller with params, do some changes in the model, set error/success message and show those message to the user.
  2. Next, perform all the actions as #1 and in addition to that refresh the content of certain HTML elements.
This module has been devised just to meet these two actions. In addition, the module is loader ready and has by default a floating message block. Followings are the ways you can perform those two actions using this module. Overview The core functionality implemenation is done in js/ajaxify/ajaxify.js file. If you look into that file, you will find a JS Class. The constructor for the class are:
  1. URL of the request controller.
  2. Parameters (JSON object) to be sent as request params to the controller.
For request and show message just call request() method, while if you want an HTML element to be updated then call requestUpdate(‘elementID’), with element ID in the parameter. Request to a controller with params, do some changes in the model, set error/success message and show those message to the user. This is how you initillize the JS Object. [source lang=”javascript”] <script type="text/javascript"> var ajxObj = new SpAjaxify(‘<?php echo $this->getUrl(‘ajaxify/index/test’) ?>’, {id: ‘12’, value: ‘23’}); ajxObj.request(); // Request </script> [/source] To set the message error/success you have to use ajaxify/session model, because it is from this model the messages are shown. [source lang=”php”] /** * Always use this session to set your error or success message * * @return Sp_Ajaxify_Model_Session * * PLEASE DO NOT EDIT THIS */ protected function _getSession() { return Mage::getSingleton(‘ajaxify/session’); } // Set Error message . $this->_getSession()->addError(‘Item was not added to the shopping cart.’); // Set Success message $this->_getSession()->addSuccess(‘Item was successfully added to the shopping cart.’); [/source] In addition to the above refresh the content of certain HTML elements. [source lang=”javascript”] <script type="text/javascript"> var ajxObj = new SpAjaxify(‘<?php echo $this->getUrl(‘ajaxify/index/test’) ?>’, {id: ‘12’, value: ‘23’}); ajxObj.requestUpdate(‘sidebar_cart’); // Ajax request with parameter to update the HTML element. </script> [/source] The source also contains description of the hidden logic to manage templates/layouts required. Fork me on GitHub

External Database Connector FAQ’s

We have been receiving a lots of comments on how to “install” External Database Connector (Formarly, TTT_EDB) in Magento. So we thought why not clear that out some of the questions we received here and lets see if this will help you and all. First of all we would like to say that this is not a fully functional module (Don’t Panic..), meaning you will not be able work with tables of external database just by configuring the settings of the module. You will have to code your associated Model/Collection classes based on the Magento External Database Connector Released. Few things which came and we would want to clear out. 1. I tried to install the module via Magento Connect, but showed some error during installation? We have packaged this extention using Magento 1.5.x. There are complaints on installing using Magento Downloader v1, please use Magento Downloader v2. We will try to fix this problem for v1 ASAP. 2. Which Config file do I have to use/edit? In Magento, database connection settings can be found on app/etc/local.xml, but we are NOT talking about that settings. If we say a config file we are talking about Sp/Edb/etc/config.xml. 3. How do I configure Edb to use my external database’s table? Edit Sp/Edb/etc/config.xml and find the [entities]. You will then find a child node there [report]. Change that to your table alias (lets say magician). Also change the value of [table]tbl_magician[/table]. The value for [table] should be the table name of the external database you want to work with. If you want to work with multiple tables of the external database, you will have to add multiple alias and its respective table name. Note #1 that the nodes are shown in [ ], because of the rendering issue. Note #2 that you can do the same in your own Module’s config file. 4. How to define Model/Resource/Collection? If you follow the basic step defined http://subesh.com.np/2012/02/magento-external-database-connector-v1-0-0-released/. You should be able to set all those up. For multiple table access you must create multiple Model/Resource and Collection. 5. How do I test if it’s working? Simplest method would be in your cron.php file found on installed Magento’s root folder. Open the cron.php file and inside the try block call the model you just created write the following. If you have followed the documentation exactly as in the link above, then [source language=”php”] try { $model = Mage::getModel(‘edb/magician’); // This data will depend on your table schema. $model->setName(‘The three Tree’)->save(); $model->setName(‘TTT’)->save(); exit; —- —- } [/source] Then run the cron.php from your browser example.com/cron.php. After this see you external database table, a new row should be inserted. Hope this clarifies something if not everything. Please send us feedbacks, we would be happy to address that.

Magento External Database Connector Released

Formarly Known as The Three Tree External Database Connector
Magento External Database Connector module will be helpful for the “Developers” who want to connect to the external Database server (other than the database used by Magento). This module will help the developer to set up a connection object (Read & Write) with the configuration configured in Admin Settings and use that connection to do database transactions on external database.
All you have to do is set the settings of your external database connection in your Magento Settings and extend your model/collection class with the class of this module and use other codes as you have been using in Magento to select/update/delete records.
It will be as simple as Mage::getModel(‘mymodule/mymodel’)->setData(‘name’,’The Next Tree’)->save()
Here is the explanation of how you can use the External Database Connector module’s classes to define your
  1. Model
  2. Resource Model
  3. Collection
Lets take a simple example. Say you have a table (of course in an external database) named tbl_magician, which has two just two columns id and name. First thing set up an entity definition in the config.xml file of your module or you can add in this module’s config as well. [source language=”xml”] <entities> <!– Add As many tables config here –> <magician> <!– Table alias –> <table>tbl_magician</table> <!– Actual Table Name –> </magician> <!– Add As many tables config here –> </entities> [/source]

Model Defination

All of your Model that uses the external source has to be extended by Sp_Edb_Model_Abstract. If you see on this class you can find that the connection has been established based on the settings you do on Magento backend. An example for your model class will be something like this. [source language=”php”] <?php class Sp_Edb_Model_Magician extends Sp_Edb_Model_Abstract { /** * Initialize resources */ public function __construct() { parent::__construct(); $this->_init(‘edb/magician); } } [/source] If you are wondering where to set up your connection settings go to System–>Configuration–>SP EDB and add your settings there.


Resource Model

Similary your resource model should extend one another class of the module as shown below. [source language=”php”] <?php class Sp_Edb_Model_Mysql4_Magician extends Sp_Edb_Model_Mysql4_Abstract { protected function _construct() { $this->_init(‘edb/magician’, ‘id’); } } [/source]

Collection

As you might have already guessed yes..! collection also needs to be extended by one another class of the module as below [source language=”php”] <?php class Sp_Edb_Model_Mysql4_Magician_Collection extends Sp_Edb_Model_Mysql4_Collection_Abstract { /** * Local constructor * */ protected function _construct() { $this->_init(‘edb/magician’); } } [/source]
All those parent classes used are themselves extended from the classes which Magento uses for Model or Resource or Collection. So there is no any functionality missing and you can use the same old methods for insert/update or select.
After setting up all these classes you can now just freely use these functions without keeping external connection in mind. [source language=”php”] $model = Mage::getModel(‘edb/magician’); // To save $model->setName(‘The three Tree’)->save(); $model->setName(‘TTT’)->save(); // Get Collection $collection = $model->getCollection(); $collection->getSelect()->where(‘main_table.id = ?’, 1); [/source] If you have any confusion we would be happy to address that.The module is now available on Magento Connect. FAQ’s

MagDoc – Powered by Scribd Released on Magento Connect

MagDoc will give store administrator a feature of managing/displaying document in the Magento storefront powered by richly featured “the world’s largest social reading and publishing platform” - Scribd. This module provides a unique user experience for reading a document online using the Scribd Reader application embedded in HTML. Get this extension on Magento Connect

Features

  1. Uses the free API service provided by Scribd to upload and manage your document from the Magento administration area.
  2. Upload as much document you want to upload, because there is no restriction on the storage limit.
  3. Tag your uploaded documents on Scribd.
  4. Set scope Private or Public for your uploaded document.
  5. Upload and transform any file – including PDF, Word and PowerPoint – into a web document that’s discoverable through search engines, shared on social networks and read on billions of mobile devices.
  6. Assign uploaded files to your product which can be shown in the storefront using a multi functional online Scribd Reader.
  7. Supports all the document formats supported by Scribd. This list of the supported format can be found on This Location

Installation Guide

  1. Get the extension from Magento Connect.
  2. Install the extension from Magento Connect Manager.
  3. Voila! Installation completed.

Setting up the Module

  1. Sign up for an account on http://www.scribd.com
  2. Get the API Key and Secret Key from Scribd. The procedure for getting your API key and Secret Key is described on http://support.scribd.com/entries/25453-where-can-i-find-my-api-key.
  3. In Magento backend goto System–>Configuration–>MagDoc–>Settings.
  4. Fill out the API key and Secret Key value you obtain from Scribd and save the settings.
  5. Now the module is set up and ready to be used.

User Guide

  1. Document can be uploaded on Scribd from Magento administration area. In admin area go to Magdoc–>Manage Document. You can add/edit/delete documents from here.
  2. Documents can be assigned to product. Create or Edit any product. A new option for selecting the document for the product will be visible in the product edit area. But make sure the attribute “magdoc_id” is already in the attribute set of the product being edited. Select the required document and save the product.
  3. Visit the product details page on the frontend. The document will be visible using Scribd Reader.

Developer Guide

To display Scribd document in the product details page. This should be placed in appropriate place. Also you can see that the height and width for the Scribd Reader can be configured from layout. [source lang=”xml”] <block type="magdoc/magdoc" name="magdoc" template="magdoc/magdoc.phtml"> <action method="setDocumentHeight"><width>600px</width></action> <action method="setDocumentWidth"><width>850px</width></action> </block> [/source] Here’s a tip for showing the Scribd document on tabs on product details page. [source lang=”xml”] <block type="catalog/product_view_tabs" name="product.info.tabs" as="info_tabs" template="catalog/product/view/tabs.phtml" > <action method="addTab" translate="title" module="catalog"> <alias>magdoc</alias> <title>Document</title> <block>magdoc/magdoc</block> <template>magdoc/magdoc.phtml</template> </action> </block> [/source] I hope the module will be useful for the store owners. If you have any feedbacks, please report in the comment section below.
Disclaimer: Scribd is the property of Scribd Inc. This module is NOT the official module of Scribd.

Debugging Magento Using Eclipse on Ubuntu

I’ve previously posted http://subesh.com.np/2010/01/debugging-magento-eclipse-pdt-zend-debugger but currently I think it was just a snub. What I currently do now is far more better approach then the previous one. Here is how you can set up a debugging environment in Ubuntu using Eclipse for debugging Magento. [Note: I am describing here based on Ubuntu.] Step 1: Download and Install Eclipse Download and Install Eclipse. Choose the relevant package to download. Unzip the package and copy to some location. Lets say /home/user/ Please note that the Eclipse IDE requires that a Java Runtime Environment (JRE) be installed on your machine to run. Java SE 5 or greater is recommended. Step 2: Setting up PHP Project Next thing you have to do is to setup the project in Eclipse. Open the Eclipse IDE and it will ask for your Workspace. Browse to your workspace (Where your Magento site is running locally) or by default point it to /var/www and click OK. Now click on File–>New –> New PHP Project, and add your folder name on Project Name and click Finish. Eclipse will take few time on building your project, so take a coffee break if you want and be back in few minutes to go through the steps below. Step 3: Installing X-Debugger [source lang=”shell”] sudo apt-get install php5-xdebug [/source] Step 4: Configure X-Debugger Type this in your command prompt. [source lang=”shell”] sudo gedit /etc/php5/apache2/conf.d/xdebug.ini [/source] And add this settings on the .ini file [source lang=”shell”] xdebug.remote_enable=1 [/source] And restart the apache server. [source lang=”shell”] sudo /etc/init.d/apache2 restart [/source] Step 5: Debug Configuration on Eclipse On menu click Window–>Preference. Find PHP–>Debug Node in the left. When you click Debug you can see screen like this. Select PHP Debugger - XDebug. To Set Server click PHP Servers and add new server as follows and click Finish. Step 6: Configuring debug conf for Magento Projects On menu click Run–> Debug Configurations. Find PHP Web Page and Right click for adding new configuration. Add something similar to like this. Step 7: Add Break-Point and start debugging Now almost all the settings are done. Now you can just add a break-point on your code and start debugging your script by clicking the BUG icon on the top bar. Few tips though before you start.
  1. Set up an external browser to run your debug configuation. Go to Window–>Preference and type in web browser in the top left search. And you will get a result. Click on Web Browser to select Use External Web Browser. If that is not clickable first click the restore default button and then the external web browser should be clickable.
  2. You can enable multi-session debug, because you do not want to always click the debug button after each debug end. For that go to preference. Search for debug. Find PHP –> Debug –>Installed Debugger. Click the XDebug and then click configure. You can then Check the Use Multisession checkbox and save.

Happy Dashain Holidays!

Its time for all of Nepal to mark their “only” long term holidays. It’d Dashain time and don’t expect me to come up with things during this week long holidays. Image courtesy: nepalifonts.blogspot.com

Custom Query in Magento a Zend Approach [Updated]

I’ve already mentioned about custom query in Magento, before but now I think its time to upgrade that method to next level because it would always be good to have standard code for reference.So it is just a new improved way of using a custom query. First of all we will need is a connection instance. Lets use default_setup instance because it can used for read and write purpose. [source language=”php”] $connection = Mage::getSingleton(‘core/resource’)->getConnection(‘default_setup’); [/source] Then we will use this connection to instanciate Zend_Db_Select object and write query like [source language=”php”] $select = new Zend_Db_Select($connection); $table = ‘catalog_product_index_price’; $select->from($table, array(‘entity_id’)) ->where(‘entity_id = ?’, $entityId); // Getting result $result = $select->query(); $rowCount = $result->rowCount(); if ($rowCount) { foreach ($result->fetchAll() as $data) { return $data[‘entity_id’]; } } [/source] The above one is for select but what about inserting data? It is simple as well. All you have to do is create an associative array of data to be inserted and use connection to add data. For example [source language=”php”] $connection = Mage::getSingleton(‘core/resource’)->getConnection(‘default_setup’); $table = ‘catalog_product_index_price’; $insertData = array(); $insertData [‘price’] = $productPrice; $insertData [‘final_price’] = $productPrice; $insertData [‘min_price’] = $productPrice; $insertData [‘max_price’] = $productPrice; $insertData [‘tier_price’] = $productPrice; $connection->insert($table, $insertData); [/source] I think this should be a good enough code for using custom query in Magento. About Zend_Db_Select please visit http://framework.zend.com/manual/en/zend.db.select.html. [UPDATE] If you want to update the data with custom query and have a condition then you can send the conditions as array as third params to update function. For example. [source language=”php”] $connection = Mage::getSingleton(‘core/resource’)->getConnection(‘default_setup’); $table = ‘catalog_product_index_price’; $updateCond = array(); // Update condition array container. $insertData = array(); $insertData [‘price’] = $productPrice; $insertData [‘final_price’] = $productPrice; $insertData [‘min_price’] = $productPrice; $insertData [‘max_price’] = $productPrice; $insertData [‘tier_price’] = $productPrice; $updateCond [] = ‘store_id = 0’; $updateCond [] = ‘entity_id = 3’; $connection->insert($table, $insertData, $updateCond); [/source] Happy Brogramming!!

Generating Invoice/Order’s Next Increment ID in Magento

Magento has its own way of generating increment ID for new invoices and new orders after they are saved. But how about knowing them before hand, i.e before the invoice or the order is created! Lets first understand the working of those increment ID generation before jumping to the code. As all of us must have known there are “Entity Types” in Magento. And those “Entity Types” are stored in table named eav_entity_type. If you look into that table for entity_type_code = order or invoice, in increment_model column you can see the Model alias used to generate new increment ID code. Lets take the case of invoice..so the increment model is eav/entity_increment_numeric and additionally this increment is store dependent as for this row increment_per_store is set to 1. Next place to look into will be .. Yes! the model eav/entity_increment_numeric. And if you see the model class Mage_Eav_Model_Entity_Increment_Numeric there is only one Method in this class the public function getNextId() which is responsible to the the Next increment ID, needless to say its parent has other methods as well since you might have already understood. So if some how you can trigger the right Increment Model for any entity type and the call this method, you must get the next increment ID of order/invoice/shippment. That was the “prose” part now lets get down to the “code poetry”. Here’s how you first find the appropriate increment ID and then fetch the new Increment ID. [source language=”php”] //Get the Entity Type Increment Model you want, our case invoice // @var $entity_type_model Mage_Eav_Model_Entity_Type $entity_type_model=Mage::getSingleton(‘eav/config’)->getEntityType(‘invoice’); //Triggering the getNextId() of the Increment Model //@var $invoiceNew Mage_Sales_Model_Order_Invoice $new_incr_id = $entity_type_model->fetchNewIncrementId($invoiceNew->getOrder()->getStoreId()); [/source] Now, you have the generated Invoice Increment ID. This can be helpful in cases when you want to do something else before Invoice is created but you want to now the Increment Id before hand. Hope this helps.

Adding Custom Javascript on Admin Form in Magento (Backend)

Sometimes in Magento, while creating a custom module we need to add our custom Javascript code in our Admin form. These Admin forms we create are extened from the Magento’s core form widget. So there is a less flexibiliy of adding a custom Javasccript code in such types of Admin forms. What to do if you really need to add some custom Javascripts to give user a better user experience? In this post I’d like to point two conditions how/where to add such custom Javascript codes in the Form class, so that you can give user an interactive Admin form. The two conditions are:
  1. If an element of the form already has a value, disable that form element.
  2. On triggering an event by acting on some form element to change other form’s element’s attribute value.

If an element of the form already has a value, disable that form element

Lets take an example of core’s customer creation Admin form. What we can see while creating a customer from Admin end, the field “Associate to Website” is available to change for the first time. But when you are editing a customer info the very field is disabled. Lets see how this can be acheivable. If you look into Mage_Adminhtml_Block_Customer_Edit_Tab_Account class you can see the following chunk of code. [source language=”php”] if ($customer->getId()) { $form->getElement(‘website_id’)->setDisabled(‘disabled’); $form->getElement(‘created_in’)->setDisabled(‘disabled’); } [/source] What this does is checks for the Id of the customer if it is present the form elements disabled attribute is set to disabled. So initially while creating a new customer this condition is not fulfilled while on edition of the customer data the condition is fulfilled and hence the form element website_id and the created_in are disabled. This was just an example, you can also write similar conditions for your custom form. Suppose your data for the current form is in $formData variable and then by checking certain field value you can add similar condition. [source language=”php”] $formData=Mage::registry(‘current_custom_data’); if(!empty($formData->getMyField())){ $targetElement=$form->getElement("my_field"); //For Disabling the field (Value will not be posted on form submit) $targetElement->setDisabled(‘disabled’); //Or for making the field readonly $targetElement->setReadonly(true); } [/source]

On triggering an event by acting on some form element to change other form’s element’s attribute value

Lets take the same customer edition page, you can see a checkbox with label Send auto-generated password. If you check that checkbox then the New Password textfield above it gets disabled. To get the similar interactivity for custom form you will have to do as following. [source language=”php”] $eventElem=$fieldset->addField(‘nocode’, ‘checkbox’, array( ‘label’ => Mage::helper(‘customer’)->__(‘Event Element’), ‘name’ => ‘eventelem’, ‘id’ => ‘eventelem’, ‘value’=>1, ‘onclick’=>’modifyTargetElement(this)’, )); $eventElem->setAfterElementHtml(‘<script> function modifyTargetElement(checkboxElem){ if(checkboxElem.checked){ $("target_element").disabled=true; } else{ $("target_element").disabled=false; } } </script>’); [/source] What you can see is after an element of a form is initiallized you can add HTML codes (which of course for us is only Javascript code) by calling a setAfterElementHtml method and write the implementation of the function called on the event of the Event element. I’ve tried to be more explanatory as possible, if you still have any confusion there is always a comment box below. Happy Coding!