Frameworks vs. traditional coding

In the last few years the usage of frameworks became a must. In my opinion there are three types of coder:

1. who loves frameworks

2. who doesn’t care too much

3. who hates frameworks

The big question is: why to love/hate frameworks? Well, because they are smart.

A few years ago, in 2005, when I started learning php the best and most used browser was IE6 (internet explorer version 6). As you may know it is a very silly browser and you have to write the code carefully to achieve your goals. Most pages were very cubic-like, and they were contructed from tables… and tables in tables. At that time the frameworks still had the egg shells on their bottoms. Even Php was in the same boot: version 5.0.0, the brand new object oriented, rewritten Php.

Some guys have decided to write some rudimentary frameworks. But wait-wait-wait… what is a framework? You can read it in this Wikipedia article or just briefly: it is a software which controls the flow of your program, it is extensible and last but not least it structurates your code. Hmm… you could ask me now: ok, but what flow are you talking about? and why to extend a code? or even better: what does it mean to extend a code?

Let me answer these. The frameworks have some drawbacks: they have some strict rules which must be followed; all these rules together creates the flow. This means that a predefined logic will always run before your code. Naturally this can be a good thing but also a bad one.

Let me give you a few examples:

Zend framwork [php]:

a URL like: www.example.com/animals/dogs by default will be parsed and it will run your dogsAction method in your AnimalsController class.

Smarty [php template framework]:

in your template when you are using for example {$myVariable} it will be transformed into a value set previously in a php file with $smarty->assign(“myVariable”, “my value”);

jQuery [javascript]:

by using $(‘input[name=first_name]’) the framework finds the input tag with the name “first_name”. You could say now that you can do it with a traditional javascript method by using document.querySelector… well yes, but not before IE8.

And here we are: the frameworks have pros! They have such functionalities which are natively not supported by the system. The javascript example with jQuery will work even on IE6!

As you can see, I’m using as examples the internet explorer browser. This is because it is the slowest, silliest and most featureless browser which is used by millions of people; and when you want to write a cool website, it should work on most of the browsers. Don’t understand me wrongly: in my opinion the IE6-8 is dead, but still tons of people are using them.

And we arrived to the extensibility… It means to write your code in the same style as the framework: structured. Most of the Php frameworks separate different type of logic into separate files: html from php logic. Since a few years we hear about the MVC. The MVC separates into three: model = everything related to an object; view = html related; controller = a class which interacts with models and views. Separating the logic doesn’t mean that you won’t have php code in it. It means that it will be a minimalistic php: ifs, loops, variables. Why is it good for you? It is easier for you to find different portions of code and you can work with others in the same project in the same time without overwriting each other.

Another good thing on frameworks are the plugins. There are many plugins for the basic frameworks. Why to reimplement the wheel? Just use it and you’re done.

Are there any drawbacks? Well, there are… The frameworks are usually slower than the pure coding. I’ve been benchmarking Mysql from Php: PDO vs. non-PDO. The non-PDO version of the same script worked 10% faster. Zend Framework uses PDO, so by start it is slower a little bit. But don’t panic, we are talking about micro seconds. On a heavy framework like Magento, well… it is slow enough, so it needs a dedicated machine anyway.

When to use traditional coding and when to use frameworks? Well, it depends. If you are writing simple things like hello world, then don’t use a framework! On small pages you can use them partially, for example a javascript framework (jQuery, Prototype, Mootools, YUI etc.). In other cases it is recommanded to use a framework (Zend Framework, Symfony, CodeIgniter, Cakephp, Magento etc.).

There is one more thing. By learning the “language” of a framework, you will be able to work on a project (written in the same framework) which was written by someone else.

If you are starting to work with the framework, try to do it everything in their way. So if you use Zend Framework, then don’t create manually forms, but create ZendForm. This way you can add validation of the fields easily.

Also, it is good to know that sometimes you have to create such functionalities of your site, which is not supported natively by the framework. In these cases you have to “hack” the framework somehow. Sometimes a simple thing needs a week of researching, while you could write it in the traditional way in five minutes.

In my opinion, anyone can write structured code without a framework, but it is good to know the other way too.

 

Using Magento Flex uploader

A few days ago I tried to use Uploadify in Magento, but it failed because of jQuery noConflict, so I decided to try Magento’s default uploader, the Flex Uploader.

