Archive for the 'Programming' category

Grouping Zend Framework controllers in subdirectories

published on April 16, 2011.

Thanks to a discussion on the Zend Framework mailing list I learned about a new feature, a feature that allows for grouping action controllers in subdirectories! Well, this is more of an unknown and undocumented feature than new, as it is the part of the framework for at least 3 years.

Subdirectories example

Why am I so hyped about this? Because it allows for better code organisation on larger projects. Heck, it might be useful on smaller ones too. For example, if a module Foo has both a backend and a frontend, what I was doing so far was to have the file and class names prefixed with an Admin prefix for the backend files and no prefix for the frontend files, so I can actually see what file belongs where. This can go out of control quite easily.

On the other hand, with this grouping of controllers I can make an Admin directory and just place all the backend related controllers there. Easy, clean and much more easier to see what’s where. In my opinion at least :)

Example

Best part is that this feature requires no additional configuration. Create a subdirectory under the controllers directory and place the controller file under that subdirectory. In that pretty screenshot image you can see a FooController.php in the directory called Sub; the class name in that example is Sub_FooController and is accessible via the sub_foo/controller URI. The corresponding view files should be placed in views/scripts/sub/foo/ directory.

A few notes on this:

  • the subdirectory separator in the URI is the underscore and not the slash.
  • The subdirectory name is uppercase: Subdirectory, not subdirectory. In the URI it's lowercase.
  • The view directories for these subdirectories are lowercased, and not uppercase.

The uppercase subdirectory sounds weird, but meh. If needed, the underscore can be “changed” to the slash with a route.

I think the level of possible subdirectories is not limited, but I really can’t see an use-case for more than one subdirectory.

Happy hackin’!

A hack for Zend Framework's translated route segments

published on April 14, 2011.

Today I came across on a little “gotcha” when using the translated route segments in a multilanguage web site and thought about sharing the dirty little hack I used to get around it.

Note: I"ve changed the title on this post. The first one sounded a bit like that ZF code itself contains a hack and not that I wrote a hack to solve a particular problem of mine. Sorry about that.

The set up of the router and translator is done “by the book”, err, by the manual.

The problem

The web site’s default locale, language, is English. If the user has no locale in the session/cookie, she, or he, will get the English version of the web site. If, for example, the user’s first visit is on the http://example.com/news URL, there’s no problem, the router will route that URI to the news module, index controller, index action and the user will get the news, in English, because the default locale is English.

But! If the user’s first visit is on the http://example.com/vesti URL (“vesti” is “news” in Serbian), the router can’t route that because it depends on the locale and the default locale is English and not Serbian, thus directing the user to the 404 page. Of course, that is not good, because the requested URL is perfectly valid, just in a different language and the user should get the news in Serbian and not an error page.

The solution dirty hack

I hacked up a front controller plugin which in the postDispatch hook, if needed, changes the web sites locale to Serbian and dispatches the request all over again. If all goes well, the router will now route correctly the URL and the user will get the content.

<?php

class App_Plugin_TranslatedRoute extends Zend_Controller_Plugin_Abstract
{

    public function postDispatch(Zend_Controller_Request_Abstract $request)
    {
        $request = $this->getRequest();
        $action = $request->getActionName();

        if($action != 'error') {
            return false;
        }

        $translator = Zend_Registry::get('Zend_Translate');
        $locale = $translator->getLocale();

        // English is the default
        // if the current locale is not the default, we might have been here earlier...
        if($locale != 'en') {
            return false;
        }

        $translator->setLocale('sr');
        Zend_Registry::set('Zend_Translate', $translator);

        $front = Zend_Controller_Front::getInstance();
        $front->getResponse()->clearBody();
        try {
            $front->dispatch();
        } catch(Exception $e) {
            // Haven't figured out a nicer way to redirect the user to the error controller
            header("Location: " . $request->getRequestUri());
            exit();
        }
    }
}

The hack for the hack

