Looking for (Magento) developers

Develop : « enrich, growth a software »

Yes it’s my definition of the word « develop ». I checked the Internet to ensure that I wasn’t wrong and I agree with the correct definition.

Many years ago, on the first 1.0 Magento release, we made a comparison for a request between the commerce server and Magento plateforms. At this time, the clients chose Magento in part because of its functionalities : Yes Magento is rich, and cover many e-merchandiser requirements.

And in case it’s not enough, there is perhaps a module allowing you to customize it according to your specificities. You know it’s quite easily to reach your customer requirement with this solution.

But I’m always despite when I want to use a functionality on my client’s plateform and see it does not work anymore… Why ? How could that happen ? This function was working, and now, it does not exist anymore….

Yes, web developers have broken it, one more time.

Continue reading “Looking for (Magento) developers”

How to schedule Magento sales rule correctly?

Magento provides a sales rule engine which allows you to offer discount to your clients: free shipping, buy x products and get y products free, providing a discount from a voucher are samples usage of prices rules

Two important concepts exist in this model:

  • Can we cluster sale rules: can rules be combined or if a rule is applied, are the others automatically excluded ?
  • Sorting rules importance within the priority concept

How does Magento apply prices rules on cart ?

Each time you update your cart content or each time you display the cart page, Magento loads all the active sales rules for the current date, current website, current user group and test for-each rule if the conditions match the cart content. If yes, Magento applies specified discounts to items in cart.

If a rule has been flagged as “stop rule processing”, we stop iteration on the rule collection. If not, we continue and apply the others matching discount until we have tested all rules or we have applied a discount which stop iteration

The Magento sales rule priority

Priority is a numeric id defining the rule importance and how it’ll be tested: the less is the priority value, the more important is the rule

Priority is specified when the sales rule is defined from back-office

Priority is not a mandatory field: if you do not specify a value, the priority applied will be 0, and so the rule will be tested at first before all other sale rules

Technically, when the rules collection is loaded, it’ll be sorted by the priority value (sort_order field)

Priority is not unique: you can define several rules having the same priority

What happens if some Magento sale rules have the same priority?

There is no second filter to order rules: so if you have two rules which can be applied, this is the oldest one which will be used and applied firstly. Is it really what you were expecting? Perhaps not.

Furthermore, if you have many sale rules, you should ensure to know exactly each conditions criteria to understand exactly how are applied rules and in which order. Possibly very difficult in a long time or if you have many sale rules defined

How can you reduce the risk that some rules are not executed as you want?

Reviewing the rules to ensure that priority is unique is the only one solution to avoid risk that rules are not executed the way you are expecting them. But it could be difficult to maintain if you define later others sales rules.

If you want to reorder priority, you can define priority levels: the most important one have a priority defined with one digit, lesser priority with two digits, oldest one or more generic sale rules with a priority of three digits. In this case, you’ll ensure that you’ll know with an unique priority how they’ll be tested, and be able to add others rules easily

One other best practice is to defind strong application conditions criteria: the more generic they are, the more risk you have to apply a rule that should not be executed

Init Magento cache block policy in _construct method… or not

We often see the Magento cache block policy initialization in the _construct method, like in this example:

class Namespace_Module_Block_Type extends Mage_Core_Block_Template
{
     protected function _construct() {
          $category = Mage::registry('current_category');

          $this->addData(array(
               'cache_lifetime' => 86400,
               'cache_tags'     => array(Mage_Catalog_Model_Category::CACHE_TAG."_".$category->getId()),
               'cache_key'      => $category->getId(),
          ));
     }
     ....

This is not a quit good example of cache block policy initialization, for the following reasons

Init cache block policy in _construct adds unnecessary treatment

The problem is due to the way of how Magento loads the page structure and how it will render blocks content loaded from cache:

When you load the layout, Magento will parse and build all defined elements in layouts files. This means instantiate all defined blocks. After, Magento will check if your block content is already in cache, and will use it if yes, or build it if not.

But instantiating one block will call the _construct method. This means even if your block content is in cache, your block will execute each time all instructions within _construct method.

Do you require to rebuild cache tags list each time?

The answer is no. The cache_tags list is required only when saving generated content into cache. So if you initialize the cache tags list in _construct, it would have an interest only if your block content doesn’t come from your cache

Init Magento cache block policy in _construct let you avoid to use layout properties

Another problem is due to accessible data in _construct method: when calling _construct, block initialization is not finished: Magento will populate data, set name in layout, reference current layout in block and so all these informations won’t yet be available.

so layout informations are not yet available, and you restrict cache block policy only to data managed in block

Possible solutions to avoid these problems?

Specifying a cache block policy is not an option for performances reasons. But defining it in _construct method can reduce performances benefits if you continue to load some data within. A possible solution to bypass these problems is to define on your block the methods getCacheLifetime, getCacheKey and getCacheTags: treatments within will be executed only when they’ll be called

Cancel commits on Magento core files with subversion hooks

As a best practice, it is not recommended to update Magento core files. This can be done by Magento overloading mechanism

This morning, an old colleague of mine mentioned that a developer committed some updates in the app/code/core files.

This could be blocked by subversions hooks scripts

What is a subversion hook?

Introduction to subversions hooks: the hook events

Subversion implement a hook mechanism which allows to call some externals scripts on some repository events. This functionality allows you to customize your repository work-flow. The most common hook usages are:

