Subesh Pokhrel

Magento Developers Blog

Adding Tabs in Product View Page Through Layout in Magento

One of my new colleague, today asked me how to add tabs in product view page in Magento. He told me earlier he had used his own tabs CSS and Javascript to do, but now he found out that Magento gives default Tab Javascript to do the same. Then, I thought why not share with everyone else! Here it goes… It is extremely easy to add a tab and its Javascript, but comparatively difficult to make its CSS, and I won’t talk about that here :D. You can manage tabs in product page of Magento just through layout files. No need to work on Javascript. Just use the following xml tags inside your catalog_product_view layout. [source language=’xml’] additionalGeneral Infocatalog/product_view_attributes deliverytimeDelivery Time catalog/product_view printinginfoPrinting Info catalog/product_view notesNotescatalog/product_view [/source] In the code above the fourth tab, we have called addTab method of catalog/product_view_tabs block, with the parameters alias as notes, title as Notes, block as catalog/product_view and template as catalog/product/view/notes.phtml. After adding this in your layout, echo the following in your view.phtml file. [source language=’php’] getChildHtml(‘product.info.tabs’); ?> [/source] After that you will see four tabbed navigation in your product view page. Easy isn’t it?

Using Custom Query in Magento

Magento has given us very good features to manage Models and Collection for interacting with Database tables. Nowonder, they are very helpful in most of the cases. Yet, we may need to write custom query in some cases (if you need it quick or if you are new to Models & Collection in Magento). But by Magento’s standard this is not recommended. If you are a starter you may find this quering to database very helpful. Here is how you can do this. The idea is simply to get the core connection object and use its functions to run your query. [source language=’PHP’] getConnection(‘core_read’); $value=$read->query(“SE…”); $row = $value->fetch(); print_r($row); // As Array // For Write // fetch write database connection that is used in Mage_Core module $write = Mage::getSingleton(‘core/resource’)->getConnection(‘core_write’); // now $write is an instance of Zend_Db_Adapter_Abstract $write->query(“insert into tablename values (‘aaa’,’bbb’,’ccc’)”); ?> [/source]

General Workflow of Magento’s Import/Export - Dataflow

Magento’s Dataflow (Inport/Export) is one of distinguishing feature that makes Magento the leader in eCommerce Software. But for a programmer to understand how it workes in Magento can be quite nasty. I tried to understand how it workes and came up with following understanding.

General Work Flow (Profile)

During Import/Export there are normally two ”Actors” involved. Actors may be the data source (Actor: Source) and the final destination of the data (Actor:Destination). While you are importing data into your Magento Sytem, the Source is the CSV or XML file while exporting it is the other way round. In any case (Import or Export) you need to first fetch the data from the source and process it and then save to its destination. So Basically there are three stages in product import. But the processing part has been split into two. Processing part has been divided into two processes namely Mapper and Parser. I’ll come to the detailed description later. So along with the extended processes, lets call there are four “Actions” occuring during Import or Export.For every “Action” to run there are seperate individual Models. And the defination of all these individual Models for each Action during the Import/Export Process (Dataflow) is called ”Profile”. Here’s the basic workflow for Dataflow. [caption id=”attachment_124” align=”aligncenter” width=”473” caption=”General Workflow”]General Workflow[/caption] That was the laymen description of Dataflow, lets see what are the Jargons used in Magento to call all the Models used in Dataflow. The Models used for all actions are listed below according to how the Dataflow works.
  1. Adapter
  2. Parser
  3. Mapper
  4. Adapter (Yes twice)
  5. Validator (Not Implemented yet in Magento, left for future implemention)

Adapter

