Category Archives: Uncategorized

Transactional Emails Basics

In the process of wanting to add a new dynamic value, based on a customer account, into the invoice email that is sent out when a customer buys something from the store, it became evident that understanding of transactional emails would be needed.

To view Transactional Emails it is possible to to into the Magento backend System -> Transactional Emails. Within this section it is possible to create a new template based on the templates defined in the file structure.

Having defined a template in the previous section, it is then possible to associate that template to an action. This is done in the Magento backend System -> Configuration -> Sales (Sales Emails).

Admin Controllers

In the config.xml file of the module extension, define the following:

   <admin>
        <routers>
            <adminhtml>
                <args>
                    <modules>
                        <{Namespace}_{Module} before="Mage_Adminhtml">{Namespace}_{Module}</{Namespace}_{Module}>
                    </modules>
                </args>
            </adminhtml>
        </routers>
    </admin>

In the controller file, example indexController.php, define the following:
class {Namespace}_{Module}_Adminhtml_IndexController extends Mage_Adminhtml_Controller_Action {
public function indexAction() {
/* Debug code */
//Zend_Debug::dump($this->getLayout()->getUpdate()->getHandles()); die ();

$this->loadLayout();
$this->renderLayout();
}
}

Note: This will not allow the testing of the page in the back end as this requires the use of a nonce key that is added by Magento when yo link to a URL defined in the core or in an extension. So do not assume that {base_url}{admin}{frontname}{controller}{action} will not grant access to a page. It is possible however to obtain a url with the command: Mage::helper(“adminhtml”)->getUrl(‘{frontname}/{action}’)

Email Templates

When dealing with the default emails that are sent out by the system, such as int he case of new registration, order confirmation and the like the code for these are placed in the /app/locale//template/.. folders.

One thing to consider in the deciphering of these template files is that it will be possible to see entries such as: {{layout handle=”sales_email_order_items” order=$order}} in the file, and it is possible to wonder what on earth such notation relates to.

The sales_email_order_items part of this refers to the file /app/design/frontend/base/default/layout/sales.xml. Here there is the following section:



defaultsales/order_email_items_order_default
groupedsales/order_email_items_order_grouped

colspan=”3″ align=”right” style=”padding:3px 9px”
align=”right” style=”padding:3px 9px”

1





The above excerpt shows defaultsales/order_email_items_order_default, and this is referencing /app/design/frontend//default/template/email/order/items/order/default.phtml

It is then possible to place an override file in your frontend template to alter the values in this file.

XAMPP – MySQL Corruption

Having used XAMPP for a time on a Mac, I have encountered a few situations in which my databases have become corrupted. I cannot say why, and if I knew I would definitely attempt to avoid this, as it often sets me back a reasonable amount of time.

Whilst this is not an instructional guide on recovering your data, this is a way to simply try and get your environment working again once such a situation has occurred as I have been left unable to start the MySQL server on my local machine and resorted to all sorts of re-installations of software in an attempt to get my XAMPP environment operational again.

So if faced with an inability to start the MySQL Database service, consider implementing the following:

1. Look to /Applications/XAMPP/xamppfiles/var/mysql/ directory and there should b a file that ends with .local.err. Open this file and this will provide some possible insight into what may be going on. Often in my situations I would see something like:

The exact text will differ, but this may provide with some assistance.

2. Then try using: innodb_force_recovery = 1 after the [mysqld] line in the /Applications/XAMPP/xamppfiles/etc/my.cnf file. This may require use of sudo when modifying this file; for example: sudo vi /Applications/XAMPP/xamppfiles/etc/my.cnf and then enter the password. Save the file; if using vi this is achieved with :w command (more information here: http://www.howtogeek.com/102468/a-beginners-guide-to-editing-text-files-with-vi/).

3. Retry starting the XAMPP MySQL Database server. Check the output of the .local.err file to see what information has been introduced to the end of this file.

4. Database repair is possible with the use of the command: sudo /Applications/XAMPP/xamppfiles/bin/mysqlcheck -c –all-databases. This will go through all the DB instances and attempt to repair them.

5. Sometimes this will not work however, and you just need to cut and run. If that is the situation, then it is possible to ensure that the MySQL Database service is disabled and then manually delete the database directories. When you then restart the MySQL Database service these will not longer be visible in the list.

6. Restore the database from a backup, and make any modifications that may be necessary if it is a remote backup, to ensure that the local parameters are set.

Hopefully that will be enough to get the system functional once again.

Checkout – Making Required Fields Un-Required or Vice Versa

There are times that you simply do not need people to submit information, and while Magento has its own idea on that, the mavericks among you simply need to go your own way.

This is a 2 step process:
1. Open up the relevant .phtml files, and removed the offending text that defines these fields as required. Primarily, the two files to consider are /app/design/frontend/defaul/{theme}/template/checkout/onepage/billing.phtml and /app/design/frontend/defaul/{theme}/template/checkout/onepage/shipping.phtml

In these files you are likely to see the following, or similar syntax:

<label for="shipping:telephone" class="required"><em>*</em><?php echo $this->__('Telephone') ?></label>

The removal of the text class=”required” and * will firstly be required. Apply those changes to the file for all of the fields that are required and that are no longer required to have such status.

This is great, but submitting the form will still produce an alert and not allow you to continue. A somewhat frustrating turn of events. The next thing is to turn to the database.

2. Find the eav_attribute table and find the field for the value that you are looking to modify. You will find a column labelled ‘is_required’. Change the value for the field of interest from 1 to 0. If it is not set to 1, then the field will probably not have generated the alert and error mentioned previously.

That is it. You should now have a working form. Yippee.

Note, that to make a field required you would want to follow the steps above but do the opposite:
1. Convert the html from

<label for="shipping:telephone"><?php echo $this->__('Telephone') ?></label>

to

<label for="shipping:telephone" class="required"><em>*</em><?php echo $this->__('Telephone') ?></label>

2. Change the database entry for the is_required column from 0 to 1 for the row related to the value in question.

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:

<?php
    // 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:

<?php
    // 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:

<?php
    // 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.

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

or

<?php
    // 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:
“fluff”,”FLUFF”.
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

Resources:

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.

Resources:
Add custom fields to magento customer address

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.

/app/design/frontend/base/default/layout/page.xml:

    <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>
                <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>
            .
            .
            .
        </block>

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

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>
                </block>
                    <label>Page Footer</label>
                    <action method="setElementClass"><value>bottom-container</value></action>
                </block>
                <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>

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:

/app/design/frontend/default//layout/local.xml

        <!-- 
               	Default Footer 
        -->
        <reference name="footer">
            <action method="unsetChild">
                <alias>cms_footer_links</alias>
            </action>
            <block type="cms/block" name="footer_block">
                <action method="setBlockId">
                    <block_id>footer_block</block_id>
                </action>
            </block>
        </reference>

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. 🙂

Resources:
http://magento.stackexchange.com/questions/617/how-to-create-multilingual-static-block

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:
customer_entity
customer_entity_varchar

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

customer_entity_varchar
value_id: 1
entity_type_id: 1
attribute_id: 5
entity_id: 1
value:

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

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

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.