Posts tagged 'zf'

Debugging Zend Framework unit tests with Xdebug and NetBeans

published on July 24, 2011.

I’ve spent this weekend hacking on some unit tests for Zend\Dojo and I ran into an issue where I need Xdebug to, well, debug. Note, that this is not for debugging a Zend Framework application, but for debugging Zend Framework itself. I am using Netbeans + Xdebug to debug regular code, but debugging unit tests was something completely new for me. Turns out, it’s not entirely different from “regular” debugging.

Greatest help to figure out this was Raphael Dohms’ blog post "Debugging PHPUnit tests in Netbeans with Xdebug". Almost worked out fine, but Netbeans complained about a missing index file and the autoload of files was… not really working. After a bit of poking around, the solution was to go to File -> Project Properties -> Run Configuration and set the “Index File” to /path/to/zend_framework_2/tests/_autoload.php - no more missing index file and the autoload works too!

Starting the debug session stays the same as explained in Raphael’s post: click “Debug project” (CTRL+F5), go to the terminal and just type something like:

robert@odin:~/www/zf2/tests$ /path/to/phpunit-debug Zend/Dojo/DojoTest.php

Netbeans will pick up the connection and debugging can start!

Happy hackin’!

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.

Loading custom module plugins

published on July 20, 2010.

OK, here’s a quicky one from the office :P

I was trying to load a Front Controller plugin which resides in app/modules/my_module/controllers/plugins/ and not in the “usual” lib/My_App/Plugin/. I want this plugin to be called in every request and I want the plugin file to be under it’s “parent” module.

Here’s what I did: added the path to the plugin and it’s namespace to the Zend_Application_Module_Autoloader as a new resource type and then just register the plugin in the front controller in an other _init method.

Code is better, here’s some:

<?php
class News_Bootstrap extends Zend_Application_Module_Bootstrap
{
    /**
     * Autoloader for the "news" module
     *
     * @return Zend_Application_Module_Autoloader
     */
    public function _initNewsAutoload()
    {
        $moduleLoader = new Zend_Application_Module_Autoloader(
                                array(
                                    'namespace' => 'News',
                                    'basePath' => APPLICATION_PATH . '/modules/news'
                                )
                            );

        // adding model resources to the autoloader
        $moduleLoader->addResourceTypes(
                array(
                    'plugins' => array(
                        'path' => 'controllers/plugins',
                        'namespace' => 'Controller_Plugin'
                    )
                )
            );

        return $moduleLoader;
    }

    public function _initPlugins()
    {
        $this->bootstrap('frontcontroller');
        $fc = $this->getResource('frontcontroller');

        $fc->registerPlugin(new News_Controller_Plugin_Scheduler());
    }
}

If anyone knows a better way for doing this, please do share it with me.

Now back to work. Cheerio.

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