Redirect In Grid To Admin URL

As part of the creation of a grid that contained sales orders, it was necessary to redirect the click on a grid row to the sales order view for the id of the row in question.

To accomplish this the following code was used in the Grid.php file:

public function getRowUrl($row) {
    return ($this->getUrl('adminhtml/sales_order/view', array('order_id' => $row->getId())));

Note that the adminhtml in the return line above was replaced with the magic key string for the administrator area.

Frontend – Adding Weights To Products

During the creation of a food and drink vendors site, it became apparent that some products needed to be displayed with a weight in grammes or kilogrammes, but yet others were measured in volume so litres were the necessary values to display to the potential customers.

I am sure that there are numerous ways of doing this, however, let us consider 2 based on 2 different scenarios:
1) The default weight attribute is not used for calculating delivery costs and therefore can be used with as we see fit.
2) Weight is used to calculate delivery and a duplication value will be established for the benefit of visitors.

So firstly we consider:
Situation 1 – Weight attribute is not used for calculating delivery costs
Log into the Magento Administrator for the site in question. Catalog -> Attribute -> Manage Attributes.
Add New Attribute.

Admin -> Catalog -> Attributes -> Manage Attributes -> Add New Attribute -> Properties

Note that it is especially important to define the ‘Used in Product Listing’ option as Yes. This will allow us to make changes to the theme page to output this value.

Admin -> Catalog -> Attributes -> Manage Attributes -> Add New Attribute -> Manage Label / Options

This has created a measurement attribute that can be assigned to a product, and from that attribute we have defined 4 possible values to select from.

We need to assign this attribute to the particular Attribute Sets which have been defined in the Magento store backend, and are to be used for products that will display their weight on the frontend.

Catalog -> Attribute -> Manage Attribute Sets. Select the appropriate Attribute Set, in this example we will use Default.

Initially the new Measurement Attribute will appear in the Unassigned Attributes area and this simply needs to be dragged into the Groups section to the required point in the list of existing Attributes. Here we have added it below weight in the General section:

Admin -> Catalog -> Attributes -> Manage Attribute Set -> Default -> Groups

Now that the Attribute has been added to the Attribute Set, it only remains to define the Attribute in a product that belongs to the Attribute Set which has had the Attribute added.

Admin -> Catalog -> Manage Products -> {product} -> {general}

This has allowed for a measurement to be associated. However, this value will not be shown as the code is not aware of the existence of this Attribute. We will need to add this.

In the filesystem, open /app/design/frontend/default/{theme}/template/catalog/product/list.phtml. Note that if this file does not exist in the theme that is being used, copy this file from /app/design/frontend/default/base/template/catalog/product/list.phtml. Once this file has been copied, it can then be modified. Please note that the base file should never be altered. Also, be aware that numerous files will need to be altered to include this change, list.phtml has been selected as it shows a number of products quickly and simply.

In this file, you can retrieve the value of the {measurement} Attribute with the code:

    // Note that in this code sample {measurement} should be replaced with your Attribute name
    echo ($_product->getAttributeText('{measurement}'));

This can be paired with the weight Attribute that is part of the default installation, as shown in the following code sample:

    // Note that in this code sample {measurement} should be replaced with your Attribute name
    echo ('<div class="weight">' . $this->__('Weight') . ': ' . $_product->getWeight() . $_product->getAttributeText('{measurement}') . '</div>');

Note, it is possible to use $_product->getData(‘measurement’) to recover the numerical value associated this will retrieve a numerical value which is associated to the option and not the label that is associated to the Attribute.

Situation 2 – Weight is used to calculate delivery
With weight being required for calculating delivery costs we can simply create a new Attribute (please see the steps above for more information on achieving this), labelled display_weight or something similar.

Add the new Attirbute to the Attribute Sets associated to the products. In each of the appropriate products this attribute will need to be given a value.

Apply the steps above for creating the measurement Attribute. Once these have been created and assigned values in the products the only thing that remains to be changed is that in the front end files that display products will need to include code similar to the following:

    // Note that in this code sample {display_weight} and {measurement} should be replaced with your Attribute names
    echo ('<div class="weight">' . $this->__('Weight') . ': ' . $_product->getData('{display_weight}') . $_product->getAttributeText('{measurement}') . '</div>');

