Delegate factories #4110

Closed
wants to merge 369 commits into
from

Conversation

Projects
None yet
Member

Ocramius commented Mar 25, 2013

I've been working on this concept for some time, but this is basically a cleaned up version of #2995

Why do we need this?

The idea is to be able to build delegates of any existing service. This can be used to build "decorators" for service instantiation and for proxying.

Delegation

Imagine that you have a DbConnection and a LoggedDbConnection object. A LoggedDbConnection wraps around a "real" DbConnection instance like following, but provides additional API that sends queries to a logger:

$connection = new LoggedDbConnection(new DbConnection());

Currently, our problem is that such a wrapper requires us to completely re-define the factory that instantiates DbConnection. There's no way to re-use logic from such a factory. We have to rewrite it and be aware of its internal logic:

    'db' => function ($sl) {
        // rewrite all ze logic here
        return new LoggedDbConnection($dbConnection);
    },

Proxying

We can proxy any service (with the assumption that we know its class name or implemented interface) and make it "lazy", so that its dependencies don't get instantiated when we request them. This allows us to build lightweight containers, as explained in https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md. Also, we don't have to worry about how the original service is instantiated, since the original factory is still existing.

Example

In the following example, I've simply replaced the original service (instance of stdClass) with a new one that contains the original service in property tab:

<?php

use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\DelegateFactoryInterface;

require_once __DIR__ . '/vendor/autoload.php';

class FooDelegateFactory implements DelegateFactoryInterface
{
    public function createDelegateWithName(
        ServiceLocatorInterface $serviceLocator,
        $name,
        $requestedName,
        $callback
    ) {
        $foo      = new \stdClass();
        $foo->tab = $callback(); // php5.4, heh

        return $foo;
    }
}

$serviceManager = new ServiceManager();
$serviceManager->setFactory('foo', function() {
    $foo = new \stdClass();
    $foo->bar = 'baz';

    return $foo;
});
$serviceManager->setService('foo-delegate-factory',new FooDelegateFactory());
$serviceManager->setDelegate('foo', 'foo-delegate-factory');

var_dump($serviceManager->get('foo')->tab->bar); // baz

Implementation flaws

  • Additional method call to doCreate, since I splitted create to allow this kind of behavior
  • doCreate is public, since I cannot use a closure and call ->bindTo($this) in PHP 5.3
  • It may not be clear at first, but the delegate factory is a service (which is a huge advantage, but is a bit different from what we're used to see)

mwillbanks and others added some commits Feb 28, 2013

Added abstract service factory to provide multiple loggers
configuration.

Change-Id: Ibd9309bf42c8992376849a1c5bbae05cd82e4c13
Added ability to configure MvcEvent listeners.
Change-Id: I568ec78485724be3ec68c0b754d9af95b3ea1b03
Added form abstract factory.
Change-Id: I071cf7b8e41d3f7f06f942650dc6f8a3d2215cba
Remove redundant "else" statement and redundant condition in factory
method.

Change-Id: I4a3bb387e4f63c5aa70519923ad3680c8ae5e5b0
Remove redundant "else" statement and redundant condition in factory
method.

Change-Id: Idf4802f8735a2333d927f5c6989e124c048e7854
Merged listeners with default set of listeners.
Change-Id: I382bc52191f3202b47ecd7910a2ffb4108c7e78e
Added test for custom application listeners.
Change-Id: Ib47b1604675e5beef8945b57df9dfb28ddef3ffd
Fixed typo in application's default listeners.
Change-Id: Ifb6241ff0d3799dbefdd9bd160e7f14c3ab68bf8
Added test case for logger abstract service factory.
Change-Id: Ibd0e492df076b801cb91078753bfe40bf77f63c0
Added injection of FormElementManager.
Change-Id: Ia85eab01106afa54e8156dadb9fece15d73e9ae8
Fixed coding style.
Minor improvements in abstract factory methods.

Change-Id: Ic6d1de0efede8780ff6d50126b98b50dee5fa5fb
Minor improvement in bootstrap method listeners merge.
Change-Id: Ib79a1e12bf93f53f44765ac2add526c3ccecfa6f
Updated test for custom application listener.
Change-Id: I32e556441e7ba46367b1a1a7485ab00e0cdcd6df
Added test case for FormAbstractServiceFactory
Change-Id: I93522febd9f4c61286a2bce36bf3a1333a54e1ae
Merge branch 'hotfix/yaml-dev-version' into develop
Fixes for symfony/yaml autoloading
Merge branch 'hotfix/phpunit' into develop
PHPUnit upgrade fixes dependency issues
Minor improvement in validation of configuration.
Change-Id: I8e342727e72db510a45b885ddb293ceef4590510
[#3814] CS fixes
- trailing whitespace
Member

Ocramius commented Mar 26, 2013

@bakura10 implemented multiple delegates

weierophinney and others added some commits Mar 26, 2013

Fix failing tests in Zend\InputFilter
- Cleaned up BaseInputFilterTest to use a data provider; makes isolating failing
  cases simpler.
- Rewrote logic in validateInputs() to capture discrete use cases; more verbose,
  but easier to determine what is happening.
- Made executive decision: non-required input that is empty is valid.
Merge pull request #3490 from youngguns-nl/zf-3371
Added support for callable credential validator

Conflicts:
	library/Zend/Authentication/Adapter/DbTable.php
Forward #4019
Merge branch 'antonycox-master' into develop
Forward #4022
Merge branch 'wryck7-hotfix/3685' into develop
Merge pull request #4048 from spiffyjr/hotfix/i18n-composer
Moved ext-intl to suggest instead of require to avoid silent fallback.

Conflicts:
	library/Zend/I18n/composer.json
Merge branch 'hotfix/4049' into develop
Conflicts:
	tests/ZendTest/ModuleManager/TestAsset/SubModule/Sub/Module.php
PR #4073
Merge branch 'develop' of git://github.com/mixkorshun/zf2 into mixkorshun-develop
PR #4073
Merge branch 'mixkorshun-develop' into develop
Merge pull request #4098 from samsonasik/fix/docblock.bool
fix php docblock : boolean should be bool

Conflicts:
	library/Zend/Filter/File/RenameUpload.php
	library/Zend/Mvc/Controller/Plugin/FilePostRedirectGet.php
	library/Zend/Mvc/Controller/Plugin/FlashMessenger.php
	library/Zend/Mvc/Controller/Plugin/PostRedirectGet.php
	library/Zend/Mvc/Router/SimpleRouteStack.php
[#4098] CS fixes
- linefeed
Merge pull request #4099 from samsonasik/fix/cast.bool
fix (bool) casting : add space and use (bool) instead of (boolean) to cast
Owner

weierophinney commented Mar 28, 2013

@Ocramius ping me when this is no longer a WIP. :)

Member

Ocramius commented Mar 28, 2013

@weierophinney I don't think this is WIP. I'm only concerned about the overhead of the additional call. I think we should inline some code like hasAlias and canonicalizeName, which is a minor BC break.

Member

Ocramius commented Mar 29, 2013

Closing. Noticed that it was PR-ed against master. Opened #4145 instead

@Ocramius Ocramius closed this Mar 29, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment