Robert Basic's blog

Posts Tagged 'zend framework'

Using the new autoloaders from Zend Framework 1.12

by Robert Basic on June 22nd, 2012

The latest, and last, release of the Zend Framework 1.x series is just around the corner as ZF 1.12.0RC1 was announced this week. As I still have projects running ZF1 I thought about giving the most interesting new feature (for me) a spin - the new autoloaders which are backported from ZF2.

Note: the code below was updated to work with ZF 1.12.0RC2. Should still work with RC1, too.

I decided using the classmap autoloader as the main autoloader, and the good ol' standard autoloader as the fallback autoloader. For the classmap autoloader to work we need to create a classmap. ZF1.12 comes with a tool, located in the bin directory, called classmap_generator.php, which will generate the classmap for us:

$ cd /path/to/project/library
$ php /path/to/zf1.12/bin/classmap_generator.php 

This will generate a PHP file called autoload_classmap.php in the library directory and it will have classname - filename mappings of the classes/files from that directory.

Next, need to change the index.php a bit to tell ZF to use the new autoloaders:

// normal setting up of APPLICATION_PATH and other constants here ...
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));
require_once '../library/Zend/Loader/AutoloaderFactory.php';
// As of ZF1.12.0RC2 the Zend prefix is not autoregistered
// with the standard autoloader, so we need to require explicitly
// the ClassMapAutoloader.php
require_once '../library/Zend/Loader/ClassMapAutoloader.php';
Zend_Loader_AutoloaderFactory::factory(
    array(
        'Zend_Loader_ClassMapAutoloader' => array(
            __DIR__ . '/../library/autoload_classmap.php',
            __DIR__ . '/../application/autoload_classmap.php'
        ),
        'Zend_Loader_StandardAutoloader' => array(
            'prefixes' => array(
                'Zend' => __DIR__ . '/../library/Zend'
            ),
            'fallback_autoloader' => true
        )
    )
);
// set up Zend_Application as normal here ...

and that's about it - the autoloader will load classes from the classmaps, but if it fails to do so, it will fall back to the standard autoloader.

Stripping out require_once calls

The Zend Framework manual has a section on how to improve performance of the framework itself, and one of the suggestion is to strip out the require_once calls from the library. I had to alter that find/sed command combination a bit in order to make it work with the classmaps:

$ find . -name '*.php' \
  -not -wholename '*/Application.php' \
  -not -wholename '*/Loader*' \
  -print0 | xargs -0 \
  sed --regexp-extended \
  --in-place 's/(require_once)/\/\/ \1/g'

If I'm not wrong in reading my "debugging" echo statements, the standard autoloader gets called only once - to load the classmap autoloader itself - everything else is loaded via the classmaps. Pretty cool.

Happy hackin'!

Tags: zend framework, autoloader, classmaps, performance.
Categories: Development, Programming.

Zend Framework full page cache tips

by Robert Basic on February 11th, 2012
When I started rewriting this blog, I knew from start that I want to use Zend Framework's full page caching, as, I think, that's the best cache for this purpose. Not much going on on the front end, much more reads than writes, no ajax or any other "dynamic" content. While implementing the cache, I ran into two issues.

The first problem was that the cache files were created, but they were never valid - on each request a new cache file was created. It was a noob(ish) mistake - I had two calls to Zend_Session::startSession() in my code, which made the session ID always to change which made the cache validity test to fail. Removed the second call and all was well. Or so I thought...

I moved the code to staging to run some final tests before pushing it live, but the cache started failing again. This time the cache files weren't even being created! The same code works on my machine, fails on staging. The only difference was that I had turned off the loading of Google Analytics in the development environment. But... that can't be it, right? Wrong. On every request the values of the GA cookies are different. The full page cache has a set of settings which dictates what variables are taken into account when creating an ID for the cache: make_id_with_xxx_varialbes where "xxx" is one of get, post, files, session, cookie and by default all are set to true. Setting make_id_with_cookie_variables to false made the cache to disregard the always changing GA cookies which made the cache start working again.

So, if Zend Framework's full page cache starts failing for you, check the contents and behaviours of all the variables - get, post, files, session, cookie - and play around with the cache settings until it starts working again.

Happy hackin'!
Tags: zend framework, full page cache, caching.
Categories: Development, Programming.

A Zend Framework 2 EventManager use case

by Robert Basic on October 19th, 2011

With Zend Framework 2 beta 1 released yesterday and some free time to spare, I decided to finally try and tackle one of the "scariest" additions to the Zend Framework - the EventManager component. Now, I won't go into details about this whole event voodoo, Matthew already did that. Twice.

Basically, this allows us to have one piece of code to trigger an event and to have one or more listeners listening to this event. When the event gets triggered, the listeners are called and then we can do *something*, like caching or logging. Logging or caching. Caching. Logging...

See, that's my problem. All the event examples stop at logging and caching. Truly there must be some other example for which this event stuff can be used for. (Yes, I know. The whole dispatch process is now event driven or whatnot in ZF2, but I need event examples in my application, not in the framework.) I don't claim I found a perfect example for the events, but I tried.

The problem

One of the most "repetitive" places in my code I found is the save method in my models. Pass an array of data to it, possibly do something with that data, validate it, persist it, maybe do some more data mangling, return true/false to the caller. Over and over again, but just with enough difference between different models that there is actually no double code to pull out to an abstract class or some such.

Say, for example, we have a Post of some sort. It has a title and a slug created from the title. Standard stuff, nothing fancy. For the Post to be valid, it needs to have both the title and the slug set.