Additional information:
The weight Attribute may not show, or will show as a 0.00 value. This would probably be due to the fact that the Used in Product Listing, Attribute setting is set to No. Go to Admin -> Catalog -> Attributes -> Manage Attributes. Select weight and change this setting in the Properties tab.

If it is desired to interpret each of the various outputs for measurement it is possible to obtain the values in the following way:
Direct Database Access:
It is possible to either get the value directly from the database. This can be achieved with a couple of steps.
a) Get the attribute_id: SELECT * FROM `eav_attribute` WHERE attribute_code = ‘measurement’. Record the a attribute_id.
b) Use this attribute_id to get the option_id: SELECT * FROM `eav_attribute_option` WHERE attribute_id = ‘162’. Record the option_id values.
It is possible to do this in alternative ways, but this way helps more easily see the relationship between the tables in the database.

File Access:
Alternatively, it would be possible to set products to the various Attribute options and add the folioing to the top of the /app/design/frontend/default/{theme}/template/catalog/product/list.phtml file.

    // Note that in this code sample {display_weight} and {measurement} should be replaced with your Attribute names
    echo ('<br />measurement value: ' . $_product->getData('{measurement}'));


    // Note that in this code sample {display_weight} and {measurement} should be replaced with your Attribute names
    echo ('<br />measurement value: ' . $_product->getAttributeText('{measurement}'));

Then view each of the products that have had the measurement Attribute set, and record the output shown on the product page.

It is now possible to display each of the various measurement types independently.

Translating Magento – Template

One way of translating in Magento is by using the translations available in a theme. However this needs to be activated in the Administration area.

Log in to the Magento Admin -> Configuration -> Design -> Design -> Themes -> Translations. In this text field submit the name of the theme that is to be used for translations. Note that this will need to have the corresponding translate.csv file in the locale directly of that theme.

The translate.csv file will need to be located in the theme specified (Administrator configuration area):
/app/design/frontend/default/{theme}/locale/{language_sortcode}/translate.csv or /app/design/adminhtml/default/{theme}/locale/{language_sortcode}/translate.csv

If this file does not exist, simply create it.

If it does not contain the translation that is required, enter the the translation string enclosed in double quotes followed by the translation string in double quotes, separated by a comma. For example:
“{string for translation}”, “{translated string}”

This will first pick up any local locale files that are being used for translation, for example: /app/locale/{language_sortcode}/{Namespace}_{Module}.csv. To override this it is necessary to implement a variation in format of the “{string for translation}” string in the .csv file to the following: “{{Namespace}_{Module}::string for translation}”, “{translated string}”. This may be better understood with an example. Consider that in the .phtml file it is desirable to introduce a string for a value defined as ‘fluff’. So in the .phtml file we place the following in the file:

<?php echo ($this->__('fluff')); ?>

Without any intervention the output would be seen as the string ‘fluff’, but this can be used for translation by inserting the string into either the frontend or administrator .csv file, depending on the file location that the fluff string has been entered. If it is assumed that the fluff string has been entered into the administrator location then it is possible to edit, or create, the file /app/design/frontend/default/{theme}/locale/{language_sortcode}/translate.csv. Inside this we put in the code:
Now when viewing the page that had the echo ($this->__(‘fluff’)); code entered the uppercase version of the string should be seen. However, if this string was part of a code defined in Mage_Customer, then in the translate.csv file the entry would look more like: “Mage_Customer::fluff”,”FLUFF”

In the php/phtml file that you want translation to occur, the required translatable string is created with the syntax: $this->__(‘{string for translation}’)

One other area of note is that a language short code will be required, for British English this will be en_GB and American English is en_US.