I couldn’t find a good documentation or tutorial about it, so I did a little research.

In the template you should put:

<?php $htmlId = "someHtmlId"; ?>
 <div id="<?php echo $htmlId ?>" class="uploader">
     <div class="buttons">
        <div id="<?php echo $htmlId ?>-install-flash" style="display:none">
            <?php echo Mage::helper('media')->__('This content requires last version of Adobe Flash Player. <a href="%s">Get Flash</a>', 'http://www.adobe.com/go/getflash/') ?>
        </div>
     </div>
     <div class="clear"></div>
     <div id="<?php echo $htmlId ?>-template" class="no-display">
         <div id="{{id}}" class="file-row">
             <span class="file-info">{{name}} ({{size}})</span>
             <span class="delete-button"><button id="{{id}}-delete" title="<?php echo $this->__("Delete")?>" type="button" class="scalable delete" onclick="uploader.removeFile('{{fileId}}')" style=""><span><span><span><?php echo $this->__("Delete") ?></span></span></span></button></span>
             <span class="progress-text"></span>
             <div class="clear"></div>
         </div>
     </div>
     <div id="<?php echo $htmlId ?>-template-progress" class="no-display">
         {{percent}}% {{uploaded}} / {{total}}
     </div>
 </div>

Practically this will be the place where the uploader will show you the progress of the upload. You will also need to place a javascript code which should look like:

    var uploader = new Flex.Uploader('<?php echo $htmlId ?>', '<?php echo $this->getSkinUrl('media/uploader.swf') ?>', <?php echo $this->getConfigJson('some_parameter_for_you') ?>);
    uploader.onFilesComplete = function(completedFiles)
    {
        completedFiles.each(function(file)
            {
                doSomethingWithTheResponse(file.response);
                uploader.removeFile(file.id);
            }
        );
        MediabrowserInstance.handleUploadComplete();
    }
    // hide flash buttons
    if ($('<?php echo $htmlId ?>-flash') != undefined)
    {
        $('<?php echo $htmlId ?>-flash').setStyle({float:'left'});
    }
//specify maximum file upload size (very important!)
    var maxUploadFileSizeInBytes = 10 * 1024 * 1024;
    var maxUploadFileSize = '10M';

 

Attention! $ is Prototype (not jQuery) in the example above.

We will need to configure the Flex uploader in the block class of the template file:

    public function getConfigJson($field)
    {
        $this->getConfig()->setParams(
            array(
                'form_key' => $this->getFormKey(),
                "field" => $field
            )
        );
        $this->getConfig()->setFileField('Filedata');
        $this->getConfig()->setUrl(Mage::getModel('adminhtml/url')->addSessionParam()->getUrl("*/*/upload", array("param1" => "value1")));
        $this->getConfig()->setFilters(array(
            'pdf documents' => array(
                'label' => Mage::helper('adminhtml')->__('Portable Document Format (.pdf)'),
                'files' => array('*.pdf')
            )
        ));
        return Mage::helper('core')->jsonEncode($this->getConfig()->getData());
    }     

    public function getConfig()
    {
        if(is_null($this->_config)) {
            $this->_config = new Varien_Object();
        }

        return $this->_config;
    }