To understand what is Adapter, lets see Magento as a System and all the resources it uses during Import/Export as external source. So external source in Most of the cases can be either File or your Database (DB). Other external source include Webservice. I’ven’t came across other yet. :D So what Adapter does is it provides the channel through which the data actually flows in/out of the Magento System. As you can see in the images below is that there is always two Adapter involved. One that reads data from the file external resource and another that saves the data into the DB external resource. Now you should be clear why I wrote Adapter twice. If you are still wondering..then you can comment below. [caption id=”attachment_114” align=”aligncenter” width=”474” caption=”Case: Export”]Adapter: Export[/caption] [caption id=”attachment_121” align=”aligncenter” width=”479” caption=”Case: Import”]Case: Import[/caption] Magento has provides us some Default Adapter to read/write from/to external resources. Here are the Adapters listed. Adapter For Files : Mage_Dataflow_Model_Convert_Adapter_Io Adapter For Customer(DB) : Mage_Customer_Model_Convert_Adapter_Customer Adapter For Product (DB) : Mage_Catalog_Model_Convert_Adapter_Product Since the work of Adapter is to just Read or Write it has basically two Methods load() and save().

Parser

What parser does is that it just converts the raw data (Human Readable) from the source into Magento’s Format (Arrays and Setting Values of Magento’s Model) or from Magento’s Format into Human readable Format. Just to understand you can think of the CSV files seperated by comma changed into Arrays. After conversion is over it then saves the data to the Batch.Batch, what is Batch? if this is what you are thinking, here is your answer. Every row in CSV,XML or Row of the DB during the dataflow are saved as different rows in a table dataflow_batch_import or dataflow_batch_export. So if there are 100 rows in your CSV file you are importing into Magento, the batch will have 100 rows of parsed data in the table dataflow_batch_import. During the final stage of the Dataflow’s run this data is referred. Magento provides some default Parses as well. Parser for CSV files : Mage_Dataflow_Model_Convert_Parser_Csv Parser for XML files : Mage_Dataflow_Model_Convert_Parser_Xml_Excel Parser for Product : Mage_Catalog_Model_Convert_Parser_Product Parser for Customer : Mage_Customer_Model_Convert_Parser_Customer

In all these classes there are two main Methods which deservers to be stated here. parse() and unparse(). If you are Importing then parse() should be defined in your profile, because you are parsing the data that is required by the System. In case of Exporting, you already have the parsed data of the system as source, you will then need to unparse() the data into Human readable format. You can refer to images above to understand more clearly. So by the end of this during the profile run you will have Parsed/Unparsed data saved in the batch table, in you hand.

Mapper

Magento’s Dataflow is so flexible that you can set the header of the CSV or XML files that can mapped to the Magento’s default attributes. Let’s take an example if you want to export the product’s name into CSV with the CSV header as “Product Name”, you can specify that mapping in your profile where the Mapper will act. And in this the Magento’s attribute code “name” will be mapped to your specified “Product Name”. To do all this mapping rules, Mapper is there. It retrives the Parsed/Unparsed Data from the batch table, we got at the end of Parser’s work, Maps to the rule we defined and then again saves back to the same table. Easy! There is one default Mapper for all Mapper : Mage_Dataflow_Model_Convert_Mapper_Column With one obvious method map(). At the end of this stage you will have your Parsed/Unparsed - Mapped Data in your dataflow table.

Adapter (Again)

At last the Adapter will use the dataflow’s batch data to save(). And after all the rows of the batch table for one batch is acted upon the profile is complete. I guess this is the general way of explaining it, please comment if I am mistake, coz I am also new to this! LOL.

Converting Text to Image in PHP Formatted by Alignment