Some possible others are (not verified):
English, US (en_US)
German, Germany (de_DE)
Chinese, PRC (zh_CN)
Chinese, Taiwan (zh_TW)
Czech, Czech Republic (cs_CZ)
Dutch, Belgium (nl_BE)
Dutch, Netherlands (nl_NL)
English, Australia (en_AU)
English, Britain (en_GB)
English, Canada (en_CA)
English, New Zealand (en_NZ)
English, Singapore(en_SG)
French, Belgium (fr_BE)
French, Canada (fr_CA)
French, France (fr_FR)
French, Switzerland (fr_CH)
German, Austria (de_AT)
German, Liechtenstein (de_LI)
German, Switzerland (de_CH)
Italian, Italy (it_IT)
Italian, Switzerland (it_CH)
Japanese (ja_JP)
Korean (ko_KR)
Polish (pl_PL)
Russian (ru_RU)
Spanish (es_ES)
Arabic, Egypt (ar_EG)
Arabic, Israel (ar_IL)
Bulgarian, Bulgaria (bg_BG) 2.3
Catalan, Spain (ca_ES) 2.3
Croatian, Croatia (hr_HR) 2.3
Danish, Denmark(da_DK) 2.3
English, India (en_IN) 2.3
English, Ireland (en_IE) 2.3
English, Zimbabwe (en_ZA) 2.3
Finnish, Finland (fi_FI) 2.3
Greek, Greece (el_GR) 2.3
Hebrew, Israel (iw_IL)* 2.3
Hindi, India (hi_IN) 2.3
Hungarian, Hungary (hu_HU) 2.3
Indonesian, Indonesia (in_ID)* 2.3
Latvian, Latvia (lv_LV) 2.3
Lithuanian, Lithuania (lt_LT) 2.3
Norwegian-Bokmol, Norway(nb_NO) 2.3
Portuguese, Brazil (pt_BR) 2.3
Portuguese, Portugal (pt_PT) 2.3
Romanian, Romania (ro_RO) 2.3
Serbian (sr_RS) 2.3
Slovak, Slovakia (sk_SK) 2.3
Slovenian, Slovenia (sl_SI) 2.3
Spanish, US (es_US) 2.3
Swedish, Sweden (sv_SE) 2.3
Tagalog, Philippines (tl_PH) 2.3
Thai, Thailand (th_TH) 2.3
Turkish, Turkey (tr_TR) 2.3
Ukrainian, Ukraine (uk_UA) 2.3
Vietnamese, Vietnam (vi_VN) 2.3


Creating Custom Customer Fields

Custom customer fields can be a little daunting to implement, due to the fact that each customer is a collection of integrated sections. However if this is a step that needs to be taken, well here is the process that I have followed, helped by many online tutorials.

Administrator View

Administrator -> Customers -> Manage Customers

Select a customer from the grid.

On the left hand side there will be a section Customer Information, select Addresses. The Edit Customer’s Address will not be viewing the new customer fields and this will be visible by making entries into customer_eav_attribute for each of the custom fields to be inserted.

Example DB entry:
INSERT INTO ``.`customer_eav_attribute` (`attribute_id`, `is_visible`, `input_filter`, `multiline_count`, `validate_rules`, `is_system`, `sort_order`, `data_model`) VALUES (‘‘, ‘1’, NULL, ‘1’, NULL, ‘0’, ‘0’, NULL). The 2 values attribute_id () and is_visible (1) will be set as required, and the other values should be default.

Once this entry has been made it should be possible to see the values in the form. However it will probably be necessary to change the DB sort order for the new custom fields to position them on the form.

Add custom fields to magento customer address

Modifying Frontend Customer Account List Options

When it comes to customer options, sometimes it is good to give them what they want, worth considering however is limiting the list to what you want them to want, and what is actually available.

By default a customer is likely to get something like the following options:

Customer Account Option Links

This is often far from desirable, and in those situations it is good to remove those choices that simply do not make sense for your installation.

One way of achieving this is with an extension.

Here are the instructional guidelines.


<?xml version="1.0" encoding="UTF-8"?>


<?xml version="1.0" encoding="UTF-8"?>



class {Namespace}_{Module}_Block_Account_Navigation extends Mage_Customer_Block_Account_Navigation {