You can specify multiple file filters with the setFilters method, not just one as in my example. Also, with the setUrl method you will set the target URL, which will do the processing of the upload. In my example I set it as */*/upload. This means that in the controller of the current page you will have to set something similar to this:

    public function uploadAction()
    {
        if (!empty($_FILES))
        {
            $result = array();
            try
            {
                $uploader = new Varien_File_Uploader("Filedata");
                $uploader->setAllowRenameFiles(true);

                $uploader->setFilesDispersion(false);
                $uploader->setAllowCreateFolders(true);

                $path = "put_your_path_to_save_here";//ex. Mage::getBaseDir('base') . DS ."my_uploads" . DS

                $uploader->setAllowedExtensions(array('pdf')); //server-side validation of extension
                $uploadSaveResult = $uploader->save($path, $_FILES['Filedata']['name']);

                $result = $uploadSaveResult['file'];
            }
            catch(Exception $e)
            {
                $result = array(
                    "error" => $e->getMessage(),
                    "errorCode" => $e->getCode(),
                    "status" => "error"
                );
            }             
            $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
        }
    }

Don’t forget to load the required javascript libraries. You can do it in your layout xml file:

   <your_layout>
        <reference name="head">
            <action method="addJs">
                <js>lib/flex.js</js>
            </action>
            <action method="addJs">
                <js>lib/FABridge.js</js>
            </action>
            <action method="addJs">
                <js>mage/adminhtml/flexuploader.js</js>
            </action>
        </reference>
   </your_layout>
   

That’s all folks!

Adding new action into controller in Magento

Sometimes you have to change the default functionality of Magento, either by modifying the core module (which is not recommended) or by writing your own module. The latter is described in many other websites, so I won’t write about that. But I feel important to write about such a simple thing like adding a new action into a controller.

Why? Because I’m just learning Magento and I have already spent too much time figuring out why it doesn’t work.

As many of you already know, Magento is based on Zend Framework. The basic mechanism of processing an URL is the following:

<protocol>://<host>/<controller>/<action>[/<parameters>]

<protocol> is for example http

<host> is your domain name ex. www.example.com

<controller> is the name of your controller

<action> is the name of your action

The rule is simple, the controller’s filename is <controller>Controller.php and the action has to be a function inside the controller with the name <action>Action.

Here’s an example:

http://www.example.com/hello/world

and it will call the worldAction in helloController.php.

These are the basics you need to know when starting to work with Magento. It is a little bit different but not so much.

The Magento team have made their system ultra-extra extensible, and that’s why it is so slow – at least the community edition. That is the reason why my local apache crashed many times while I tried  to debug with xdebug to understand how Magento works; and beside this, sometimes even Eclipse or Netbeans cannot resolve the correct class names.

I won’t go into the details of routings or other special stuff, I know there are plenty of ways to create a new action, but sometimes it is better to know the basics. In the case of Magento you will see something similar to what we have for Zend Framework:

<protocol>://<host>/[index.php/]<module frontName>/<controller>/<action>[/<parameters>]

example: http://www.example.com/index.php/myuniverse/hello/world

The basic logic is the same: you will find the worldAction in the helloController.php in your module’s folder.

Up to this point everything seemed to be clear for me. I opened the browser, entered the url and it redirected me to the home page. Tried to do things like

<?php
class ...._HelloController...
{
  ...
  public function worldAction()
  {
    echo "something";
    exit;
  }
  ...
}

but the “something” didn’t show up. I made a little research to make it work, tried different configuration changes in config.xml but it didn’t helped. I got a tip to make a route in the configuration, which would point a URL to a specific method of a class… what??! Does it seems complicated only for me? I said there must be an easier solution for this.

And the solution is really easy. You may have already observed that on every page (of the admin backend) you can find some junk parameters like …/key/0123456789abcdef0123456789abcdef/. Well, I thought that it is rubbish… it is not.

Suddenly, I said `Let me try to generate the URL to my page within an existing template with something like:

$this->getUrl("*/hello/world", array("myparam1" => "myvalue1"))

which resulted in a bulky, sausage-like  link:

http://www.example.com/index.php/myuniverse/hello/world/myparam1/myvalue1/key/0123456789abcdef0123456789abcdef/

then I opened it in the browser and tadamm!: it showed the “something”.

Briefly: you don’t have to modify your configurations, just simply add your action method into the controller (ex. worldAction into helloController.php) and access your page with the complete URL (which contains the […]/key/[…]/); you can generate the link with the getUrl() function.

Uploadify with jQuery noConflict

Yesterday I tried to implement on a webpage the Uploadify 3.1. I downloaded the zip package from the official website. It didn’t contain an example code usage, this was a bad omen. Anyway, I used it before, so I could easily set up and integrate it on the page.

But it didn’t work.

The place – where the upload button should have been –  changed the mouse pointer but the button was invisible. Also I could click on it and then browse for files with it, but the file was not uploaded. I’ve searched for a while after such a bug and after spending a few hours with the search engine, I found out that Uploadify has problems when the $ function is not the jQuery. In my case the $ was the Prototype and the jQuery was the $j. In the Uploadify jquery plugin I tried to replace all the relevant $ functions with $j, but it still didn’t work.

Briefly: if $ is not jQuery, then don’t use Uploadify, unless you want to rewrite the Uploadify jQuery plugin and recompile the Uploadify flash component.