  • Sending email notification (on each commit, when a tag is done, …)
  • Control access to repository (when locking files, …)

List of available hooks events can be found in the subversion documentation

Hook event we’ll use to control our commit must be executed before transaction is completed: the pre-commit hook

What subversion does on a subversion hook event?

On this predefined event list, Subversion will check if there is an executable script in the hooks folder of your subversion repository with the name of the event

If yes, subversion user will call this script with some arguments. Arguments list sent to this script depends on the hook event. For example, for the pre-commit hook script, arguments are:

  • Full path to repository involved
  • Current transaction number
  • With these arguments, you can do what you want within, especially calling all the administrative subversion commands:

    • svnadmin
    • svnlook

    Setting up a subversion hook which cancels the transaction in case core files are updated

    Here’s an example of the script you can use as pre-commit hook for Magento projects

    #!/bin/bash
    ##################################
    # render more readable parameters
    ##################################
    REPOS="$1"
    TXN="$2"
    ################
    # configuration 
    ################
    # path to svnlook script
    SVNLOOK=/usr/bin/svnlook
    #############
    # librairies
    #############
    # a method to send message to client and end transaction
    show_error_message() {
        echo $1 1>&2;
        exit $2;
    }
    ###############################
    # run
    ###############################
    # fetch the account user from the current transaction informations
    AUTHOR=`$SVNLOOK author -t "$TXN" "$REPOS"`
    
    # check if we do not updating file in core files
    $SVNLOOK changed -t "$TXN" "$REPOS" | grep "^U \+app/code/core" > /dev/null
    if test $? -eq 0 
    then 
        show_error_message "$AUTHOR, You cannot update Magento core files" 2
    fi
    

    This script will look for files involved in current transaction with the svnlook script and look for path app/code/core in the output answer. (this svnlook command lists all files and their state in a transaction). If we find something matching, we send a message on the STDERR (STDERR will be sent to subversion client) and exit script with a non 0 error code, which will cancel the transaction and so block the commit

    To use it, just copy this script content in a hooks/pre-commit file of your repository folder and make it executable by the system

    Conclusion about usage of hooks on Magento scripts

    No more reasons to leave developers committing app/code/core files with this script!

    But you can extend hooks to do many other things on your repository: block Magento core files commit, block update on tagged versions, notifications of branch creation, block commit of PHP files which contains parse errors, etc…

    Do you use these events on your Magento repositories?

    How to patch PROPERLY Magento Zend Framework XML-RPC security issue?

    On July, 5th, 2012, an important security issue has been highlighted in Zend Framework, and so in Magento. This issue allows people to read almost any file on your webserver. A very dangerous issue, that’s why it must be patched quickly

    Tell me, how can we patch it?

    Oh nice, there is a patch available. I open it, and now, I have some red spots appearing on my body: they edited the embedded Zend Framework and Magento core sources…. Almost everybody agree that we do not edit the Magento sources files. Why do it there?

    A common workaround about Magento overloading is the following one: use local to patch Magento and Zend Framework files. We’ll use this way to patch the XML-RPC issue instead of editing Magento sources files

    The following script updatepath.sh init your Magento so it can patch this way. It works with the provided patch file for CE 1.5 to 1.7 Magento version