    public function removeLinkByName($name) {

This is pretty much it, and sets up the environment for one last change.

In the /app/design/frontend/default/{theme/default}/layout/local.xml file, add immediately before the closing tag:

               Customer Profile page
        <reference name="customer_account_navigation">
            <action method="removeLinkByName"><name>billing_agreements</name></action>

This will remove the Billing Agreements option. However, add from the following to remove other options that are not needed:

            <action method="removeLinkByName"><name>account</name></action>
            <action method="removeLinkByName"><name>account_edit</name></action>
            <action method="removeLinkByName"><name>address_book</name></action>
            <action method="removeLinkByName"><name>orders</name></action>
            <action method="removeLinkByName"><name>billing_agreements</name></action>            
            <action method="removeLinkByName"><name>recurring_profiles</name></action>
            <action method="removeLinkByName"><name>reviews</name></action>
            <action method="removeLinkByName"><name>tags</name></action>
            <action method="removeLinkByName"><name>downloadable_products</name></action>
            <action method="removeLinkByName"><name>wishlist</name></action>
            <action method="removeLinkByName"><name>newsletter</name></action>

Recurring Profiles =

<action method="removeLinkByName"><name>recurring_profiles</name></action>

My Product Reviews =

<action method="removeLinkByName"><name>reviews</name></action>

My Tags =

<action method="removeLinkByName"><name>tags</name></action>

My Applications =

<action method="removeLinkByName"><name>OAuth Customer Tokens</name></action>

My Downloadable Products =

<action method="removeLinkByName"><name>downloadable_products</name></action>

Remove Billing Agreements and Recurring Profiles from Dashboard

Changing The Adminhtml Template Location

This solution came courtesy of the Magento forums, but is so simple, it deserves repetion here:

Create a folder in the /app/design/adminhtml/default/ directory, this will be the name of the new admin theme.

Then modify the local.xml file located in the /app/etc/ directory by adding the following code:

            <!-- default admin design package and theme -->

Note that for simplicity, it may be ideal to place this code immediately before the closing tag at the end of the file.


Frontend – Adding a Static Block Multilingual Footer

The footer in a Magento site can be specified in a few ways. The most popular way that I have determined is from a combination of static blocks, and layout files.

Let’s consider the typical default layout in this here example. If you cast your eyes to the code below.


    <default translate="label" module="page">
        <label>All Pages</label>
        <block type="page/html" name="root" output="toHtml" template="page/3columns.phtml">
            <block type="page/html_footer" name="footer" as="footer" template="page/html/footer.phtml">
                <block type="page/html_wrapper" name="bottom.container" as="bottomContainer" translate="label">
                    <label>Page Footer</label>
                    <action method="setElementClass"><value>bottom-container</value></action>
                <block type="page/switch" name="store_switcher" as="store_switcher" template="page/switch/stores.phtml"/>
                <block type="page/template_links" name="footer_links" as="footer_links" template="page/template/links.phtml"/>

        <block type="core/profiler" output="toHtml" name="core_profiler"/>

A delightful and well meaning piece of xml, I am sure that you will agree. For more information regarding the intricacies of layout files, then you may want to read a more detailed definition at the layouts page.

However, we want to add something specific, that we need to make in the administrator area so that the client can modify that content. To achieve this we create some static blocks. Administrator -> CMS -> Static Blocks. Then create the block that needs to be created. In the case of requiring multiple languages of the same block, create multiple blocks but give them all the same identifier value, but make sure to associate each static block with the Store View dropdown specified in the static block definition area.

Return to the page.xml file defined above and modify code similar to the following:

             <block type="page/html_footer" name="footer" as="footer" template="page/html/footer.phtml">
                <block type="page/html_wrapper" name="bottom.container" as="bottomContainer" translate="label">
                <block type="cms/block" name="cms.footer_links" as="<static_block_ identifier>">
                    <action method="setBlockId"><block_id><static_block_ identifier></block_id></action>
                    <label>Page Footer</label>
                    <action method="setElementClass"><value>bottom-container</value></action>
                <block type="page/switch" name="store_switcher" as="store_switcher" template="page/switch/stores.phtml"/>
                <block type="page/template_links" name="footer_links" as="footer_links" template="page/template/links.phtml"/>

Please replace shown in the code to the identifier that was specified in the block/s created in the Administrator -> CMS -> Static Blocks area.

Note that you do not need to worry about the appending anything regarding language changes of the site as this will all be handled

I attempted to add a new static block in the administrator area of the Magento site, giving it the reference name of “footer”. However nothing would display. On further investigation it was seen that the local.xml file had deactivated this from functioning with the following code:


               	Default Footer 
        <reference name="footer">
            <action method="unsetChild">
            <block type="cms/block" name="footer_block">
                <action method="setBlockId">

This was an early trial to see what would happen, and not particularly relevant, but I thought to add it as a mater of completeness. 🙂


Database – Importing Customers From Another DB

A bespoke system had been created for a client, and due to the demands on the single developer that had produced the solution, I recommended a more robust and well known solution, in this case Magento.

It was necessary to recreate all of the the existing customers in the Magento DB, so an understanding of how the database hangs together was required.

When a typical customer creates an account 2 tables appear to be updated in the customer tables, these are:

Typical values that can be seen will be something like:
entity_id: 1
entity_type_id: 1
attribute_set_id: 0
website_id: 1
group_id: 1
increment_id: NULL
store_id: 1
is_active: 1
disable_auto_group_change: 0

value_id: 1
entity_type_id: 1
attribute_id: 5
entity_id: 1

value_id: 2
entity_type_id: 1
attribute_id: 7
entity_id: 1

value_id: 3
entity_type_id: 1
attribute_id: 12
entity_id: 1

value_id: 5
entity_type_id: 1
attribute_id: 3
entity_id: 1
value: ‘Default Store View’

However, how do we enter the password hash for the existing customer, as the value can be seen to consist of value similar to: c83bb10f066c20a2beb7c120cec5d003:VX
This value is defined by the MD5 encryption combined with a salt value. However, Magento will happily work with the MD5 value as a start point and then wen the customer updates the password then it will add the salt to the string for enhanced security.

Hope that helps.

Frontend – Modifying Bundled Products

Consider a product that is made up of other catalog items. This product needs to be a box of those other items and not allow the user to modify this list. It is a simple case that this is what they get and that is that. This was one of the issues I needed to resolve, and this is how I got around it.

1) Create a Bundle Product.

Admin -> Manage Product -> Add Product -> Create Product Settings

Admin -> Manage Product -> Add Product -> Create Product Settings -> Product Type -> Bundle Product

In the situation that needed to be resolved the price was set to a fixed value, and this was defined instead of the dynamic alternative.

Admin -> Manage Product -> Add Product -> Create Product Settings -> Product Type -> Bundle Product -> Price

The key area to adding the products that this master product will be made up of is defined in the the bottom option on the left hand side; Bundle Items.

Admin -> Manage Product -> Add Product -> Create Product Settings -> Product Type -> Bundle Product -> Bundle Items

In the Bundle Option header click the Add New Option button, and this will display an additional set of options.

Admin -> Manage Product -> Add Product -> Create Product Settings -> Product Type -> Bundle Product -> Bundle Items -> Add New Option

As the intention is to remove the option for the front end visitor to be able to select the products that this bundle will be comprised of, the Checkbox Input Type has been selected, although this is a somewhat random, it will define the Template file that we need to modify later. To avoid any issues with required values the Is Required selection has been set to no. The Add Selection button has then been clicked.

Admin -> Manage Product -> Add Product -> Create Product Settings -> Product Type -> Bundle Product -> Bundle Items -> Add New Option -> Add Selection

Click Search to display a list of products available.

Select the items with the checkbox on the same line as the product and add a quantity in the relevant box.

Click the Add Selected Product(s) to Option button.

Admin -> Manage Product -> Add Product -> Create Product Settings -> Product Type -> Bundle Product -> Bundle Items -> Add New Option -> Add Selection -> Add Selected Product(s) to Option


This creates a basic Bundled product. All well and good and perhaps nothing of note there. The options above are obviously only a suggestion and therefore setting the values appropriate to the individuals needs is required.

Modifying the Template file to limit and delight is the next intended objective.

As the checkbox option was defined in the creation of the Bundle Product, this will will be the Template file that will need to be altered.

Copy the file: frontend/default/base/template/bundle/catalog/product/view/type/bundle/option/checkbox.phtml into your own theme directory.

This is where we used the following code:

<?php /* @var $this Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Checkbox */ ?>
<?php $_option = $this->getOption() ?>
<?php $_selections = $_option->getSelections() ?>
<dt><label<?php if ($_option->getRequired()) echo ' class="required"' ?>><?php echo $this->htmlEscape($_option->getTitle()) ?><?php if ($_option->getRequired()) echo '<em>*</em>' ?></label></dt>
<dd<?php if ($_option->decoratedIsLast){?> class="last"<?php }?>>
    <div class="input-box">
    <?php if (count($_selections) == 1 && $_option->getRequired()): ?>
        <?php echo $this->getSelectionQtyTitlePrice($_selections[0]) ?>
        <input type="hidden" name="bundle_option[<?php echo $_option->getId() ?>]" value="<?php echo $_selections[0]->getSelectionId() ?>"/>
    <?php else:?>
    <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/jquery.easing-1.3.pack.js') ?>"></script>
    <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/jquery.mousewheel-3.0.4.pack.js') ?>"></script>
    <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/jquery.fancybox-1.3.4.pack.js') ?>"></script>
    <script src="//"></script>

