Last year, in Magento 2.0 Live Chat Session, it was discussed that the next major release of Magento would be compatible with PHP 5.4 and would use Zend Framework 2 components. However, exploring the under development code till last month, namespace utilization could not be seen. But the code after the latest commit has major improvement on this step. As far as I have observed the code, Traits and Generators of PHP 5.4 and 5.5 are still not seem to be implemented and probably they wouldn’t be part of the next big release to make it compatible with PHP 5.3.
First stable version of PHP 5.3 was released more than 4 years ago. Namespace, Late Static Binding, Closures etc. were the most anticipated features which many of the PHP developers were keen to use. However, as it usually happens with PHP, these new features has taken a long time to be adopted by developers. The primary reason I can see for this delay of adoption is, it requires most of the code to be rewritten for using Namespace, which would take lots of time for huge projects. Also it breaks backward compatibility because Namespace does not work in earlier versions of PHP. Therefore, huge projects like Zend Framework, Symfony, Magento etc. planned to adopt these new features in their major version upgrade. Where both Zend Framework 2 and Symfony 2 are already released, Magento 2 is under development.
It is also nice to see that Magento 2.0 has dumped Prototype JS and adopted jQuery. Finally, with Namespace, Closures and jQuery, it would be more fun to develop themes and extensions of Magento 2.0.
In my previous post, I had explained a way to add extra controllers to existing route. Here I am going to explain another method which is used for overriding controllers and actions. Like my each post on tips & tricks, I am going to first explain where the trick is applicable! I am considering that readers of this post are aware of MVC architecture in Magento.
Let me explain the difference between the both tricks. The trick explained in previous post is used when we need additional URLs in same route i.e. additional controllers and actions. I have already explained an example there. Here we need to change the behavior of existing controller and action. For example, when a customer adds a product to shopping cart,
Mage_Checkout module is called. If we want to override this by
myaddAction as similarly as we can override Models and Blocks in our own modules. So the the trick in previous post is used for overloading while the trick here is used for overriding.
Of course, this too can be done just by simple XML configuration (apart from creating custom controllers and actions) but without using route rewriting approach! Let’s take a same example above where we want to override action for
checkout/cart/add. First create
My_Checkout module with
MycartController class and
myaddAction method defined within it. The way to do this is better explained in this wiki. Then the configuration required in
My_Checkout module is like below:
<global> <routers> <checkout> <!-- Mage_Checkout module --> <rewrite> <cart> <!-- CartController --> <to>mycheckout/mycart</to> <!-- My_Checkout module, MycartController --> <override_actions>true</override_actions> <actions> <add> <!-- addAction --> <to>mycheckout/mycart/myadd<to> <!-- My_Checkout/MycartController/myaddAction --> </add> </actions> </cart> </rewrite> </checkout> </routers> </global>
Here we also need configuration to define module front name for
My_Checkout module as below:
<frontend> <!-- It will be admin for overriding admin controller --> <routers> <mycheckout> <use>admin</use> <args> <module>My_Checkout</module> <frontName>mycheckout</frontName> </args> </mycheckout> </routers> </frontend> <!-- It will be admin for overriding admin controller -->
Note: The above configuration examples only display portions of
config.xml file. Please do not consider it as a complete configuration.
Simple isn’t it? Now let’s understand how it works. The work flow of this rewrite process is little bit tricky.
- When an
checkout/cart/addaction is going to be dispatched, first it is passed through rewrite process.
- Rewrite process tries to find
global/routers/checkout/rewrite/cartnode is found in configuration, where
checkoutis front name of
- If this node is not found, rewrite process is not be continued and returned to dispatch process. So the action is executed normally. Otherwise, rewrite process is continued.
- Now, under this node, it tries to find whether
false. By default value of
override_actionsis true. So if it is not added in configuration, it is considered as true.
true, it overrides all actions of
Mage_Checkout_CartControllerwith same actions of
My_Checkout_MycartControlleras defined by
mycheckout/mycart. For example, if we have defined
My_Checkout_MycartController, then it automatically overrides both
Mage_Checkout_CartController. In short using
override_actionsnode we can override whole controller instead of individual actions.
actions/addnode is defined where,
override_actionsnode value is not considered and overrides action by value of
actions/add/tonode which is
myaddAction. So we can also override individual actions by this type of configuration.
Sounds good again? Try it too…
I have already talked about flexible architecture of Magento Commerce in my previous posts. As Magento allows to customize its default behavior without touching and modifying the existing code, we can override any of the existing class by defining our own in our out of the box extensions. I have also played with Magento by creating variety of extensions, and believe me, it was a real fun of programming. Magento allowed me to change everything I desired.
But I was still feeling that something is missing! And that missing thing was provision for sharing of route names which is now available since Magento 1.3 released yesterday. Now, the first question may arise here that “what is sharing of route names?”. ‘Sharing of route names’ is not a functional feature. So if you’ll try to find it in Magento features list, you may be disappointed. Actually it is a feature for developers. It is not even mentioned in Magento 1.3 Release Notes. I found this secret feature in newer version of Magento when I was roaming inside the code to search the difference between 1.2 and 1.3. Let me explain this feature in more detail.
Sometimes, I was supposed to develop extensions which required extra pages or forms in existing modules. For example, adding extra features to Admin Panel. I needed some extra controllers and actions for Admin Panel. This seems OK. I could easily create a local module for it as explained in this Wiki. But an uncomfortable part in this way is this configuration:
<admin> <routers> <sintax> <use>admin</use> <args> <module>Mage_Sintax</module> <frontName>sintax</frontName> </args> </sintax> </routers> </admin>
Here, all URLs of my additional pages will be started by
/sintax/ while all other admin panel pages will be started by
/admin/. I am forced to use other routes for my additional modules. I cannot just add more URLs to ‘admin’ route! This can be fare for Admin Panel pages as they will never be visible by public. But what if I want to add more pages to frontend? If I add any extra page to ‘catalog’ module, I can’t define URLs for my pages starting with
/catalog/. I have to define a route something like
/mycatalog/ which I don’t like!
One solution for this to use URL rewrite from
/mycatalog/mypage/. But unfortunately, URL helpers will still generate URLs like
The problem with the older version of Magento was mapping one to one relationthip with module front name to module real name i.e. ‘catalog’ => ‘Mage_Catalog’, ‘admin’ => ‘Mage_Adminhtml’ etc. So I could not map my additional module to existing front name. But Magento 1.3 allows to map additional modules to existing front names. How? Just by changing router configuration for module shown above to the following:
<admin> <routers> <adminhtml> <args> <modules> <sintax before="Mage_Adminhtml">Mage_Sintax</sintax> </modules> </args> </adminhtml> </routers> </admin>
This configutation will add
Mage_Sintax module to
admin frontname. An attribute
before can be added to give more priority then existing module in finding controllers. For example in this case,
/admin/catalog/ URL will call a controller class
Mage_Sintax_CatalogController, if it is defined and if not then it will call
after attribute will assign less priority then the existing module. We can add as many modules as we need to the same front name using this way.
Sounds good? Then try it yourself…!
Zend Framework 1.7.0 is now available from the Zend Framework download site: http://framework.zend.com/download/latest
This release introduces many new components and features, including:
- Zend_Amf with support for AMF0 and AMF3 protocols
- Dojo Toolkit 1.2.1
- Support for dijit editor available in the Dojo Toolkit
- ZendX_JQuery in extras library
- Metadata API in Zend_Cache
- Google book search API in Zend_Gdata
- Preliminary support for GData Protocol v2 in Zend_Gdata
- Support for skip data processing in Zend_Search_Lucene
- Support for Open Office XML documents in Zend_Search_Lucene indexer
- Performance enhancements in Zend_Loader, Zend_Controller, and server components
- Zend_Mail_Storage_Writable_Maildir enhancements for mail delivery
- Zend_Tool in incubator
- Zend_Text_Table for formatting table using characters
- ZendX_Console_Unix_Process in the extras library
- Zend_Db_Table_Select support for Zend_Paginator
- Global parameters for routes
- Using Chain-Routes for Hostname-Routes via Zend_Config
- I18N improvements
- Application wide locale for all classes
- Data retrieving methods are now static
- Additional cache handling methods in all I18N classes
- Zend_Translate API simplified
- File transfer enhancements
- Support for file elements in subforms
- Support for multifile elements
- Support for MAX_FILES_SIZE in form
- Support for breaking validation chain
- Support for translation of failure ,messages
- New IsCompressed, IsImage, ExcludeMimeType, ExcludeExtension validators
- Support for FileInfo extension in MimeType validator
- Zend_Db_Table_Select adapater for Zend_Paginator
- Support for custom adapters in Zend_Paginator
- More flexible handling of complex types in Zend_Soap
In addition, almost three hundred bugs have been fixed:
I develop my PHP web applications in Zend Framework since its first stable release. I compared it with many other frameworks and I choose Zend Framework for my development approch because of its outstanding flexibility, huge community support and transperent development roadmap.
Yesterday, Zend has released a brand new version of Zend Framework 1.6. This new version has introduced many new useful features. The new 1.6 version includes built in support of Dojo Toolkit, a powerful AJAX and UI library as well as PHPUnit, the most powerful Unit Testing framework for PHP.
The complete list of new features of Zend Framework is:
- Dojo Integration
- Dojo Data packing
- Dojo View Helper
- Dijit integration with Zend_Form & Zend_View
- Dojo Library Distribution
- SOAP Server
- SOAP Client
- WSDL access
- WSDL Generation
- Preview of Tooling Project in Laboratory (see /laboratory folder)
- Command Line Interface
- Project Asset Management
- Unit Testing Harness for Controllers
- Lucene 2.3 Index File Format Support
- Zend_Session save handler for Database Tables
- Paginator Component
- Text/Figlet Support
- ReCaptcha Service
- Zend_Config_Xml Attribute Support
- Character Set Option for DB Adapters
- Zend File Transfer Component
- New Media View Helpers (Flash, Quicktime, Object, and Page)
- Support in Zend_Translate for INI File Format
- Zend_Wildfire Component with FireBug Log Writer
- Zend_Db_Profiler with FireBug support
With the lots of new features, Zend Framework has also enhansed the performance compared to older releases. You can download the latest release of Zend Framework from here.
Zend Framework has made its own place in the clouds of more than 40 PHP Frameworks.
Frameworks like Ruby on Rails have made MVC (Model View Controller) architecture more popular and easier. Most of the PHP frameworks like CakePHP, Symfony, PHP on Trax, Zend Framework have followed similar patterns as Ruby on Rails for MVC. By using these frameworks, MVC in design is no longer painful.
But do all people maintain MVC in real manner??? The major misconception the people have is about the role of Model in MVC. I read many tutorials of Ruby on Rails, Zend Framework, CakePHP and Symfony. Many of the tutorials explain the role of Model as to access data from database. That means Model would be responsible for providing and updating of data into the database!!! All the business logic would be handled by the Controller!!!
It is a simple way, but would be fare only for small scale applications which do only CRUD (Create, Read, Update, Delete) operations. Then, what about large applications where business logic is much complex? Is it a good idea to encapsulate all business logic in Controller?
I recently read some blog posts such as:
ActiveRecord sucks by Kore Nordmann,
ActiveRecord sucks, but Kore Nordmann is wrong by Mike Seth,
ActiveRecord does not suck by Bill Karwin and
Fat Models and the Data Access Layer by Dave Marshall
Bill Karwin and Dave Marshall explains actual implimentation of Model. The Model is a business logic of your application not only the database access layer. Active Record (in RoR, Cake, Symfony) or Table/Row Data Gateway (in Zend Framework) should be used as a part of model not as a model. Your all business logic should be encapsulated in Models only.
One of the strongest reasons for following MVC is reusability. Think about the case when you want to port your PHP web application to desktop application using PHP-GTK. If you have followed correct MVC architecture then you can easily reuse the same Models of web based application into GTK based application. If you have encapsulated your business logic in controller, then you have to rewrite all the code again for GTK!!! It would simply kill DRY (Don’t Repeat Yourself) principle!!!
I am using Zend Framework since its 1.0 release. At the beginning I read lots of tutorials about it and I was in the same misconceptions about the Models. Then I had taken a look around the code base of Magento Commerce. As I told in my previous post, Magento is built on Zend Framework and follows MVC architecture. (I noticed that Magento uses many ZF components but does not use Zend_Controller and Zend_View for its MVC because of its own custom patterns. But the implementation is quite similar to Zend Framework.) I’d noticed that MVC is followed in really nice way and provides very much flexibility for customization. It is very good example for enterprise application design.
Since the release of first preview version, the updates was being released frequently. With every release, Magento was shining more and more. The progress is incredible in very less time. Magento provides lot of exciting features like Multiple Stores and Websites, Google Checkout support, Single Page Checkout, Shipping to multiple addresses in one order and many more.
As a developer, the most impressive thing I found in magento is its flexibility for customization. As I have already mentioned in my previous post, magento is developed on Zend Framework and uses MVC architecture, which makes magento easier to maintain. Apart from that, magento also provides out of the box solution for customization. That means, magento can be customized as you need without modifying a single line of code in existing core modules. Instead, you can develop your own modules with specific configuration which overwrite the behavior of existing core modules. I love this way because it provides flexibility for upgrading magento to newer version.
So, on this occasion it really worths if they say:
Open Source eCommerce has officially evolved.
After investing 5 years in osCommerce based E-Commerce solutions, Varien is going to launch it’s own Open Source E-Commerce Solution – Magento.
As osCommerce is not much upgraded since long time, E-Commerce service providers are eagerly waiting for new solutions with more functionalities and features, Magento will have to pass through a difficult examination. At a first look at the website of Magento it seems that it would be better than any older E-Commerce solutions.
It is very hard to make users to switch from other products to your product. Because first question they would ask you is: “What’s better in yours than the current?”. Varien says something in answer of it on their Why Magento Page.
- No Constraints: Magento is much flexible so that you can create your online store exactly as your business model without any extra clutter or constricting design limits.
- Completely Scalable: Magento is completely scalable. So with growing of your site, you can easily manage more resources.
- Professional and Community Support: Magento offers professional reliable support, as well as the help of its passionate community.
- Smooth Integration: You can create your customized store according to your business model in Magento with easier integration by saving your time and resources.
- Cutting Edge Features: Magento provides many extra features like Produce Tagging, Multi-address Shipping, Product Comparison System etc. those are not yet provided by any other open source e-commerce solutions.
Magento is built on Zend Framework so it is clear that it will strictly follow MVC structure in it’s through out coding. Thus, it would be flexible for developers too. Let’s wait for it’s first Beta Release and examine it’s power trying it our self.
Apache, the most popular web server on earth, is distributed with a large number of modules, some of which are included by default when you compile the package, and some which aren’t. One of those that you can optionally compile is mod_vhost_alias, which I find particularly useful. It’s been available since Apache version 1.3.7.
Mod_vhost_alias adds dynamic virtual hosting. That is, we don’t need a VirtualHost declaration for each site. Using mod_vhost_alias directives, we can rewrite requests based on the IP address or the host name of the requested resource and return documents from the correct site. The advantages of this capability are that you can add any number of web sites without resorting to modifying and reloading the Apache configuration time and time again.
The extra directives available to us when mod_vhost_alias is present are: VirtualDocumentRoot, VirtualDocumentRootIP, VirtualScriptAlias, and VirtualScriptAliasIP.
Those ending with ‘IP’ use the IP address of the site requested, whereas the others use the host name. Since IP addresses are hard to come by these days, that is until IPV6, the 128 bit net addressing protocol becomes the norm, we’ll concentrate on using VirtualDocumentRoot and VirtualScriptAlias to maximize the number of sites we host under one IP. If you need to use the IP versions of these instructions, it shouldn’t be difficult for you to figure out since they work exactly the same way, but parse the IP of the requested host name instead.
Let’s start with an example from an imaginary configuration file…
CustomLog /www/logs/188.8.131.52.log vcommon
You’ll first notice the “UseCanonicalName Off” core directive. This is mandatory for our purposes as it tells Apache to use the host name as requested by the client rather than a value set in a ServerName directive or devising one if it’s absent. You’ll also notice that all our sites’ web documents must be in a sub-directory of /www/webdocs and all their scripts in a sub-directory of /www/scripts. For each site you added, you’d have to create these sub-directories and add a dns zone with the IP 184.108.40.206, but that’s all. Of course, you can use your own paths.
More important are the strange %-2 in the paths. This is a vhost instruction that allows us to extract a part of the host name and use it in the rewriting of the document path. The parts of the host name are determined by the ‘.’ it contains. Thus, www.xyzcgrf.com has 3 parts. ‘%-2’ means “extract the second to last part of the host name”. Again using our example, suppose we have a request for “http://www.xyzcgrf.com/hello.htm”…Since xyzcgrf.com resolves to 220.127.116.11, Apache would use our VirtualHost declaration and would replace ‘%-2’ with ‘xyzcgrf’, as the latter is the before last part of the host name. The document to return would thus be found at: /www/webdocs/xyzcgrf/hello.htm.
Continuing with our example, a request for the script “http://www.xyzcgrf.com/cgi-bin/test.cgi” would execute the script found at /www/scripts/xyzcgrf/test.cgi. Note that even if the requested url omitted the ‘www.’, it would still be rewritten correctly in my example. While the above example would serve you well for the dot-com and dot-net type domains, it would not fare well for country domains. Thus, a request for http://xfxfvc.co.uk and http://ghtrrd.co.uk would both translate to a path of /www/webdocs/co/, which is obviously not what we intended. There’s actually a whole slew of interpolation meta characters that we can use, so we’re not stuck. Here are some of them, using http://www.bogus.xyzcgrf.com as an example.
%0 : use the whole name [www.bogus.xyzcgrf.com]
%1 : use the first part [www]
%2 : use the second part [bogus]
%3 : use the third part [xyzcgrf]
%-1 : use the last part [com]
%-3 : use the third to last part [bogus]
%2+ : use the second and all subsequent parts [bogus.xyzcgrf.com]
%3+ : use the third and all subsequent parts [xyzcgrf.com]
You can also go nuts by extracting a part from a host name, then extracting a part from that part. In the latter case, the part would be a character or sequence of characters. We do this by using the format ‘%N.M’, where %N is our first extract and ‘M’ is the second. The ‘.’ is mandatory, but you omit the ‘%’ in the second. For example…
…if we put the url http://www.bogus.xyzcgrf.com through this directive, we get /www/webdocs/y/. That’s because %-2 extracted xyzcgrf, and the ‘2’ gave us the second letter ‘y’. I never needed this capability, but maybe you’ll find some use for it. If what truly interests you is extreme url rewriting, there’s another module which can allow you to slice and dice urls any which way, called “rewrite_module”. We’ll explore its possibilities in the near future.
In order to smoothly rewrite paths for our xfxfvc.co.uk type host names that our first example fumbled with, we need to assign them a different IP in a separate VirtualHost declaration. Our vhost directives in that one would look like this…
Thus, we’d extract the xfxfvc rather than the ‘co’. I believe in keeping things simple, so I avoid using anything but the %- interpolations, as the rightmost part of any host name is reliable whereas the leftmost isn’t. One drawback to using vhost_mod is that you can’t have individual log files for each site sharing the IP. Instead, all will log to the same files. The way we compensate for that is by creating a special logging definition that will include a field that registers the domain of the request. Thus, for example, the instruction…
LogFormat “%V %h %l %u %t “%r” %s %b” vcommon
Appears somewhere in our configuration file. The “%V” tells apache to log the host name requested by the client [See: mod_log_config].
With the LogFormat we’ve just defined, your log might look something like this…
www.rtzxfgh.com 18.104.22.168 – –
“GET /bogus.htm HTTP/1.1” 200 0
www.ouwqagxh.com 22.214.171.124 – –
“GET / HTTP/1.1” 200 0
In order to generate individual traffic reports for each site sharing the log file is a statistical tool that can parse such a log.
Some useful links you can follow to get further knowledge on the subjects discussed today:
Nowadays, object oriented programming (OOP) is quickly taking place over the traditional procedure oriented programming (POP). Success of the modern programming languages like C# and Java is obviously because of OOPs Power.
As all the OOP languages use CLASS or similar data structures for Object Oriented Programming, we have considered that without a “CLASS”, OOP is not possible.
With the same idea in my mind, I’d briefly gone through the code base of “Drupal” – One of the most popular open source content management system and framework built with PHP language. I often read and heard many praise about the power of Drupal, but after the first look at the code base, I amazed that Drupal doesn’t use a single Class in it’s code base! Whole Drupal code base is based on just functions. As PHP, with which programming language Drupal itself is built, is also implementing many powerful OPP features, I could not understand why Drupal is not using these features!
As I’d not seen the keyword ‘class’ in Drupal code base, I evaluated Drupal as non-OOP as many programmers do. And that was my mistake! Even though, Drupal doesn’t contain any class like data structure, it is still Object Oriented. I realized this fact after details study of Drupal.
Actually, the OOP concept is not based on uses of data structures like CLASS. It is based on the fundamentals of features like Objects, Abstraction, Encapsulation, Polymorphism, Inheritance etc. If these fundamental features are included in programming then it can be considered in OOP.
Drupal covers all these features without classes. I also realized that the power of Drupal is hardly depends on this programming structure only. The way, how the hook system has been implemented in Drupal would never been possible with the use of Classes.
See more details about how Drupal implements Object Oriented Programming (OOP) without using Classes, visit: http://api.drupal.org/api/HEAD/file/developer/topics/oop.html