Category Archives: PHP

Some hate over Cake’s i18n

I'm really fond of CakePHP's principles, but I'm too tired of its i18n features. For some reason internationalization, although one of the really major requirements for every framework or CMS, is implemented poorly in most of the systems I've worked with. Django had few disadvantages (but few strong points as well) with its django-multilingual, and here it comes Cake with its toolkit for multilingual applications.

Comparing with few Java frameworks + CodeIgniter, I'm pretty aware of using locale-based apps with few languages for dynamic content. It's ugly as hell most of the times.

The beauty of Cake is mostly its 'convention over configuration' and dynamic admin panel generation. Admin panel is pretty neat, although there is no CMS-alike functionality and one should translate/adapt the admin for a project every single time. This is a problem that savant is taking care of, creating a multi-functional and reusable administrative panel. However, nobody has ever thought about creating something advanced like in Django's admin - data filters, field hiding, form populating module etc. Everything is hardcoded (actually spitted from the code generator, which is fine, automagic should be based on something and code must be there at some point) but not flexible at all except if you don't rewrite your admin generator.

The other thing is the multilingual content.

Designing i18n stuff in CakePHP is done by Translate behavior. You define your languages in the core file (or bootstrap in older versions) and you use it for localization. Also, your models actAs Translate behavior and you need to define the fields to be translated.

What is missing here is that because of the database normalization, these fields in question are not in the model table, but in the translation one. For that matter you cannot create a multilingual views for add/edit/view/index, because you miss some of the important fields (usually such as name/content that need to be translated in other languages as well). Also, relations in the previous abstraction level with translate tables are done transparently and using find() with translated fields is pretty hardcore. 

Croogo is a pretty neat CMS based on Cake. Translation there is modified by Fahad and he had done few changes in the main mechanism. Also, in order to add some translation, you do the following:

  • enter the base material and submit
  • view the material
  • click on a 'translate' button
  • select a language to translate in
  • fill data for the language in question

This one ain't bad, but it requires 5 steps for adding one translation. What if we have 5 languages?

Django's multilingual module is better in my opinion. It iterates over the languages and it outputs all translatable fields for every language in one page. When you add content, you could insert the whole data in one window or skip the unnecessary details at first. That's a better one. However, Django has a different approach (the one that jose is taking into consideration - actually creating database over the models and not MVC over a database). This way connection between fields for translation could be predefined in a smarter way. 

Why should all of that be so hard? Cake needs to be rapid and DRY and KISS, but admin needs to be changed every time, translation is tough to configure, administration is not straight-forward with its acl (and tens of auth modules). Croogo does a good job with putting all of that in one package, but it's too heavy sometimes (Cake is not the fastest framework after all). I really need there is a place left for a good i18n module, some killing-auth lib and a better convention definition for even more rapid dev. Digg DZone Facebook Google Google Reader Magnolia reddit SlashDot Technorati

First week with Croogo


It's been my first week using Croogo - a CMS platform based on CakePHP and created by the Bangladesh developer Fahad Heylaal. Recently I've been looking for a next level platform in order to decrease development time and reduce wasting time for writing standard things from scratch such as menus, user controls (Auth+ACL), multilingual options etc. What Croogo does is delivering all this in a way upper lever. 

Croogo itself works out some general concepts in a way that we know from other popular systems. Overall look & feel in admin panel seems like the one that we've seen in WordPress. The node-based content (with ability to create new types from the admin) is a well known practice in Drupal - CCK. The core is, of course, CakePHP. I'm quite sure I could find more similar characteristics but the point is that the system is stable enough and flexible as well for other people to develop beyond and contribute as well.

I'll share some notes and issues from my first steps. Wiki is the first place to stop by. 

Theming - themes could easily apply to a Croogo website because there are no special functions needed here. Of course you could (and probably should) use helpers in views to build a better and well structured website. Adding blocks/menus via helpers is also 'a must'. The point is that you could easily take a free html template (or a sliced PSD design) and adapt it in Croogo in no time. 

Themes are installed in app/views/themed - theme name, layout, css/img etc and yml file for configuration.

i18n - multilingual websites are what's worth to me. I had to release a website in 2 languages, 4 types of users, contact (registration) form, dynamic menu. Everything is already here if you know how to use it. I still do translate the Bulgarian version of Croogo (admin panel, static messages etc). The Translate plugin allows you to add different languages and translate every node/menu/link or a custom type of yours. That frees a room for your powerful multilingual website. Just enable the translate plugin and you'll see the correct button. Note: please use version 1.3.2 and above because of crucial bugs in 1.3.1 translations.

User management - Auth + ACL. Each controller+action has a granular permission to access from every role you have specified. Fair enough.

Custom stuff - There are helpers, behaviors and components meant to be reused and inherited. Just have a look at what Croogo gives you (the additional config stuff, the new helpers/plugins etc) and you could easily attach your custom code here. If you add actions to your existing controllers (or add controllers) be sure you've refreshed your permissions table in order to give rights to certain roles here.

Hacky: reset admin password

I've migrated 1.3.1 db in a 1.3.2 website and I misgenerated my admin password. I tried the forgotten password feature which doesn't work on local accounts. However, the activation key is in the database. Suppose we're on a local server, you could copy activation key and visit:


and then your password is free for you to reset. Digg DZone Facebook Google Google Reader Magnolia reddit SlashDot Technorati

Access beforeFilter set variable in controller (CakePHP)

In a CakePHP application we could define an intermediate abstraction of a controller called AppController. The concept is having a Controller class defined by Cake core, writing controllers for our project and defining app_controller.php file for our common functions repeated in every controller.

In this case we usually use beforeFilter or beforeRender method in AppController in order to define some data to be transferred automatically in every controller. More about app_controller and callback functions.

When a variable is set in beforeFilter, it could be used with it's name later in CakePHP views. For example:


  2. $this->set('products', array('P1' => 'Pizza', 'P2' => 'Water'));


Any view later:


  2. <?php echo $products['P1']; ?>

But that variable could not be accessed directly in a controller function. In this case we could use viewVars array in order to access beforeFilter set variable in other controller method, which solves our problem: 


  2. function test() {
  3. $products = $this->viewVars['products'];
  4. $product_1 = $products['P1'];
  5. }
  6. Digg DZone Facebook Google Google Reader Magnolia reddit SlashDot Technorati

Easy AJAX calls in CakePHP

 CakePHP is a great framework for rapid development of web based applications that serves well the principles of DRY (Do not Repeat Yourself). However unlike other web frameworks, CakePHP is not (and probably will not) fully AJAX based (for instance, you could check the list of PHP Ajax frameworks or try some Java/Python implementations such as Google Web Toolkit and Pyjamas). 

In no way the statement above means that you cannot do some flexible and dynamic client-side calls into your CakePHP site. You could freely use plain Javascript in your views, use the JS helper of CakePHP or add some prototype/jQuery library and take advantage of its features. Beyond all that possibilities you could use one more helper of Cake - the AJAX helper. The AJAX helper provides an intuitive interface for maintaining some standard task with only few lines of code.

Some of the methods that you can use with the Ajax helper:

  • link
  • remoteFunction
  • form
  • observeField
  • autoComplete
  • drag & drop

and few more that you could find in the link above. 

The standard 1.2 implementation expects prototype and scriptaculous in order to run properly. However you could easily replace them with jQuery (and jQuery UI) libraries. Some examples on that: Digg DZone Facebook Google Google Reader Magnolia reddit SlashDot Technorati

How to hide load time comment for AJAX calls in CakePHP

 CakePHP puts some debug info after page load including the load time of the page. Even though it is an HTML comment line, it does affect returned data for AJAX calls (and not only). 

If we do return JSON, we could set the returned type for json-like and then json_encode the data using the $this->autoRender = false; clause. However, if we expect some specific data (like a boolean yes/no result), we would have problems with the debug feature of CakePHP.

So we could disable the debugging feature of Cake only for AJAX calls adding this statement to the beforeFIlter() action of the app_controller.php:


  1. if ( $this->RequestHandler->isAjax() ) {
  2. Configure::write('debug',0);
  3. } Digg DZone Facebook Google Google Reader Magnolia reddit SlashDot Technorati

Motoclub.BG – our new moto project


We delivered Motoclub.BG and now it's available and accessible. The web portal is an online version of a magazine for motorcycle sports and vehicles, ATVs and others. As the bikers' favourite music is rock/metal, breaking news on concerts and live events in clubs are posted there as well.

The portal has few interesting sections for magazine online overview. You could find news and specialised articles, moto calendar with coming events, catalogue with specifications for different brands and so on. Filters and archives provide searching via keywords or month/year ranges. RSS feed on latest news is staying in the left column, next to the invitation to the Facebook group of the website.

The project is CakePHP based with MySQL database behind. I've implemented a few custom solutions on user management and RSS aggregation which I'm going to describe later. Digg DZone Facebook Google Google Reader Magnolia reddit SlashDot Technorati

CodeIgniter advanced search implemented


I had to implement advanced search algorithm which supports pagination and multiple open sessions at one browser. My main issues were the following:

  • how am I able to support the pagination?
  • where am I going to save the search parameters?
  • what happens when I open 3 tabs and search simultaneously?
  • when am I going to flush the recorded results?

It was clear that I had to persist the data to each page. My first idea was saving the params into flashdata() (the temporary 1-time session or rather request forwarding). It was good solution if you restrict yourself to one tab only and navigation only page-to-page. The problem was my 'details' page where parameters got lost. As well as the 'back' button, too.

CodeIgniter itself doesn't allow GET queries in the URL. Actually it does, but not by default and it's bad practise to do it.

Therefore I decided to resend the flashdata on all required pages. But what happens if you open few tabs at the same time? All search results get mixed up and all tabs get the data from the last query called.

Another popular trick is persisting into multidimensional $_SESSION array - the name (unique) of the session and all the params. I actually can't think of a reasonable way to flush the sessions regularly and manage big sessions (cookie limit is 4K after all).

So we decided to create a new DB table for sessions. There we save all the params as serialized array. We use both the session unique ID and the page number when navigating.

Code snippet and explaining in the CI forums - How to implement complex search Digg DZone Facebook Google Google Reader Magnolia reddit SlashDot Technorati