Now, without the EventManager, the save method could have a similar flow:

  • call the save method, passing in the data array
  • check if the data array has a slug set, if not, create one from the title
  • validate the data array, to make sure both title and slug are properly set
  • save the post

As I said, pretty standard stuff, so I'll assume you can imagine that piece of code in your head (read, I'm lazy to write it). The problem: the save method is stuffed with data preparing and validation code.

Using the EventManager

This is where, I hope, the EventManager can help. Call the save method and, just before the persist call, trigger a "pre-save" event and then persist the data. Attach two listeners to this "pre-save" event; the first will do the data preparation, the second will do the validation. There, done. Now the save method doesn't have that unneeded code around it and can be pulled out to an abstract class, all that is in the event listeners.

Let's see some code:

<?php

// This is the Post object

class Post
{
    protected $events = null;

    public function events()
    {
        if ($this->events === null) {
            $this->events = new Zend\EventManager\EventManager(__CLASS__);

            $this->events->attach('save', array('SlugifyPost', 'slugify'), 100);
            $this->events->attach('save', array('ValidatePost', 'validate'), 90);
        }

        return $this->events;
    }

    // this method can be pulled out to an abstract model class
    // and reuse it for all the models that extend it
    public function save($data)
    {
        $this->events()->prepareArgs($data);
        $response = $this->events()->trigger('save', $this, $data);

        echo 'data saved! ' . json_encode($response->last());
    }
}

I just set a "save" event to be triggered and attached two listeners to that event, the slugify and the validate methods. When the save method gets called, the event is triggered and the EventManager calls our listeners. One fairly important point here is the prepareArgs method call, which prepares the event arguments in such way, that when these arguments (the $data array in this case) are modified in one listener, this modification is reflected for the other listeners, too. If you don't want to modify the arguments in the listeners, this call can be omitted. As for the rest of the code, it's explained in Matthew's posts and in the ZF2 docs.

And here's how the slugify method modifies the data:

<?php

class SlugifyPost
{
    public function slugify($event)
    {
        $data = $event->getParams();

        $event->setParam('slug', strtolower(str_replace(' ', '-', $data['title'])));

        return $data;
    }
}

Calling the save method itself remains as it was before introducing the EventManager, which means I could add this to my models without changing the API and not break anything! Genius! Theoretically, anyway...

<?php

$post = new Post;

$values = array(
    'title' => 'My post'
);

try {
    $post->save($values);
} catch(\InvalidArgumentException $e) {
    echo $e->getMessage();
}

You can find this complete example on Github.

Thoughts?

So, what do you think? Does this approach makes sense to you? Do tell. I kinda like the idea, but time will tell in the end, as always.

Happy hackin'!

Tags: eventmanager, events, listeners, zend framework, zf2.
Categories: Development, Programming.

Helping out with Zend Framework 2

by Robert Basic on July 27th, 2011

OK, here are some tips and resources so you can start helping out and contributing to Zend Framework 2.0 :)

First, here's a nice wiki page with some links on how to start with Zend Framework 2. Be sure to check out the Zend Framework 2.0 patterns tutorial slides and the webinar on the same topic (you need to log in to watch it, but the registration is free, so no excuses).

The development is happening on github, so that's a nice starting point to get your hands dirty with some code. On the wiki there's a Zend Framework Git Guide to get you started. Pay close attention to the "Working on Zend Framework" chapter.

As Matthew noted in this thread you can:

Fix unit tests!

Once you forked and cloned the github repo, cd to the zf2/tests directory and simply make the tests there pass! Of course, there are *a lot* of tests there, so you might want to start with something easy and small; for example I picked the Zend\Dojo component :P

Anyway, once you're in the tests directory, just type:

robert@odin:~/www/zf2/tests$ phpunit --verbose Zend/Dojo

or:

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

and watch the tests pass or fail. If they pass, good, if they fail, try to fix them and make them pass! I tell you, it's fun! By using the "--verbose" flag you'll get more (helpful) info about the tests.

Port Zend\Service

I haven't look into it yet, so just quoting from the mailing list:

* Port Zend\Service classes that interest you to namespaces, new
exception usage, etc.

but I believe if you start from the tests for the services too, you should be all set!

Port ZF1 patches to ZF2!

Even if ZF2 is under development, ZF1 is still taken care of: that means, a lot of patches are present in ZF1 which are not in ZF2 (cause they were added after ZF2 branched off of ZF1, obviously...). Some patches will probably not be needed thanks to the rewrite, but some patches will be! So head over to the issue tracker, search for recently (where recently is, say... this year?) resolved and fixed issues, see if they have a patch attached, if yes, open the patch, see if that patch is already in ZF2, if not, add it, issue a pull request, move on to the next issue.

Play with the existing code!

The official Zend Framework Quickstart is also on github, with different features on different branches! Fork it, clone it, test it, make it, break it, fix it... I myself am rewriting a ZF1 based application to ZF2, so you can have a look at that too!

I have also created a few gists about using the new helper loaders/brokers/plugins.

That's it for now, if I remember/find anything else, I'll update the post. Of course, if you have to add something, fire away! :)

Happy hackin'! :)

Tags: contribute, contributing, help, zend framework, zend framework 2.
Categories: Development, Programming.

Debugging Zend Framework unit tests with Xdebug and NetBeans

by Robert Basic on July 24th, 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'!

Tags: netbeans, tests, unit testing, xdebug, zend dojo, zend framework.
Categories: Development, Programming, Software.