Deprecated Behaviour

The inane, sometimes insane, ramblings from the mind of Brenton Alker.

The Silver Lining of the ReadWriteWeb/Facebook Login Debacle

The furor surrounding the amusing chaos that ensued following ReadWriteWeb’s article on Facebook Connect has been interesting, in that it brings attention to developers assumptions about the way users interact with their products.

There have been articles debating who is the cause of the confusion; whether it’s the Developers or the Users that need to try harder.

But in all this, what I think has been missed is the success of Facebook Connect. There are hundreds of comments on the ReadWriteWeb article from users who failed (for whatever reason) to find their way to Facebook, yet still managed to use Facebook Connect to leave a comment.

Sounds like a testament to the usability of Facebook Connect to me!

Bootstrapping the Doctrine 2.0 Autoloader in Zend Framework

Please Note: This post was based on the Alpha release of Doctrine2. They have since added Doctrine\Common\IsolatedClassLoader which (among other things) doesn’t automatically register itself so we no longer have to unregister it, making things much easier.

Doctrine 2.0 looks like it might finally be the ORM framework I have been seeking for PHP. While the older versions of Doctrine provided great functionality, they were too intrusive for my taste. I think an ORM should provide a true data mapper; in which the domain entities need know nothing about their persistence.

Matthew Weier O’Phinney has already posted about autoloading Doctrine in Zend Framework, but Doctrine2 presents some new challenges. Mainly that Doctrine2 is fully PHP5.3, including “real” namespaces, so its classes don’t follow the (current) Zend naming standard and the ZF autoloader won’t load them for us.

Good News, Doctrine provides its own autoloader that we can leverage to load its own classes.

Bad News, the Doctrine autoloader automatically registers itself with spl_autoload_register, causing the normal Zend loader to be forgotten (well, pushed down the stack, where it isn’t very useful).

Good News, it’s easy to remove the doctrine autoloader using spl_autoload_unregister, then push it onto the ZF autoloader stack, targeting the Doctrine namespace. Letting the ZF autoloader call it as necessary.

Enough jibber-jabber, how do we do all this? In the bootstrap! Adding this method to your Bootstrap.php will achieve what we want; adding the Doctrine autoloader to the Zend Framework autoloader queue for the “Doctrine\” namespace.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
    protected function _initDoctrine()
    {
        // Create the doctrine autoloader and remove it from the spl autoload stack (it adds itself)
        require_once 'Doctrine/Common/ClassLoader.php';
        $doctrineAutoloader = array(new \Doctrine\Common\ClassLoader(), 'loadClass');
        spl_autoload_unregister($doctrineAutoloader);

        // Fetch the global Zend Autoloader
        $autoloader = Zend_Loader_Autoloader::getInstance();

        // Push the doctrine autoloader to load for the Doctrine\ namespace
        $autoloader->pushAutoloader($doctrineAutoloader, 'Doctrine\\');
    }

We can use all of Doctrine’s classes anywhere else in our code.

1
2
3
4
<?php
use Doctrine\ORM;
$manager = EntityManager::create(array('driver' => 'pdo_sqlite', 'path' => ':memory:/'));
// ...

I still have a lot to learn and the documentation on 2.0 is a little sparse as yet, but this is a start.

Dependency Injection Container Resource in Zend Framework

A good dependency injection container is a godsend when it comes to managing the dependency tree of even a moderately complex domain model. As such, it comes as no surprise there has been much discussion about them of late in the PHP and Zend Framework communities.

Based on the Yadif and Benjamin Eberlei’s recent look at Using a Dependency Injection Container with Zend_Application, where he replaces Zend_Applications default container instance (A Zend_Registry instance) with a Yadif_Container, I have created a Zend_Application_Resource to allow configuration based injection of dependencies into the container via the normal ZF configuration file (application.ini)

The container resource copies any already instantiated objects from the old container into the new one, then replaces the default container.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
class Tek_Application_Resource_Container extends Zend_Application_Resource_ResourceAbstract
{
    protected $_container = null;

    public function getContainer()
    {
        if (null === $this->_container) {
            $options = $this->getOptions();
            $container = $this->_getBootstrap()->getContainer();
            if (!$container instanceof Yadif_Container) {
                $config = isset($options['options']) ? new Zend_Config($options['options']) : null;
                $container = new Yadif_Container(array(), $config);

                // import instances from the existing (Zend_Registry) container
                foreach ($this->_getBootstrap()->getContainer() as $key => $instance) {
                    $container->__set($key, $instance);
                }
            }
            $container->addComponents($options['objects']);
            $this->_container = $container;
        }

        return $this->_container;
    }

    public function init()
    {
        $this->getContainer();
        $this->_getBootstrap()->setContainer($this->_container);
        return $this->_container;
    }

    protected function _getBootstrap()
    {
        $app = $this->getBootstrap()->getApplication();
        if ($app instanceof Zend_Application) {
            return $app->getBootstrap();
        } else {
            return $app;
        }
    }
}

I’ve also created a simple action helper to allow easy grabbing of resources from the action controllers. Both reside in my extensions repository.

To use the container resource you will need to add the prefix and path to the bootstrappers plugin loader:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
// ...
    protected function _initPlugins()
    {
       $this->getPluginLoader()->addPrefixPath(
           'Tek_Application_Resource',
           'Tek/Application/Resource'
       );
    }
// ...
}

Then you can add the resources and their dependencies via the normal configuration system. This means adding lines like:

resources.container.objects.Log.class = "Zend_Log"
resources.container.objects.Log.arguments.0 = "Log_Writer"

resources.container.objects.Log_Writer.class = "Zend_Log_Writer_Stream"
resources.container.objects.Log_Writer.arguments.0 = "%Log_Writer.stream%"

resources.container.options.Log_Writer.stream = APPLICATION_PATH "/../log/application.log"

There are 2 resources defined here, the “Log” and the “Log_Writer”.

  1. Log is an instance of Zend_Log and takes a Log_Writer resource as the first (and only) argument to its constructor.

  2. The Log_Writer resource is an instance of Zend_Log_Writer_Stream and takes a scalar as its only argument. The scalar value is defined in the container option specified.

Now, the controller can write a log like this.

1
2
3
4
5
6
<?php
$logger = $this->getInvokeArg('bootstrap')->getResource('Log');
// or, with the helper
$logger = $this->_helper->resource('Log');

$logger->log('A log message', Zend_Log::NOTICE);

While this is a simple example, it can be really beneficial when working with, for example, a service layer. The service you need might depend on another service, both of which may depend on an Authorization service. All the services depend on their data mappers (which themselves depends on a database connection) and their entity factories, etc. Instantiating a dependency tree like this for every object you need can lead to duplicate and hard to modify code. Dependency injection coupled with a good container can provide highly versatile code whose behaviour can be drastically changed by only modifying a configuration file.