    <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/bundledbox.js') ?>"></script>
    <link rel="stylesheet" type="text/css" href="<?php echo $this->getSkinUrl('css/jquery.fancybox-1.3.4.css') ?>" media="screen">
    <link rel="stylesheet" href="">

        <?php foreach($_selections as $_selection): ?>
        <a class="bundledbox-product" href="#product-<?php echo ($_selection->getId()); ?>" title="<?php echo ($_selection->getName()); ?>"><?php echo ($_selection->getName()); ?></a><?php var_dump ($_selection); ?>
        <div style="display:none">
            <div id="product-<?php echo ($_selection->getId()); ?>">
                <div class="tabs">
                    <li><a href="#<?php echo ($_selection->getId()); ?>-tab-1"><?php echo ($this->__('Description')); ?></a></li>
                    <li><a href="#<?php echo ($_selection->getId()); ?>-tab-2"><?php echo ($this->__('Information')); ?></a></li>
                    <li><a href="#<?php echo ($_selection->getId()); ?>-tab-3"><?php echo ($this->__('Storage')); ?></a></li>
                  <div id="<?php echo ($_selection->getId()); ?>-tab-1">
                    <p><?php echo ($_selection->load($_selection->getId())->getShortDescription()); ?></p>
                  <div id="<?php echo ($_selection->getId()); ?>-tab-2">
                    <?php if ( $_selection->getData()['manufacturer_value']) { echo ($this->__('Manufacturer') . ': ' . $_selection->getData()['manufacturer_value'] . '<br />' ); } ?>
                    <?php if ($_selection->getData()['organic_value']) { echo ($this->__('Organic') . ': ' . $_selection->getData()['organic_value'] . '<br />' ); } ?>
                    <?php if ($_selection->getData()['vegetarian_value']) { echo ($this->__('Vegetarian') . ': ' . $_selection->getData()['vegetarian_value'] . '<br />' ); } ?>
                    <?php if ($_selection->getData()['vegan_value']) { echo ($this->__('Vegan') . ': ' . $_selection->getData()['vegan_value'] . '<br />' ); } ?>
                    <?php if ($_selection->getData()['natural_value']) { echo ($this->__('Natural') . ': ' . $_selection->getData()['natural_value'] . '<br />' ); } ?>
                    <?php if ($_selection->getData()['sin_tacc_value']) { echo ($this->__('Sin TACC') . ': ' . $_selection->getData()['sin_tacc_value'] . '<br />' ); } ?>
                  <div id="<?php echo ($_selection->getId()); ?>-tab-3">
                    <p><?php if ($_selection->getData()['storage']) { echo ($_selection->getData()['storage']); } ?></p>
        <br />
        <?php endforeach; ?>
        <div id="bundle-option-<?php echo $_option->getId() ?>-container"></div>
    <?php endif; ?>

There are possibly some confusing aspects of this and while this is not a primer on javascript and jQueryUI the new lines are based on allowing users to click on the product options to get more information on the individual options that the Bundle Product is comprised.

Creating Administrator Reports

While Magento offers a number of reports that cover many of the operational business needs, people always seem to need their own sort of data, in a format that makes sense to them. For this reason it is possible to create custom reports for Administrators. The basics of such reporting is covered here.

The following example requires the creation of the following files:

Start by creating the directory tree and then create the file config.xml. Populate with the following:

<?xml version="1.0"?>