During one of my project works I came across a situation like changing the input of TINYMCE editor to image. Can you believe what can be the user’s requirement? :P Basically what the client needed was to change the text to image and text should be in American Typewriter Font with the option of showing text as image formatted by alignment. i.e Left Alignment, Center Alignment or Right Alignment in a white background image. Then I did some research, this is another way of saying I Googled a lot! lol. I came across two scripts, one which converted text to image and another a function to set alignment. So I thought that why not combine both the codes and publish for others, who may need it as well. The compiled code [source language=”php”] im = @imagecreate($W, $H) or die(“Cannot Initialize new GD image stream”); $background_color = imagecolorallocate($this->im, $bgcolor[0], $bgcolor[1], $bgcolor[2]); //RGB color background. $text_color = imagecolorallocate($this->im, $color[0], $color[1], $color[2]); //RGB color text. $this->imagettftextbox($this->im, $fsize,0, $X,$Y, $text_color, $font, $text,800); } /** * This function works to set alignment in image and write image. */ public function imagettftextbox(&$image, $size, $angle, $left, $top, $color, $font, $text, $max_width) { $text_lines = explode(“\n”, $text); // Supports manual line breaks! $lines = array(); $line_widths = array(); $largest_line_height = 0; foreach($text_lines as $block) { $current_line = ”; // Reset current line $align=ALIGN_CENTER; // Setting Alignment $words = explode(’ ‘, $block); // Split the text into an array of single words $first_word = TRUE; $last_width = 0; for($i = 0; $i < count($words); $i++) { $item = $words[$i]; $dimensions = imagettfbbox($size, $angle, $font, $current_line . ($first_word ? '' : ' ') . $item); $line_width = $dimensions[2] - $dimensions[0]; $line_height = $dimensions[1] - $dimensions[7]; if($line_height > $largest_line_height) $largest_line_height = $line_height; if($line_width > $max_width && !$first_word) { $lines[] = $current_line; $line_widths[] = $last_width ? $last_width : $line_width; /*if($i == count($words)) { continue; }*/ $current_line = $item; } else { $current_line .= ($first_word ? ” : ’ ‘) . $item; } if($i == count($words) - 1) { $lines[] = $current_line; $line_widths[] = $line_width; } $last_width = $line_width; $first_word = FALSE; } if($current_line) { $current_line = $item; } } $i = 0; foreach($lines as $line) { if($align == ALIGN_CENTER) { $left_offset = ($max_width - $line_widths[$i]) / 2; } elseif($align == ALIGN_RIGHT) { $left_offset = ($max_width - $line_widths[$i]); } imagettftext($image, $size, $angle, $left + $left_offset, $top + $largest_line_height + ($largest_line_height * $i), $color, $font, $line); $i++; } return $largest_line_height * count($lines); } /** * @name showAsPng * * Function to show text as Png image. * */ public function showAsPng(){ header(“Content-type: image/png”); return imagepng($this->im); } } ?> [/source] Save this file as TextToImage.class.php. And then use this code to call the classes instance. [source language=”php”] makeImageF(“Thank you ! Subesh Pokhrel \n subesh.com.np”,”KORONG.TTF”); $_im->showAsPng(); ?> [/source] Cheers!

Image Resize in Magento & Cache the Resized Image

Handling Products image in Magento is quite easy to do. Magento has deviced as very good class and function to create product’s image by defining widht and height and in addition it caches that image created if you want to get the same sized image next time. But managing other images like category images or other image you may need in your module can be quite troublesome. I went to the core of the function used to cache product’s image and came up with the script which can be used to cache any other images, like the product’s image. Basically the theroy is to create the image of sizes defined in the function parameter and while it is being fetched for the second time checked if the same size image exists or not. If yes then returnt the http url of that image else create new image.Next trick is to save the new size image in the folder with name as widhtXheight (101X65), which can be helpful to check if image exists or not for the given width and height parameters. Below is the code for doing this, you can place this code in your helper, for easy access. [source language=”php”] splitImageValue($imgUrl,”path”); $imgName=$this->splitImageValue($imgUrl,”name”); /** * Path with Directory Seperator */ $imgPath=str_replace(“/”,DS,$imgPath); /** * Absolute full path of Image */ $imgPathFull=Mage::getBaseDir(“media”).DS.$imgPath.DS.$imgName; /** * If Y is not set set it to as X */ $widht=$x; $y?$height=$y:$height=$x; /** * Resize folder is widthXheight */ $resizeFolder=$widht.”X”.$height; /** * Image resized path will then be */ $imageResizedPath=Mage::getBaseDir(“media”).DS.$imgPath.DS.$resizeFolder.DS.$imgName; /** * First check in cache i.e image resized path * If not in cache then create image of the width=X and height = Y */ if (!file_exists($imageResizedPath)&amp;&amp; file_exists($imgPathFull)) : $imageObj = new Varien_Image($imgPathFull); $imageObj->constrainOnly(TRUE); $imageObj->keepAspectRatio(TRUE); $imageObj->resize($widht,$height); $imageObj->save($imageResizedPath); endif; /** * Else image is in cache replace the Image Path with / for http path. */ $imgUrl=str_replace(DS,”/”,$imgPath); /** * Return full http path of the image */ return Mage::getBaseUrl(“media”).$imgUrl.”/”.$resizeFolder.”/”.$imgName; } /** * Splits images Path and Name * * Path=custom/module/images/ * Name=example.jpg * * @param string $imageValue * @param string $attr * @return string */ public function splitImageValue($imageValue,$attr=”name”){ $imArray=explode(“/”,$imageValue); $name=$imArray[count($imArray)-1]; $path=implode(“/”,array_diff($imArray,array($name))); if($attr==”path”){ return $path; } else return $name; } } [/source] And you can access this from anywhere by just this. [source language=”php”] /** *But remember your base image or big image must be in Root/media/custom/module/images/example.jpg */ echo Mage::helper(‘yourmodulehelper’)->getResizedUrl(“custom/module/images/example.jpg”,101,65) /** *By doing this new image will be created in Root/media/custom/module/images/101X65/example.jpg */ [/source] Stay tuned for more on Magento!