    #!/bin/bash
    ##################################
    # config
    ##################################
    LOCAL_FOLDER="app/code/local";
    RESPONSE_FILE="Zend/XmlRpc/Response.php";
    RESPONSE="$LOCAL_FOLDER/$RESPONSE_FILE";
    REQUEST_FILE="Zend/XmlRpc/Request.php";
    REQUEST="$LOCAL_FOLDER/$REQUEST_FILE";
    PATCH_FILE="CE_1.5.0.0-1.7.0.1.patch";
    DESTINATION_PATCH_FILE="kyp_$PATCH_FILE";
    ###################################
    # process
    ###################################
    # check if patch file already exists
    if [ ! -f $PATCH_FILE ]; then
        echo "Patch file $PATCH_FILE does not exists. Please download it at http://www.magentocommerce.com/blog/comments/important-security-update-zend-platform-vulnerability/";
        exit 2;
    fi
    # create local folder if not exists (eg: CE1.7 and related EE)
    if [ ! -d $LOCAL_FOLDER ]; then
       echo "Init app/code/local folder";
       mkdir $LOCAL_FOLDER
    fi
    # create folder for Zend Framework Response file patch
    if [ ! -d "$LOCAL_FOLDER/Zend/XmlRpc" ]; then
        echo "Creating Zend/XmlRpc local folder";
        mkdir -p "$LOCAL_FOLDER/Zend/XmlRpc";
    fi
    if [ -f $RESPONSE ]; then
        echo "File $RESPONSE already exists. Please append patch in";
        exit 1;
    fi
    echo "copying $RESPONSE_FILE in local folder";
    cp lib/$RESPONSE_FILE $RESPONSE;
    
    if [ -f $REQUEST ]; then
        echo "File $REQUEST already exists. Please append patch in";
        exit 1;
    fi
    echo "copying $REQUEST_FILE in local folder";
    cp lib/$REQUEST_FILE $REQUEST;
    # update patch file to replace lib by app/code/local
    echo "Update patch file"
    sed "s|lib/|app/code/local/|g" $PATCH_FILE > $DESTINATION_PATCH_FILE
    echo "new patch file $DESTINATION_PATCH_FILE has been generated. You can now apply it with patch -p0 < $DESTINATION_PATCH_FILE"
    

    This way, you are sure that your Magento will always be patched, even if you upgrade to a prior version than 1.7.0.2 CE (first release which embedded the patch)

    The only way it won't work is if you load Response.php and Request.php files with a requirement to full path to lib folder, but this is not the Magento best practices

    Don’t forget app/design/adminhtml/base/default folder when adding customs elements to Magento back-office

    From the beginning of Magento until today (eg Community edition 1.7 and Enterprise Edition 1.12), Magento admin design folder has always been located in the app/design/adminhtml/default/default folder.

    This folder contains all the required files to build adminhtml pages:

    • layouts to define adminhtml pages structure
    • templates used by theses layouts

    So, If you need to provide specific back-office interfaces, where will you put them? in this app/design/adminhtml/default/default folder?

    Magento page structure loading file API

    Adminhtml is managed like the same loading API used in the front office; this API has been reviewed in Magento CE 14 and related Enterprises editions to load content in the following order:

    • Custom package / Custom theme folder
    • Custom package / default theme folder
    • Base package / default theme folder

    I have previously explained the aim of this rule and what you can do with it

    But the question is: adminhtml default default folder is: base package or custom package?

    app/design/admintml/base/default as a default package folder

    Yes it is. The folder app/design/admintml/default/default is not a default one, but the the default theme for the adminhtml default package; folder app/design/admintml/base/default can also exists even if it’s not embedded with magento sources.

    So for sure, this is not an error to enhance this default package, but it does not respect the role of this loading api.

    So it could be interesting to use app/design/adminhtml/base/default as folder for your new back-office interfaces

    Conclusion

    app/design/adminhtml/base/default folder does not exist in Magento sources but you can create it as you wish.
    In a dream world, back-office updates should be managed as this:

    • Move app/design/adminhtml/default/default folder to app/design/adminhtml/base/default folder: we ensure this way that we have the default magento design for back-office
    • Use a custom package for the back-office updates of the existing interfaces
    • Provide new back-office interfaces in the adminhtml/base/default folder

    Do you have already created the app/design/adminhtml/base/default folder for your own back-office interfaces or you do not take care of this case?

    Magento multistore model: in which default language do I have to describe best my sales catalog?

    One of the Magento amazing feature is the ability to manage different stores in different languages: You can administrate many websites to share a common sales catalog in a same Magento host

    Magento configuration hierarchy is based upon a cluster of website, stores and store views. The following schema is an exemple of a possible Magento multi store usage: We have two websites; the first one is available in French and English, the second one in Japanese and Chinese

    Magento products are initially in a code pool not linked to a website. Linking a product to a website renders it available for sale. But if you share this sales catalog within different languages, it’s interesting to take time to define in which default language you’ll define your catalog, the language for the product code pool / default scope

    Take a look at the following example:

    • If you store your catalog in French, you only have to overload description for English store view.
    • If you store your catalog in English, you must make two times the same work for the French stores views