That terrible, ugly, I-should-have-never-written-it piece of code at the end, the one with the header(“Location… code in it is a hack for a hack. If in the second dispatching some error occurs, which at this point is a “valid” error, the user should be directed to the error controller/action. I haven’t figured out a nicer way to do this. I tried several different things like doing the dispatch for the 3rd time, setting the request’s controller/action to the error controller/action and whatnot but to no avail, every time I just end up a with blank page (yes, with error reporting turned on. Y’know, I’m one of those nuts who develops with E_NOTICEs on).

If anyone has some tips on fixing this problem in a more cleaner way, please do share them.

Happy hackin’!

Playing with Zend Framework and Dojo

published on March 02, 2011.

Yesterday there was some talk on Twitter including Zend Framework and Dojo. I didn’t quite follow it through, something about why Dojo and not jQuery, it’s not that popular blablabla. Anyway, who cares? We have Zend_Dojo, we have ZendX_Jquery. I’m using ZendX_Jquery, but only as far as setting it up and loading jquery and jqueryui via the view helpers. Tried to use it on forms, to use tabs and whatnot, but in the end it was easier to write up a separate javascript file and do the jquery stuff there. But, I’ve never used Zend_Dojo before. Guess I was a bit scared away with all that dojo, dijit, dojox stuff… So, last night, being bored and all, I’ve decided to try and use it. Oh boy. How wrong was I for not diving into it before. OK, so far I’ve created only one form with dojo, but damn it’s good.

In short: set up the Zend_Dojo view helpers, pick a theme, make the forms extend Zend_Dojo_Form, change the elements from Zend_Form_Element_* to Zend_Dojo_Form_Element_*, if needed add/tweak some attributes and bang! the form is all sexy with nice colors & rounded borders & (error) messages in a nice little tooltip. And I haven’t wrote a single line of javascript. Not.a.single.line. Magic, I like it.

Setting it up

All I did was to set up dojo is:

<?php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {

    public function _initViewHelpers()
    {
        $this->bootstrap('layout');
        $this->_layout = $this->getResource('layout');
        $this->_view = $this->_layout->getView();

        $this->_view->addHelperPath('Zend/Dojo/View/Helper','Zend_Dojo_View_Helper');

        $this->_view->dojo()
                        ->enable()
                        ->setCdnBase(Zend_Dojo::CDN_BASE_GOOGLE)
                        ->setCdnVersion('1.5.0')
                        ->setCdnDojoPath(Zend_Dojo::CDN_DOJO_PATH_GOOGLE)
                        ->addStyleSheetModule('dijit.themes.claro')
                        ->useCdn();
    }

and then just called echo $this->dojo(); in the layout and added class="cairo” to the body element. I think this body thing can also be done via the helpers. The biggest struggle I had with the theme. Where do I download it? There’s no “download theme x” on the dojo website. How do I set it up? What is this madness? Then I realized it can pull not just the javascript files from the CDN, but also the CSS and images! Very cool.

A simple form

Next step: spice up the forms with Zend_Dojo_Form:

<?php
class My_Form extends Zend_Dojo_Form
{
    public function init()
    {
        $this->addElement(
            'ValidationTextBox',
            'title',
            array(
                'label' => 'Title:',
                'missingMessage' => 'You have to enter something', // overriding the default "This value is required."
                'promptMessage' => 'Enter a title', // on focus
                'invalidMessage' => 'Type some random characters, 3 min, 100 max', // error message for the failed regExp
                'regExp' => '.{3,100}', // regexp for validation
                'required' => true,
                'validators' => array(
                    array(
                        'validator' => 'StringLength', 'options' => array(3, 100)
                    )
                ),
                'filters' => array(
                    array(
                        'filter' => 'StringTrim',
                        'filter' => 'StripTags'
                    )
                )
            )
        );

With these ~20 lines I’ve got some basic client side validation with a pretty nice look and feel to it while still having all of the Zend_Form power to do the validation and filtering on the server side. Still need to figure out what those “constraints” are and how and for what to use them (they’re in the ZF manual, so they gotta be good for something), how to add for example a dojox.validate.isEmailAddress validator to the element, but for starters, this is quite impressive.

Besides this, I’ve also played with Zend_Dojo_Form_Element_Editor which is a WYSIWYG editor, extended Zend_Dojo_Form_Element_Button to create my own ResetButton (for some odd reason there is no reset button in Zend_Dojo), played around with the decorators… But that’s for some future rambling, gotta go to work now.

In the end, I feel stupid for not using Zend_Dojo before, well, Zend_Dojo_Form at least, but I definitely will be from now on. Here’s to hoping that it will be included in Zend Framework 2, too :)

Happy hackin’!

Tags: dojo, form, zend framework, zend_dojo, zf.
Categories: Programming.

A real gem - PHP_CompatInfo

published on December 27, 2010.

Last night I was pondering how nice would it be to have a tool of some sort, that would simply spit out what version of PHP does my app require. Something like: here are my .php files, what PHP version and/or extensions do I need for it? First I thought about jumping right in and writing it myself, but hey, this kind of a tool sounds way to useful not to be written already! After a bit of a googling there it was: PHP_CompatInfo. A nice PEAR package that can tell me everything I want about my code and even a bit more.

It tells what’s the minimum overall PHP version needed, all the PHP extensions used and the PHP versions and extensions file by file.

Installing PHP_CompatInfo is easy: pear install php_compatinfo and that’s about it. Using it isn’t much harder:

<?php

require_once 'PHP/CompatInfo.php';

$source = '/home/robert/www/Zend/';

$driverType = 'xml';
$driverOptions = array();

$info = new PHP_CompatInfo($driverType, $driverOptions);
$info->parseDir($source);

Include the main PHP_CompatInfo file, set the path to the file or directory you want to check and then just run it. By default it’ll just var_dump the results, which is pretty much OK for a few files and directories. For a library like Zend Framework, I found the XML output to be the best. Besides the var_dumping and XML, there are other options for the output like CSV, a simple HTML table and Text, which is used when using the CLI. Oh, right, you can run it either from the console or from your web browser. PHP_CompatInfo’s documentation is very well written and describes all part of it, so I won’t be bugging you with that.

So yea, this little gem goes right into my box of must have tools.

Passing arguments to custom slots in PyQt

published on November 30, 2010.

While hacking on ape, I came to a situation where I need to pass some arguments to a custom defined slot. The slot is being called from different signals, one where the argument is passed by PyQt itself and a second one where I need to programmatically pass the argument to the slot.

First I tried with something like:

action = QAction("My action", parent)
action.triggered.connect(my_slot(my_argument))

which ended in an error: TypeError: connect() slot argument should be a callable or a signal, not ‘NoneType'

After a bit of poking around I passed a lambda function to the connect() method:

action = QAction("My action", parent)
action.triggered.connect(lambda arg=my_argument: my_slot(arg))

Works like a charm.

Also this is my first try to use github gists as a way to embed/highlight code. Hope it’ll work out.

Happy hackin’!

Tags: ape, lambda, pyqt, python, signals, slots.
Categories: Programming.
Robert Basic

Robert Basic

Software developer making web applications better.

Let's work together!

I would like to help you make your web application better.

Robert Basic © 2008 — 2020
Get the feed