1

In the album example of the Zend Framework 2 User Guide the model is configured like this:

<?php
namespace Album;

// Add these import statements:
use Album\Model\Album;
use Album\Model\AlbumTable;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;

class Module
{
    // getAutoloaderConfig() and getConfig() methods here

    // Add this method:
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'Album\Model\AlbumTable' =>  function($sm) {
                    $tableGateway = $sm->get('AlbumTableGateway');
                    $table = new AlbumTable($tableGateway);
                    return $table;
                },
                'AlbumTableGateway' => function ($sm) {
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new Album());
                    return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
                },
            ),
        );
    }
}

The variable $sm is a Zend\ServiceManager\ServiceManager object. But how/when/where is it created/initialized?

EDIT:

What I want to know, is: How/where does $sm get its value (and become a ServiceManager object).

automatix
  • 14,018
  • 26
  • 105
  • 230
  • I'd wait for a Answer from one of the ZF2-Devs, but my ASSUMPTION would be this line: https://github.com/zendframework/zf2/blob/master/library/Zend/ServiceManager/ServiceManager.php#L737 – Sam Mar 21 '13 at 11:43
  • If you're using the skeleton app, it's instantiated by `Application::init()` here -> https://github.com/zendframework/zf2/blob/master/library/Zend/Mvc/Application.php#L236 – Crisp Mar 21 '13 at 12:29
  • Thank you for your replies guys! I'm still not getting, how it can work. I've just tried to formulate my question exacter, s. EDIT. – automatix Mar 21 '13 at 12:56
  • @automatix, when you retrieve a service from a service manager, if it's a factory, it passes an instance of itself as the first parameter to whichever `callable` is responsible for creating the service, that will usually be either a `closure` (as in your example), or the `createService` method of a factory class. This is done, in the case of factories, by the code here -> https://github.com/zendframework/zf2/blob/master/library/Zend/ServiceManager/ServiceManager.php#L859 – Crisp Mar 21 '13 at 13:10
  • @Crisp I agree with you, post this as an answer so it can help others with similar question – Stoyan Dimov Mar 21 '13 at 14:25
  • @StoyanDimov, wasn't sure if it classed as an answer, however, since you agree, I've added it :) – Crisp Mar 21 '13 at 14:52
  • So basically i was right? Yay, i understand the framework a little bit after all :D – Sam Mar 21 '13 at 14:53

1 Answers1

1

When you retrieve a service from a service manager, if it's a factory, it passes an instance of itself as the first parameter to whichever callable is responsible for creating the service, that will usually be either a closure (as in your example), or the createService method of a factory class.

This is done, in the case of factories, by the code here https://github.com/zendframework/zf2/blob/master/library/Zend/ServiceManager/ServiceManager.php#L859

Basically, in your module you're telling the ServiceManager that those services are created by calling the closures you provided. When you ask the ServiceManager to get() one of them the first time, it'll determine it's a factory (it was supplied in the factories key in config), then figure out if it's a closure or an instance of FactoryInterface (a factory class), and finally call it appropriately to instantiate your service.

Crisp
  • 11,417
  • 3
  • 38
  • 41
  • Thank you for your comments and the answer! I think, I'm stuck... I've tried to debug the Application and especially the `ServiceManager#createFromFactory()`, but cannot find the point, where `$sm` gets its value. ZF2 is hard to debug and hence hard to learn/unterstand (for me anyway). If it's not too much effort, could you (or somebody else) please describe step by step the whole chain to the place in the code, where `$sm` is initialized and gets the value. Something like a commented stack trace. It would be really great. Thank you very much in advance! – automatix Mar 21 '13 at 15:33
  • 3
    The line that @Sam linked in your OP is where the $sm gets its value, the line `$instance = call_user_func($callable, $this, $cName, $rName);` where the second param `$this` is the `ServiceManager` instance passed to `call_user_func`, that becomes the `$sm` instance you receive as first param of your closure – Crisp Mar 21 '13 at 15:46