    Take care also of your deploying plan: if you plan to open many website for south america, perhaps it could be interesting to set up your catalog in spanish instead of you using your native language: describe a catalog is a long task, and time is money

    So you should always use the most used language

    Have Zend Studio and Eclipse PDT faster with Magento projects: the build path configuration

    Eclipse PDT editors like Zend Studio analyse the PHP source code to enable autocompletion: they analyze source files and index content found in

    Magento embeds more than 10000 files (7000 php files) in Magento 1.7.0.0. Do we need to index all content? no

    To ensure that eclipse and Zend studio will offer you all the expected functionalities, you can make it faster, by removing all the non required editor files from editing build path.

    What is Zend studio and Eclipse PDT build path?

    Build path defines classpath for your project: folders that will be analyzed by editors to index content and where look for methods.

    All build path sources defined within will be made available for Content Assist options, including source code completion

    Basic configuration of the build path directive in Magento projects

    Folders that we can remove from build path could be the following ones:

  • var: contains variables Magento data. Too much volatil, there is no real reason to include it in build path
  • media: all media elements used on your website. It should contain all picture files from your website and so there is no reason to analyse binary sources
  • skin: even if skin folder can contain js files, we can remove it
  • app/locale: for the time being, there is no link between magento translations calls and translations files. so we can also remove it
  • app/etc: like translations files, we can remove it
  • If you do not enable javascript support on your magento project, you can also remove the js folder

    How to configure build path with Zend Studio and eclipse PDT?

    On your Magento project, click right on the project and edit the build path configuration menu through the menu configure build path

    You’ll have a new window which look like this one:

    And then edit the excluded folders in list. When finished, eclipse will rebuild the build path with your new configuration

    By updating the build path, you can reduce by 30 percent number of files analyzed by eclipse. Even if you use some ssd disks, your eclipse should be faster. so if you use some slower disks or use shared networks folders, you should not forget to use this configuration value

    Best practices when using Magento setup scripts

    As I mentionned before, Magento setup scripts enable you to make your software setup more reliable. But working with setup require to use some best practices. If not, it could become a nightmare…

    Here’s a list of points you should take care of when writing setup scripts

    Do not update a setup script already under revision control

    A script already under version control has perhaps already been played in some locations, and so core_resource record for this setup has already been updated

    In this case, in order to play a second time this script, you must restore the initial state before it:

    • At least, downgrade the core_resource related record
    • Perhaps destroy all that has been run within the script

    It’s very problematic because we lost all the automation within the setup. So you should really be careful before sharing a script to ensure that all the script’s content is well written

    Be independant from database structure

    This is why I wrote previously to not use the SQL files and prefer using the PHP scripts: Magento allow you to prefix your table names for security reasons. If in production you’ve prefixed your tables but not in testing, your script must work fine in each case.

    So you must be able to find the table name in currnet context, and this is the role of the methode Mage_Core_Model_Setup::getTableName method

    Be independant of the server type which hosts your Magento

    For now, this is only in theory that Magento can be run on other database servers than MySQL. But even if it’s a dream, perhaps the module you developed will exist very longer and in 2015, when Magento will be able to use another SGBD, your setup script will also work fine

    To do that, it’s really easy since the 1.6CE / 1.11EE because database connexion layer has been updated to be more abstract

    Reduce SQL instructions to their minimal to have the more accurate error management

    Take a look at the following SQL query we want to run:

    CREATE TABLE foo AS
    SELECT entity_id, sku FROM catalog_product_entity;
    ALTER TABLE foo ENGINE=Memory;
    ALTER TABLE foo ADD INDEX (entity_id);
    </code>
    <p>The historical way to run it in Magento could something like this:</p>
    <code>
    $this->run("CREATE TABLE {$this->getTableName('module/foor')} AS
    SELECT entity_id, sku FROM {$this->getTableName('catalog/product')}
    ALTER TABLE  {$this->getTableName('module/foor')} ENGINE=Memory;
    ALTER TABLE  {$this->getTableName('module/foor')} ADD UNIQUE (entity_id)");
    

    Fine, but each SQL instruction can have its own errors. So if we play back the script, it's possible to have some instructions run many times and could lead to an inconsistent context, like:

    • Same index defined multiple times
    • Insert run many times
    • ...

    To reduce this risk, divide each SQL query to its minimal entity: if an SQL error is encountered, the following code won't be executed and so next time you'll launch the script you won't run the same SQL request. So in this example, use multple run instructions

    Take care of existing

    It's very important to take care of possible existing resources, and so, for the following reasons:

    • In 1.6 and previous versions, there is no semaphore in Magento setup scripts; in multiple servers, it's possible that you've started your setup while another server was aleady running it (but have not yet updated the core_resource table)
    • If the first time you've run it, there was an error, you'll need to execute it a second time. Testing already existing resources will avoid you to restore initial state before executing it a second time

    It can be done in SQL instruction or within PHP code

    Don't use constants in Magento setup scripts

    Constants are used to declare some reference content. So it's often the case when you write some setups scripts.

    But if you reuse the constant definition in multiples scripts, take care of ensuring that you test if the constant already exists: When Magento run some upgrade scripts, it will execute all the required scripts in one time by including all scripts. So it could lead to a case thasituation where the constant is defined multiple times, and so through an error.

    Leave Magento use its own database connexion management

    It means, do not access connexions objects in setup scripts: this is not a problem when you use only one database server, but if you use different read and write database servers, by using database connexion objects you 'll may change where will be written the data you want to setup

    So leave Magento make it's own work

    Some best practices to manage templates with the magento template loading API

    I presented you a few days ago an introduction on how are built the Magento pages. Now we we’ll see how the templates files are loaded since Magento 1.4 with the template loading API and how we can use this loading API to reduce our work with Magento.

    Reminder: how are defined the templates path in a layout file?

    Templates are defined in the layout files in a couple block / template with a relative path like this:


    <block type="module_identifier/class_suffix" template="relative/path/to/template/file/in/the/template/design/subfolder.phtml"/>

    For example, here’s the definition of the block / template that defines the search form field available in your catalog pages:

    So, how does Magento find the full path for the relative path defined in this structure?

    Magento template loading API available since Magento community edition 1.4 and above (Enterprise 1.7 and above)

    Since Magento 1.4.x, when a page is requested, Magento analyzes all couples block / template that compose it. Afterthat, Magento will look for the full path of the template file in the following folders:

    • 1. app/design/%context%/%design%/%theme%/template
    • 2. app/design/%context%/%design%/default/template
    • 3. app/design/%context%/base/default/template

    Magento takes the first file found and use it.

    What happens if the file is not found? By default, if template file is not found in these folders:

    • No output is renderering
    • A trace in log will be written if log is enabled

    This loading API explains why we can define easily some temporary themes for your site like for christmas, summer, sales…: after setting up a new theme, you must only update some elements in your template in a new theme template folder

    This is this loading API which allow Magento to drive some merchandising design on your website

    We will now see how we can work more efficiantly whis this loading template API

    Some best practices when building a new Magento design and theme

    Copy paste the default theme when building your package?

    When looking for the template file in the folders mentionned before, Magento runs a file_exists. Even if copy paste is the devil, when you build your package, duplicate content will avoid many file_exists when rendering your page, so it could be interesting to duplicate the base/default theme

    But one of the drawback of duplicate base/default content will appear during magento upgrade: you won’t benefit of the new templates design for templates you have not overloaded: after upgrading the magento source code: do you really want to check if all template have changed? Or keep your own one and do not use the new functionnalities?

    Today, I haven’t seen any limit of the file_exists loading. There are many others points to check before this performance option to make magento faster…

    New functionnality in Magento: in base/default !!!!

    Another common workaround in Magento project is that we can hear that it’s strictly forbidden to write in the in base/default template folder. I never understood why: if you run in multiple stores model and have specific packages defined for each store, this is the only way you have to share templates between each store. In case we do not want to write in base/default, the only way that we have to share template is to copy paste it in each package/default theme… wonderfull 🙂

    Furthermore, if you want to share your module in Magento connect, this is the only way you have to avoid requiring a post configuration by copying the embedded template files in the current package folder (modules should be installed through only one click)

    How organize your new templates file in your theme?

    When we define a new couple block / template, we provide a relative path to define the related template to load. As a best practice, I cluster all my templates in a subfolder like %namespace%/%module%

    This best practice has the following advantages:

    • When you develop your module, this is quicker to find it in the directory tree
    • If you share your module in Magento connect, this reduce the risk that other modules will have already existing templates in directory tree

    Be lazy when you work with Magento templates!

    I’ve made hosting for one of the biggest french bank and I liked this work: check everything is ok or be able to solve problem quickly and easily with the tools you made. Magento loading API is able to help you to provide you quick answer and easily manageable way to customize the appareance of a Magento website

    Sometimes I hear that for performance issues, some people overload the Magento template loading API. It’s a shame to avoid using this model because your client won’t be able to drive the website marketing design: model is quite fine and allows you to do what you want easily without too much work. There are really many thing to do before updating this API for performance issues