Product Import in Magento Alongwith Updating the Attribute’s Options

As you may know or not ! Magento is the fastest growing eCommerce plateform, nowonder because Magento has a lots of flexibility in it. You can feel that too if you are a just a user and as for me as Programmer I just Love it. One of the salient feature that makes Magento a leader in eCommerce software is its ability to Import and Export data to an from the system. Magento gives you a default interface to import or export data, but you will need the specific format of your data.It is easy to customize that as well, but today lets be interested in standard import, but with one small (Yet important) modification. The important modification in the standard code is this code will be able to options to the attribute of Select/Multiselect/Radio/Checkbox input type, while the product is being imported. By default Magento only imports the values of the option, of any attribute, which are already avaliable. But this code can be used to create option at run time if it does not exits and assign to the product, during import. For doing this we need to first set up an Advanced Profile of Export/Import. Go to System–>Import/Export–>Advanced Profile and create new Profile. Then in the Action XML paste this. [source language=”XML”] <!– Path=Path of the file relative to ROOT filename= File name of the XML(MS EXCEL 2003) where import data is saved in Magento’s Format format = XML You can use CSV as well. –> <action type="dataflow/convert_adapter_io" method="load"> <var name="type">file</var> <var name="path">var/import</var> <var name="filename"><![CDATA[products.xml]]></var> <var name="format"><![CDATA[xml]]></var> </action> <!– adapter= Your Model path –> <action type="dataflow/convert_parser_xml_excel" method="parse"> <var name="single_sheet"><![CDATA[]]></var> <var name="fieldnames">true</var> <var name="store"><![CDATA[0]]></var> <var name="number_of_records">1</var> <var name="decimal_separator"><![CDATA[.]]></var> <var name="adapter">yourmodel/import</var> <var name="method">save</var> </action> [/source] The Model defined in the adapter should be like this. You can create a new module for this. [source language=”php”] <?php class Namespace_Module_Model_Import extends Mage_Catalog_Model_Convert_Adapter_Product { /** * Save product (import) * @param array $importData * @throws Mage_Core_Exception * @return bool */ public function saveRow(array $importData) { $product = $this->getProductModel() ->reset(); if (empty($importData[‘store’])) { if (!is_null($this->getBatchParams(‘store’))) { $store = $this->getStoreById($this->getBatchParams(‘store’)); } else { $message = Mage::helper(‘catalog’)->__(‘Skip import row, required field "%s" not defined’, ‘store’); Mage::throwException($message); } } else { $store = $this->getStoreByCode($importData[‘store’]); } if ($store === false) { $message = Mage::helper(‘catalog’)->__(‘Skip import row, store "%s" field not exists’, $importData[‘store’]); Mage::throwException($message); } if (empty($importData[‘sku’])) { $message = Mage::helper(‘catalog’)->__(‘Skip import row, required field "%s" not defined’, ‘sku’); Mage::throwException($message); } $product->setStoreId($store->getId()); $productId = $product->getIdBySku($importData[‘sku’]); if ($productId) { $product->load($productId); } else { $productTypes = $this->getProductTypes(); $productAttributeSets = $this->getProductAttributeSets(); /** * Check product define type */ if (empty($importData[‘type’]) || !isset($productTypes[strtolower($importData[‘type’])])) { $value = isset($importData[‘type’]) ? $importData[‘type’] : ”; $message = Mage::helper(‘catalog’)->__(‘Skip import row, is not valid value "%s" for field "%s"’, $value, ‘type’); Mage::throwException($message); } $product->setTypeId($productTypes[strtolower($importData[‘type’])]); /** * Check product define attribute set */ if (empty($importData[‘attribute_set’]) || !isset($productAttributeSets[$importData[‘attribute_set’]])) { $value = isset($importData[‘attribute_set’]) ? $importData[‘attribute_set’] : ”; $message = Mage::helper(‘catalog’)->__(‘Skip import row, is not valid value "%s" for field "%s"’, $value, ‘attribute_set’); Mage::throwException($message); } $product->setAttributeSetId($productAttributeSets[$importData[‘attribute_set’]]); foreach ($this->_requiredFields as $field) { $attribute = $this->getAttribute($field); if (!isset($importData[$field]) &amp;amp;amp;&amp;amp;amp; $attribute &amp;amp;amp;&amp;amp;amp; $attribute->getIsRequired()) { $message = Mage::helper(‘catalog’)->__(‘Skip import row, required field "%s" for new products not defined’, $field); Mage::throwException($message); } } } $this->setProductTypeInstance($product); if (isset($importData[‘category_ids’])) { $product->setCategoryIds($importData[‘category_ids’]); } foreach ($this->_ignoreFields as $field) { if (isset($importData[$field])) { unset($importData[$field]); } } if ($store->getId() != 0) { $websiteIds = $product->getWebsiteIds(); if (!is_array($websiteIds)) { $websiteIds = array(); } if (!in_array($store->getWebsiteId(), $websiteIds)) { $websiteIds[] = $store->getWebsiteId(); } $product->setWebsiteIds($websiteIds); } if (isset($importData[‘websites’])) { $websiteIds = $product->getWebsiteIds(); if (!is_array($websiteIds)) { $websiteIds = array(); } $websiteCodes = split(‘,’, $importData[‘websites’]); foreach ($websiteCodes as $websiteCode) { try { $website = Mage::app()->getWebsite(trim($websiteCode)); if (!in_array($website->getId(), $websiteIds)) { $websiteIds[] = $website->getId(); } } catch (Exception $e) {} } $product->setWebsiteIds($websiteIds); unset($websiteIds); } foreach ($importData as $field => $value) { if (in_array($field, $this->_inventoryFields)) { continue; } if (in_array($field, $this->_imageFields)) { continue; } $attribute = $this->getAttribute($field); if (!$attribute) { continue; } $isArray = false; $setValue = $value; if ($attribute->getFrontendInput() == ‘multiselect’) { $value = split(self::MULTI_DELIMITER, $value); $isArray = true; $setValue = array(); } if ($value &amp;amp;amp;&amp;amp;amp; $attribute->getBackendType() == ‘decimal’) { $setValue = $this->getNumber($value); } /**CODE MODIFICATION STARTS HERE*/ $optionLabelArray=array(); if ($attribute->usesSource()) { $options = $attribute->getSource()->getAllOptions(false); /** * Update the Source of the attribute when source has no options. */ if(count($options)<1){ if($isArray){ foreach($value as $key=>$subvalue){ if(!in_array($subvalue,$newOptionLabelArray)){ $setValue[]=$this->updateSourceAndReturnId($field,$subvalue); array_push($newOptionLabelArray,$subvalue); } } } else{ if(!in_array($value,$newOptionLabelArray)){ $setValue=$this->updateSourceAndReturnId($field,$value); array_push($newOptionLabelArray,$value); } } } /** * Work on the source when it has options */ else{ /** * This is the case of Multi-Select */ if ($isArray) { foreach ($options as $item) { /** Setting the option’s ID if Label matches with the current value of XML column.*/ if (in_array($item[‘label’], $value)) { $setValue[] = trim($item[‘value’]); array_push($optionLabelArray,$item[‘label’]); /**Adding Reference to worked attribute option**/ } } /** * Checking in the current XML column value if all values were used in the above loop or not * If not used then they are new options value, then new option is created and then assigned. **/ foreach($value as $key=>$subvalue){ if(!in_array($subvalue,$optionLabelArray)){ $setValue[]=$this->updateSourceAndReturnId($field,$subvalue); } } } /**This is the case of single select**/ else { $setValue = null; $newOptionLabelArray=array(); foreach ($options as $item) { if ($item[‘label’] == $value) { $setValue = $item[‘value’]; array_push($optionLabelArray,$item[‘label’]); /**Adding Reference to worked attribute option**/ } } /** * Checking in the current XML column value if all values were used in the above loop or not * If not used then they are new options value, then new option is created and then assigned. **/ if(!in_array($value,$optionLabelArray)){ $setValue=$this->updateSourceAndReturnId($field,$value); } } } } /**CODE MODIFICATION ENDS HERE*/ $product->setData($field, $setValue); } if (!$product->getVisibility()) { $product->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE); } $stockData = array(); $inventoryFields = isset($this->_inventoryFieldsProductTypes[$product->getTypeId()]) ? $this->_inventoryFieldsProductTypes[$product->getTypeId()] : array(); foreach ($inventoryFields as $field) { if (isset($importData[$field])) { if (in_array($field, $this->_toNumber)) { $stockData[$field] = $this->getNumber($importData[$field]); } else { $stockData[$field] = $importData[$field]; } } } $product->setStockData($stockData); $imageData = array(); foreach ($this->_imageFields as $field) { if (!empty($importData[$field]) &amp;amp;amp;&amp;amp;amp; $importData[$field] != ‘no_selection’) { if (!isset($imageData[$importData[$field]])) { $imageData[$importData[$field]] = array(); } $imageData[$importData[$field]][] = $field; } } foreach ($imageData as $file => $fields) { try { $product->addImageToMediaGallery(Mage::getBaseDir(‘media’) . DS . ‘import’ . $file, $fields); } catch (Exception $e) {} } $product->setIsMassupdate(true); $product->setExcludeUrlRewrite(true); $product->save(); return true; } /** * Updates the source of the attribute by the current new value in the XML column, and returns * the id of the newly created option. * * @param string $attribute_code * @param string $newOption * @return int|string New Option Id */ public function updateSourceAndReturnId($attribute_code,$newOption){ $attribute_model = Mage::getModel(‘eav/entity_attribute’); $attribute_options_model= Mage::getModel(‘eav/entity_attribute_source_table’) ; $attribute_code = $attribute_model->getIdByCode(‘catalog_product’, $attribute_code); $attribute = $attribute_model->load($attribute_code); $attribute_table = $attribute_options_model->setAttribute($attribute); try{ $value[‘option’] = array(trim($newOption),trim($newOption)); $result = array(‘value’ => $value); $attribute->setData(‘option’,$result); $attribute->save(); } catch(Exception $e){} $options = $attribute_options_model->getAllOptions(false); foreach($options as $option) { if ($option[‘label’] == $newOption) { return $option[‘value’]; } } return ""; } } ?> [/source] Please note the /**CODE MODIFICATION ENDS HERE*/ block. Most of the description is on the code. I got it working, feel free to ask if you got any problem. I am also working on importing custom option. I’ll soon make a post in it as well. Download Source[Updated] Here’s the sample import sheet with request from the reader Sample Sheet

Adding Related Product and Other Links to Product in Magento

Here is a simple way of adding product link such as Related, Upsell and Crosssell Link to a product in Magento. I just got the way of doing this and thought to share! So kind of me :) [source language=”php”] /** First Create Link Array of following type **/ $linkArray=array(‘product_id’=>array(‘position’=>’’)); /** Then set the Link Data **/ /** For Upsell Link**/ $product->setUpSellLinkData($linkArray); /** For Crosssell Link**/ $product->setCrossSellLinkData($linkArray); /** For Crosssell Link**/ $product->setRelatedLinkData($linkArray); $product->save(); [/source] Hope this helps.

Working With AJAX in Magento

Ajax in Magento can be pretty troublesome.Because you will need to take controllers and layout into account.And I almost used up a whole day trying to make ajax work. Here are some of the steps I’d like to share so that you will not waste lots of your time, before making this work :D. [UPDATE]
Get Ajaxify Extension from Magento Connect to work with AJAX on Magento
Let’s first know in Magento terms what we need. Controller: The url on which Ajax will work on, or the request URL. You will have to set up the controller with its frontend router set in config.xml and its corresponding controller class. Layout: Layout to handle the requested URL and return HTML if required. Block: The block to call through layout for the above controller. Now lets be descriptive. If you want to show a loader while request is being processed just add the following whereever you like in the phtml page.First fetch the Javascript. [source language=”javascript”] <script src="<?php echo $this->getJsUrl() ?>mage/adminhtml/loader.js" type="text/javascript"></script> [/source] Then echo the loader which pops up. This loader will be similar to that of the admin. [source language=”html”] <div id="loadingmask" style="display: none;"> <div class="loader" id="loading-mask-loader"><img src="<?php echo str_replace("index.php/","",$this->getUrl()) ?>skin/adminhtml/default/default/images/ajax-loader-tr.gif" alt="<?php echo $this->__(‘Loading…’) ?>"/><?php echo $this->__(‘Loading…’) ?></div> <div id="loading-mask"></div> </div> [/source] Now to Call Ajax, use the following lines [source language=”javascript”] /*Please note that the URL is created in reloadurl. Also see that the response text will be echoed in div with id=output-div*/ var reloadurl = ‘<?php echo $this->getUrl(‘router/controller/action’) ?>’; Element.show(‘loadingmask’); new Ajax.Request(reloadurl, { method: ‘post’, parameters: "Params_Here", onComplete: function(transport) { Element.hide(‘loadingmask’); $(‘output-div’).innerHTML = ""; $(‘output-div’).innerHTML = transport.responseText; } }); [/source] After the Ajax Request is made it goes to your controller’s action, which in turn sees to your layout as follows: [source language=”php”] class Namespace_module_frontendController extends Mage_Core_Controller_Front_Action { public function actionAction(){ $this->loadLayout()->renderLayout(); } } [/source] And here is the main part in layout where I spent most of my time in. Since in layout we will have to define reference where the html will echo (Most of the times), i got stuck here, because i need to echo the output on the div with id output-div not in any reference.And the trick is to name the layout as root and output as html. Like the following: [source language=”XML”] <module_controller_action> <block type="module/block" name="root" output="toHtml" template="module/template.phtml"/> </module_controller_action> [/source] You are done now! What ever you write or echo in phtml file you will see populated in the DIV. Now you can treat block as normally as you do before. Happy Coding!! [UPDATE]
Get Ajaxify Extension from Magento Connect to work with AJAX on Magento

How to Get Query as a String in Magento?

Magento as you might know or not! has really a very PIA (Pain in the A**) type of methods to create SQL, execute and fetch! There are two ways of getting SQL from the collection of Magento. Here are the two ways. 1. Only Echoing Query String. For just echoing the query string you must call printlogquery(), method the the collection. Like. [source language=”php”] /** If $collection is your collection**/ $collection->printlogquery(true); /** Don’t forget to write true in param**/ [/source] But by this method you cannot assign the query you get echoed to some variable. To get the query string here is what you do. 2. Getting the query String [source language=”php”] $query=$collection->getSelectSql(true); echo $query; [/source] You can then use this $query to concat with more query, in some cases you desperately need this. Stay Tuned!

Wonder if This Is the Reason Behind the Name “Gmail”!

I was working in Magento trying to print PDF of the shipping information, with out changing the locale of the site and it was set to “Dutch”. And I came up with this word “gemailed”, I pronounced it as “G-Mailed”. Then suddenly my mind clicked with a connection G-Mailed and Gmail. So i thought it would be a good (if not better) discovery and share on my blog. Here’s the screen shot of the translation. This is not any official thing or anything, just a mere coincidence, but really a thing to think about for once any may be crack a joke or say it to your friends.