Coder Social home page Coder Social logo

zend-servicemanager's Introduction

zend-servicemanager

Repository abandoned 2019-12-31

This repository has moved to laminas/laminas-servicemanager.

Master: Build Status Coverage Status Develop: Build Status Coverage Status

The Service Locator design pattern is implemented by the Zend\ServiceManager component. The Service Locator is a service/object locator, tasked with retrieving other objects.

Benchmarks

We provide scripts for benchmarking zend-servicemanager using the PHPBench framework; these can be found in the benchmarks/ directory.

To execute the benchmarks you can run the following command:

$ vendor/bin/phpbench run --report=aggregate

zend-servicemanager's People

Contributors

akrabat avatar bakura10 avatar blanchonvincent avatar coss avatar dasprid avatar demichl68 avatar evandotpro avatar ezimuel avatar freeaqingme avatar geeh avatar jonathanmaron avatar kokspflanze avatar kokx avatar maks3w avatar marc-mabe avatar michalbundyra avatar mikaelkael avatar mpinkston avatar mwillbanks avatar ocramius avatar prolic avatar ralphschindler avatar samsonasik avatar sgehrig avatar snapshotpl avatar thinkscape avatar veewee avatar wdalmut avatar weierophinney avatar xerkus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zend-servicemanager's Issues

v3 performance while registering services factories and aliases

Working with zend-expressive i found out that migrating to a newer version that included servicemanage 3 the very same test app was much slower. This occurred when registering all zend-form helper plugins.

zendframework/zend-expressive-zendviewrenderer#25
zendframework/zend-form#76

So i decided to prepare and run 2 simple test scripts whose only purpose is to register all zend-form view helpers using zend-servicemanager v2 and v3 and explain the issue here as I believe this repo is more appropriate for this.

v3 test: zend-form configuration time ~ 22 ms (PHP 7.0), ~52-70 ms (PHP 5.6)
cd /my/test/path/sm3
composer require zend-servicemanager:3.0.*
composer require zend-i18n
composer require zend-form
composer require zend-view
<?php
// file /my/test/path/sm3/test.php
require 'vendor/autoload.php';

use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\Config;
use Zend\I18n\View\HelperConfig as I18nViewHelperConfig;
use Zend\Form\View\HelperConfig as FormViewHelperConfig;
use Zend\View\HelperPluginManager;

$serviceManager = new ServiceManager();
$helperManager  = new HelperPluginManager($serviceManager);

(new I18nViewHelperConfig())->configureServiceManager($helperManager);

$t0 = microtime(true);
(new FormViewHelperConfig())->configureServiceManager($helperManager);
$ms = 1000 * round(microtime(true) - $t0, 5) . ' ms';

echo 'zend-servicemanager-v3 => ' . $ms . PHP_EOL;
$ php70 test.php # ~ 22 ms
$ php56 test.php # ~52-70 ms
v2 test: zend-form configuration time < 2ms (PHP 7.0), ~7-9 ms (PHP 5.6)
cd /my/test/path/sm2
composer require zend-servicemanager:2.7.*
composer require zend-i18n
composer require zend-form
composer require zend-view
<?php
// file /my/test/path/sm2/test.php
require 'vendor/autoload.php';

use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\Config;
use Zend\I18n\View\HelperConfig as I18nViewHelperConfig;
use Zend\Form\View\HelperConfig as FormViewHelperConfig;
use Zend\View\HelperPluginManager;

$serviceManager = new ServiceManager();
$helperManager  = new HelperPluginManager();
$helperManager->setServiceLocator($serviceManager);

(new I18nViewHelperConfig())->configureServiceManager($helperManager);

$t0 = microtime(true);
(new FormViewHelperConfig())->configureServiceManager($helperManager);
$ms = 1000 * round(microtime(true) - $t0, 5) . ' ms';

echo 'zend-servicemanager-v2 => ' . $ms . PHP_EOL;
$ php70 test.php # < 2ms
$ php56 test.php # ~7-9 ms

All the installed packages have the same version excluding zend-servicemanager

any hint/help?

could this performance degradation be related to ServiceManager 3 configure() method, involving rewriting the alias arrays and performing inner tests on existing keys and called for every registered alias?

or simply is there something wrong in my setup (all this started when overwriting/delegating a new HelperPluginManagerFactory/DelegatorFactory in zend-expressive zendframework/zend-expressive-zendviewrenderer#25
zendframework/zend-form#76 my last comments)

kind regards

PS
forgot to mention that in the zend-expressive test app I obviously use zend opcode cache ext.

ServiceManager returns that service does not exist with has() but can create with get()

I created service manager like this:

use Zend\ServiceManager\AbstractPluginManager;
use Zend\ServiceManager\Exception\RuntimeException;

class TypesManager extends AbstractPluginManager
{
    protected $invokableClasses = [
        InArrayType::class => InArrayType::class,
        RegexType::class   => RegexType::class,
    ];
    protected $aliases = [
        'in_array' => InArrayType::class,
        'regex'    => RegexType::class,
    ];

    public function validatePlugin($type)
    {
        if ($type instanceof SettingTypeInterface) {
            return; // we're okay
        }
        throw new RuntimeException(sprintf(
            'SettingType of type %s is invalid; must implement %s',
            (is_object($type) ? get_class($type) : gettype($type)),
            SettingTypeInterface::class
        ));
    }
}

I am using like this:

$manager = new TypesManager();
$manager->has(InArrayType::class); // returns false
$manager->has('in_array'); // returns false(canonicalization problem because of `_` ?)
$manager->has(RegexType::class); // returns false
$manager->has('regex'); // returns true
$manager->get(InArrayType::class); // returns instance off InArrayType::class
$manager->get('in_array'); // // returns instance off InArrayType::class
$manager->get(RegexType::class); // returns instance off RegexType::class
$manager->get('regex'); // // returns instance off RegexType::class

when I sow this I thought maybe I doing it wrong so checked other zend modules like zend-filter and wrote some tests:

    public function testFirstGet()
    {
        $manager = new FilterPluginManager();
        $this->assertInstanceOf('Zend\Filter\Boolean', $manager->get('Zend\Filter\Boolean'));
        $this->assertTrue($manager->has('Zend\Filter\Boolean'));
    }
    public function testFirstHas()
    {
        $manager = new FilterPluginManager();
        $this->assertTrue($manager->has('Zend\Filter\Boolean')); // fails here
        $this->assertInstanceOf('Zend\Filter\Boolean', $manager->get('Zend\Filter\Boolean'));
    }

First pass second fails.
order of has() and get() is important?

Repeated AbstractFactory in ServiceManager may occur.

I use zend-mvc. When module A & B may be have the same AbstractFactory in module.config.php. Can remove duplicate AbstractFactory in ServiceManager ?

Exapmle:

use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
use Interop\Container\ContainerInterface;

class TestAbstractFactory implements AbstractFactoryInterface
{
    public static $calls = 1;
    public function canCreate(ContainerInterface $container, $requestedName)
    {
        echo "Call: " . self::$calls . "\n";
        self::$calls++;
        return false;
    }
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
    }
}

$services = new ServiceManager();
$services->addAbstractFactory('TestAbstractFactory');
$services->addAbstractFactory('TestAbstractFactory');
$services->addAbstractFactory('TestAbstractFactory');

$services->has('test');

//Print:
//Call: 1
//Call: 2
//Call: 3

//Expected: 
//Call: 1

Merging to master

Hey @weierophinney ,

Is there any specific things to do/verify before we can merge that to master ? Would help to try Zend\Expressive with this :)

2.7 InvokableFactory options from AbstractPluginManager affect multiple unshared instantiations

I ran into this when using a NotEmpty validator, if I specify the options for one of them, all of them get those options rather than the defaults.

public function getInputFilterSpecification()
{
    return [
        'elementA' => [
            'required' => true,
            'validators' => [
                [
                    'name' => 'notEmpty',
                    'options' => [
                        'type' => NotEmpty::NULL,
                    ],
                ],
            ],
        ],
        'elementB' => [
            'required' => true,
            //Injected validator will have type NotEmpty::NULL
        ],
    ];
}

[Expressive] Factories are not sharable if calling class is in different __NAMESPACE__ (module)

I'm working with Zend Expressive and I encounter the following issue when I reuse the Factory class.

I have two similar classes but in different NAMESAPCE (module).

'factories' => [
      App\Page\MyAppPage::class  => App\Factory\PageInitializerFactory::class 
      OtherApp\Page\MyOtherAppPage::class => App\Factory\PageInitializerFactory::class
]

Upon execution it prompts ERROR: CLASS OtherApp\Page\MyOtherAppPage not found.

Since they are both injecting the same dependencies (Router and Template), and as recommended in the documentation, I've created a page factory class that has the following structure:

namespace App\Factory;

use Interop\Container\ContainerInterface;
use Zend\Expressive\Router\RouterInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\Expressive\Template\TemplateRendererInterface;

class PageInitializerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $router   = $container->get(RouterInterface::class);
        $template = ($container->has(TemplateRendererInterface::class))
            ? $container->get(TemplateRendererInterface::class)
            : null;

        return new $requestedName($router, $template);
    }
}

I've also checked the both configuration was merged properly, since they are in a different module (NAMESPACE).

Below are the class structure that I've tested.

namespace App\Page;

use Zend\Expressive\Router;
use Zend\Expressive\Template;

class MyAppPage
{
    private $router;

    private $template;

    public function __construct(Router\RouterInterface $router, Template\TemplateRendererInterface $template = null)
    {
        $this->router   = $router;
        $this->template = $template;
    }
}

Similar class in a different NAMESPACE (module)

namespace OtherApp\Page;

use Zend\Expressive\Router;
use Zend\Expressive\Template;

class MyOtherAppPage
{
    private $router;

    private $template;

    public function __construct(Router\RouterInterface $router, Template\TemplateRendererInterface $template = null)
    {
        $this->router   = $router;
        $this->template = $template;
    }
}

ViewHelperPlugin manager configure problem

ViewHelperManager is special type of ServiceManager. There is problem with flushing instances with configure (SM 3.0). It is needed for still alive applications e.g on ReactPHP

['HelperName' => null] + $this->services

does not work, because there is plugin validation.

[Zend\ServiceManager] Add alternatives services proposals when service not found is thrown

This issue has been moved from the zendframework repository as part of the bug migration program as outlined here - http://framework.zend.com/blog/2016-04-11-issue-closures.html


Original Issue: https://api.github.com/repos/zendframework/zendframework/issues/6836
User: @blanchonvincent
Created On: 2014-11-03T14:33:39Z
Updated At: 2015-02-19T20:09:54Z
Body
This idea comes from symfony, it would be good to add some details about services that are close (about name). This point can help developer to save time during the debug.


Comment

User: @blanchonvincent
Created On: 2014-11-03T17:21:43Z
Updated At: 2014-11-03T17:21:43Z
Body
The travis fail seems pretty strange


Comment

User: @manchuck
Created On: 2014-11-03T19:57:41Z
Updated At: 2014-11-03T19:57:41Z
Body
I would want an option to disable this feature for production.


Comment

User: @blanchonvincent
Created On: 2014-11-03T20:01:19Z
Updated At: 2014-11-03T20:01:19Z
Body
@manchuck why?


Comment

User: @manchuck
Created On: 2014-11-03T20:10:51Z
Updated At: 2014-11-03T20:10:51Z
Body
If by some chance something gets released to prod with that causes this to be called, having a lev look up can cause a slowdown. If someone finds this out, it could bring the sever to a crawl doing all these look ups


Comment

User: @blanchonvincent
Created On: 2014-11-03T20:15:55Z
Updated At: 2014-11-03T20:17:24Z
Body
@manchuck I think the lev method consume less memory cpu/memory than a big sql request, so if someone want to put the mess in your server with malicious action, it's pretty easy to do that without these lines :)


Comment

User: @blanchonvincent
Created On: 2014-11-04T20:29:08Z
Updated At: 2014-11-04T20:29:08Z
Body
@manchuck After considering it, if the developers want to handle the exception from the service manager to load services from another manager as a fallback of provide a default action, it can be good to allow to deactivate this feature. I would like other reviews about this PR. Thank you for your time. 👍


Comment

User: @mpalourdio
Created On: 2014-11-04T20:33:58Z
Updated At: 2014-11-04T20:41:06Z
Body
I'm definitely +1 with this feature for a dev environment. I like this feature in symfony. I once thought about adding it into ZDT. Maybe it would better land in ZDT, as it's more a dev specific information, no ?


Comment

User: @Ocramius
Created On: 2014-11-22T08:19:34Z
Updated At: 2014-11-22T08:19:34Z
Body
I had implemented this as an abstract factory once :-) I suggest doing the same in this case ;-)


Comment

User: @Pittiplatsch
Created On: 2014-11-24T17:54:00Z
Updated At: 2014-11-24T17:54:00Z
Body
@Ocramius Nice idea. If done properly, this abstract factory can be configured for dev env's only. 👍


Comment

User: @Ocramius
Created On: 2014-12-06T01:33:11Z
Updated At: 2014-12-06T01:33:21Z
Body
I suggest looking at https://github.com/Ocramius/zf2/blob/95ad5fd6877335f8670b3635952e5bdaa696dc00/library/Zend/ServiceManager/Zf2Compat/ServiceNameNormalizerAbstractFactory.php for that.


Comment

User: @weierophinney
Created On: 2015-02-19T20:09:54Z
Updated At: 2015-02-19T20:09:54Z
Body
I'm with @Ocramius on this one; let's implement it as an abstract factory. Developers can then enable/disable at will, and it doesn't require changes to the service manager itself.


ServiceManager constructor arg

Copying from the online documentation:

ServiceManager API Changes
Configuration no longer requires a Zend\ServiceManager\Config instance. Config can be used, but is no needed.

While constructor source code requires an array as 1st argument and it breaks migration.

Circular dependency with creation options

I use InputFilterAbstractServiceFactory to create input filters. I need to create validator which require another input filter. Every thing works great, but when required input filter contains same validator I get circular dependency exception. It's expected behavior, however I use MutableCreationOptionsInterface and using options parameter I configure another input filter. When I remove circular dependency checking everything works fine.

return [
'input_filter_specs' => [
        'address' => [
            'locality' => [],
            'postal_code' => [],
            'country' => [],
        ],
        'user' => [
            'company' => [
                'type' => Zend\InputFilter\InputFilter::class,
                'name' => [],
                'vat_id' => [
                    'required' => false,
                ],
                'address' => [
                    'required' => false,
                    'validators' => [
                        [
                            'name' => Infrastructure\Validator\Structure::class,
                            'options' => [
                                'input_filter' => 'address',
                            ],
                        ],
                    ],
                ],
            ],
        ],
        'some_input_filter' => [
            'number' => [
                'required' => true,
            ],
            'user' => [
                'required' => false,
                'validators' => [
                    [
                        'name' => Infrastructure\Validator\Structure::class,
                        'options' => [
                            'input_filter' => 'user',
                        ],
                    ],
                ],
            ],
        ],
    ],
];

So:

  • some_input_filter contains user input which have Infrastructure\Validator\Structure validator created with user input filter
  • user input filter contains company.address input with Infrastructure\Validator\Structure validator created with another address input filter.

Why shared large do not work by base name of class?

In ZF2 shared worked both base name and alias name of class. Now (ZF3) shared work only by specified name of class or alias in config. Example, test ended with a error: test . In ZF2 it worked: old test.

My config following:

return [
    'service_manager' => [
        'factories' => [
            FormBuilder::class => FormBuilderFactory::class,
        ],
        'shared' => [
            FormBuilder::class => false,
        ],
        'aliases' => [
            'Bupy7\Form\FormBuilder' => FormBuilder::class,
        ],
    ],
    'view_helpers' => [
        'factories' => [
            FormBuilderHelper::class => FormBuilderHelperFactory::class,
        ],
        'shared' => [
            FormBuilderHelper::class => false,
        ],
        'aliases' => [
            'formBuilder' => FormBuilderHelper::class,
        ],
    ],
];

If to change to:

return [
    'service_manager' => [
        'factories' => [
            FormBuilder::class => FormBuilderFactory::class,
        ],
        'shared' => [
            FormBuilder::class => false,
            'Bupy7\Form\FormBuilder' => false,
        ],
        'aliases' => [
            'Bupy7\Form\FormBuilder' => FormBuilder::class,
        ],
    ],
    'view_helpers' => [
        'factories' => [
            FormBuilderHelper::class => FormBuilderHelperFactory::class,
        ],
        'shared' => [
            FormBuilderHelper::class => false,
            'formBuilder' => false,
        ],
        'aliases' => [
            'formBuilder' => FormBuilderHelper::class,
        ],
    ],
];

all work. Both name of class and alias of class.

Is it bug or no?

'proxy' alias for alias of invokable factory

I found this bug after update zend-servicemanager to version 2.7. I'm using zfcampus/zf-mvc-auth and the problem is caused because of:

    'service_manager' => array(
        'aliases' => array(
            'authorization' => 'ZF\MvcAuth\Authorization\AuthorizationInterface',
            'ZF\MvcAuth\Authorization\AuthorizationInterface' => 'ZF\MvcAuth\Authorization\AclAuthorization',
        ),

so there is kind of "proxy alias" ZF\MvcAuth\Authorization\AuthorizationInterface for an invokable factory ZF\MvcAuth\Authorization\AclAuthorization. It is not possible to get service authorization, because of the proxy.

Commit a7bc0d1, which should fix alias invokable aliases (version 2.7), caused BC.

ServiceLocator instead of Container

Hi,

I want to migrate our Application from Zend 2 to Zend 3. At first only the servicemanager.
We want to use the new "build" method for creating objects with options.

The new system always uses the "__invoke" method to call the factory. This is fine by us, but the signature has now the "ContainerInterface" instead of the "ServiceLocatorInterface".
The "ContainerInterface" does not have the "build" method. The "$container->build('Foo')" works (Its always a servicelocator), but the IDE shows a warning.

I think we need an FactoryInterface with the ServiceLocator inside the __invoke method.
Is this possible to implement with the next version.

Greetings Jan

ServiceManager Initializers seems not to work on Controller

ZF3 zend-servicemanager v3.1.1
I've tried to add an Initializer which will not be called for the controller:

Zend\ServiceManager\ServiceManager on Line: 761 (doCreate)

foreach ($this->initializers as $initializer) {

    if(!is_array($object)){
        if('Application\Controller\IndexController' == get_class($object)){
            die(var_dump(get_class($initializer)));
        }               
    }
    $initializer($this->creationContext, $object);
}

Returns:

Warning: get_class() expects parameter 1 to be object, array given in vendor\zendframework\zend-servicemanager\src\ServiceManager.php on line 764
bool(false) 

Are the badges wrong?

The coverage badge says that master is tested at 78% while develop is 99%. But now that v3 is merged, the master should be also at 99%.

I'm not really sure why the badge is incorrect though.

[v3] Abstract factories for zend-expressive middleware

I'm testing the ServiceManager version 3 in a Zend Expressive application and I'm getting this problem.
Since abstract factories are no longer included while calling Container::has, it always returns false.
That makes all my middleware to be lazily instantiated, instead of being fetched from the ServiceManager, producing exceptions due to missing constructor arguments.

BC Break: zend-hydrator does not work with zend-servicemanager 2.7.4 anymore

Hi,

after upgrading zendframework/zend-servicemanager from 2.6.0 to 2.7.4 i get the following exception when trying to retrieve delegatinghydrator (Zend\Hydrator\DelegatingHydrator):

Uncaught exception 'Zend\\ServiceManager\\Exception\\ServiceNotFoundException' with message 'An alias "Zend\\Hydrator\\DelegatingHydrator" was requested but no service could be found.'

How to create ServiceManager object for both V2 and V3

I want to support both but the constructor signatures are different

ServiceManager::__construct(ConfigInterface $config = null);
ServiceManager::__construct(array $config = []);

and now I am creating ServiceManager:

$config = [];
new ServiceManager(new Zend\ServiceManager\Config($config)); // does not work for V3
new ServiceManager($config); // does not work for V2

maybe I am missing something?

Thrown exceptions don't implement the container-interop interfaces

The latest version of the ServiceManager advertises that it implements the container-interop interface, but it doesn't follow the spec rules on exceptions:

Exceptions directly thrown by the container MUST implement the Interop\Container\Exception\ContainerException.

A call to the get method with a non-existing id SHOULD throw a Interop\Container\Exception\NotFoundException.

Initializer with returning value

I think it could be useful to allow the InitializerInterface to return a new instance of the object it is initializing.

For example we could have an initializer like

function ($container, $instance) {
    if (/*some condition on $instance*/) {
        return new OtherClass($instance);
    }
}

This could be useful, for example, for decorating a set of objects based on an interface they are implementing.

Moreover, this would not influence the current behaviour of the initializers.

Is there any reason not to do this I am not seeing?

Classes conflicts with zend-servicemanager-di

See zendframework/zend-mvc@65b6f01

So, installing zf2 (only 2.x components) you have both zend-servicemanager 2.7 and zend-servicemanager-di 1.0, both providing the same classes.

perhaps

  • zend-servicemanager should drop these classes and requires zend-servicemanager-di
    or
  • zend-mvc should not requires zend-servicemanager-di (which should then be required by zend-servicemanager > 3)

Slow aliases and factory set methods

In new SM3 there is couple of methods that are more slowly than in SM2

Difference in time is great (about 8x slower on this method)
All other comparisons I provide exactly on that function.

The reason is that is it a lot of factories and aliases that pass to SM with functions setAlias and setFactory. Behind the scene one key value pair meld with config in configure method.

I see 2 ways to solve problem:

  • add functions such as setAliases and etc...
public function setAliases($aliasTargetPairs)
{
    $this->configure(['aliases' => $aliasTargetPairs]);
}
  • Modify function setAlias to something like that: it was a bad idea, skip that
public function setAlias($alias, $target)
{
    $this->validateOverrides(['aliases' => [$alias => $target]]);
    $this->aliases[$alias] = $target;
}

First one is more elegant and have maximum speed(10x faster then in SM2, 75x faster current SM3). But we need to rewrite other components.
Second one is twice slower than SM2, but there is no need to modify other components.

Of course we could apply both of them.
I think that first one is best idea, I would like to provide PR for this issue, if it is resonable.

Also I could provide PR to to 2.7 branch of SM witch allows modify other components to use that methods.

ServiceManager\Factory\InvokableFactory why so difficult ?

Why not AbstractFactory?

final class InvokableFactory implements AbstractFactoryInterface
{
    public function canCreateServiceWithName(ServiceLocatorInterface $serviceManager, $name, $requestedName)
    {
        return class_exists($requestedName);
    }
    public function createServiceWithName(ServiceLocatorInterface $serviceManager, $name, $requestedName)
    {
        return new $requestedName();
    }
}

Сonfigurable factories

Hi, all,

I have tourbles with tons of factories (controllers/actions/simple services/etc) and I think to do simple dependencies configuration like:

'dep-name' => [
    'class' => MyService::class,
    'deps' => [
        Dep1::class,
        Dep2::class,
    ],
],

It's will be alternative for factories, invokables etc and works like a factory sample:

'dep-name' => function($container) {
    return new MyService($container->get(Dep1::class), $container->get(Dep2::class));
},

In the future it can be used for annotations/reflection support maybe.

I want to implement it.

But I need help from you!
First, I need discussions and ideas for implementation (config examples, naming etc).
Second, I need support (moral).

Cannot create using alias and InvokableFactory

I try to get service using alias. Alias is linked to factory with InvokableFactory. I get exception:

InvokableFactory requires that the requested name is provided on invocation; please update your tests or consuming container

After debug I have found that requested name in InvokableFactory is alias name.

It's occur in 2.7.

zendframework/zend-stdlib should be required in composer.json

library zendframework/zend-stdlib should be required in composer.json because it is used in class Zend\ServiceManager\Config, and for example running unit tests gives a fatal error:

PHP Fatal error: Class 'Zend\Stdlib\ArrayUtils' not found in ...\zend-servicemanager\src\Config.php on line 62

Add configure() method to 2.8 for easier migration to 3.0

It would be useful for libraries to have a support for version >= 2.7 und >= 3.0. For this I need a configure() method so i can use it for version 2.8 and 3.0, because the constructor has changed.

I can not do this return new ServiceManager(new Config(require 'config/dependencies.php')); in my services.php in 3.0.

For example for SM 2.8

    public function configure(array $config)
    {
        $config = new Config($config);
        $config->configureServiceManager($this);
    }

What do you think?

[v3] Proposal of provide at least empty traits for interfaces.

Actually it's difficult to make changes on interface definitions and preserve the backward compatibility at the same time.

Abstract classes are more flexible and allow more code changes without break the compatibility while still preserving the same signature as before. However Abstract classes does not allow composition (multi inheritance)

I propose to provide at least an empty trait for each defined interface and suggest to the user to always use that trait in their code. Traits allow us to provide small changes (usually proxy methods) while preserve the compatibility with existing implementations.

Implement this code style guideline implies the following:

  • Existing traits which name match with the interface are reserved for provide the most basic implementation (When a set of traits provide alternative implementations about the same interface their names must not match with the interface name)
  • Code on traits should must rely only on the interface public methods and don't provide new methods don't exists on the interface.
  • protected and private methods are not allowed. Traits must be minimal.

Migration questions

Couple of things I'm not 100% about:

  • I see $services->get('Config') in lots of v2 packages. In Expressive "config" is lowercased. I'm guessing it should be lowercased to make it compatible with both v2 and v3. Can you confirm?
  • There seem to be endless variations of alias formats for plugin managers. The docs have alllower, camelCase and CamelCase, but test cases for lots packages (esp. those dependent on zend-validator) use a lot of snake case in the config ('not_empty', 'string_trim', etc). Should the tests change, or the aliases?
  • The docs for AbstractPluginManager have the validate() method throwing an InvalidServiceException. Most packages throw their own exception from validatePlugin(). Is the intention that all v3 packages use the InvalidServiceException (in which case validatePlugin() should catch and re-throw), or is it OK to throw the package-specific exception from validate()?

Many thanks!

FEATURE REQUEST

Hello,

many invokables are likely to be configured like this:

[
    //....
    'invokables' => [
        //....
        My\Name\Space\ClassName::class => My\Name\Space\ClassName::class,
        //....
    ],
    //....
]

wouldn' it be useful to be able to define just 1 string value in the configuration array and handle cases when $name type is integer (by setting $name = $class) in ServiceManager::createAliasesForInvokables(), ServiceManager::createFactoriesForInvokables()?

kind regards

[Docs] Service Naming Convention: class or interface

In one of my projects based on ZF3 Service-Manager I noticed that the InvokableFactory does not work properly when I use an interface for the naming of a service. That makes sense but leads to a question:

What is the best practice to name a service? Use the class name or the interface? For example Zend\I18n uses both concepts:

https://github.com/zendframework/zend-i18n/blob/master/src/ConfigProvider.php

Is there a clear definition and should that be documented?

BC break: zend-servicemanager 2.7.6 and zend-inputfilter 2.7.1 fatal error

Hello,

I have this fatal error in my code, when using zend-servicemanager 2.7.6 and zend-inputfilter 2.7.1:

Fatal error: Uncaught Error: Call to undefined method Zend\ServiceManager\ServiceManager::getServiceLocator() in vendor/zendframework/zend-inputfilter/src/InputFilterAbstractServiceFactory.php:74
Stack trace:
#0 vendor/zendframework/zend-servicemanager/src/ServiceManager.php(771): Zend\InputFilter\InputFilterAbstractServiceFactory->canCreateServiceWithName(Object(Zend\ServiceManager\ServiceManager), 'doctrine.connec...', 'doctrine.connec...')
#1 vendor/zendframework/zend-servicemanager/src/ServiceManager.php(716): Zend\ServiceManager\ServiceManager->canCreateFromAbstractFactory('doctrine.connec...', 'doctrine.connec...')
#2 vendor/dasprid/container-interop-doctrine/src/AbstractFactory.php(121): Zend\ServiceManager\ServiceManager->has('doctrine.connec...')
#3 vendor/dasprid/container-interop-doctrine/src/EntityManagerFactory.php(40): ContainerInteropDoctrine\AbstractFactory->retrieveDependency(Object(Zend in vendor/zendframework/zend-inputfilter/src/InputFilterAbstractServiceFactory.php on line 74

Is this a BC break in zend-servicemanager and could it be fixed? Thanks!

AbstractPluginManager raises deprecation warning (possible bug?)

As many of you know, migration to Zend\ServiceManager 3.0 isn't straightforward as it includes many BC breaks. This includes the removal of ServiceLocatorAwareInterface.

This is the place to ask if this is an actual bug or just early notice, but in version 2.7.6 of zend-servicemanager, the Zend\ServiceManager\AbstractPluginManager tends to implement the interface above, causing an E_WARNING to be thrown during it's initialization.

Is it possible to create a fix for it or I should consider migration to version 3.0 of the module, when possible?

BC break: not able to find ServiceManager named service

After upgrade ( I am not sure it's zend-mvc or zend-servicemanager), the code below is throwing exception:
Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for ServiceManager

Factory/AuthControllerFactory

$services = $controllers->getServiceLocator()->get('ServiceManager');

When the code is changed to:

$services = $controllers->getServiceLocator();

It works but I am not sure if this is backward compatible.

is it possible that 2.7.5 contains BC break?

in https://github.com/bushbaby/BsbFlysystem module everything works with <=2.7.4 then I changed zend-sericemanager from 2.7.4 to 2.7.5 in composer and run composer update:

Updating dependencies (including require-dev)
  - Removing zendframework/zend-eventmanager (2.6.3)
  - Installing zendframework/zend-eventmanager (3.0.1)
    Loading from cache

  - Removing zendframework/zend-servicemanager (2.7.4)
  - Installing zendframework/zend-servicemanager (2.7.5)
    Loading from cache

  - Removing zendframework/zend-cache (2.5.3)
  - Installing zendframework/zend-cache (2.6.1)
    Loading from cache

  - Removing zendframework/zend-log (2.6.0)
  - Installing zendframework/zend-log (2.7.1)
    Loading from cache

  - Installing psr/http-message (1.0)
    Loading from cache

  - Installing zendframework/zend-diactoros (1.3.5)
    Loading from cache

  - Installing zendframework/zend-escaper (2.5.1)
    Loading from cache

  - Installing zendframework/zend-uri (2.5.2)
    Loading from cache

  - Installing zendframework/zend-http (2.5.4)
    Loading from cache

  - Installing zendframework/zend-psr7bridge (0.2.1)
    Loading from cache

  - Removing zendframework/zend-mvc (2.6.3)
  - Installing zendframework/zend-mvc (2.7.3)
    Loading from cache

Writing lock file
Generating autoload files

after only this change tests fails.
because travis did not work as expected I copy pasted phpunit output here
bushbaby/BsbFlysystem#25

ping @weierophinney

Intuitive use of MutableCreationOptionsInterface

This implementation works in an unintuitive way. For example, if I wire a Form Factory like so:

'form_elements' => [
    'factories' => [
        ServerForm::class => ServerFormFactory::class,
    ],
],

Then the expected is true, I can call this on the SL and the options are properly captured in the Factory through MutableCreationOptionsInterface (thanks for the new trait btw, very handy).

$server_form = $this->getServiceLocator()->get( 'FormElementManager' )->get( ServerForm::class, [ 'test' => 123 ] );

With the code above, the factory's creation options are indeed [ 'test' => 123 ].

The problem with intuitive use arises in normal factories, the same rule isn't true (I can pass options to a factory through MCOI as a second Array argument). This wiring produces an unexpected result:

'service_manager' => [
    'factories' => [
        CartService::class => CartServiceFactory::class,
    ],
],
class CartServiceFactory implements FactoryInterface, MutableCreationOptionsInterface {
    use MutableCreationOptionsTrait;

public function createService( ServiceLocatorInterface $serviceLocator )
{
        var_dump( $this->creationOptions );

In the latter case, when I call this in a controller:

$sm = $this->getServiceLocator();
$cs = $sm->get( CartService::class, [ 'test' => 123 ]);

The dump in createService outputs 'null', which goes against what one would expect. It'd sure be convenient if they all worked under a same covenant.

I realize that the second argument to get on the main SM is $usePeeringServiceManagers, but since its use is implicit, it's probably an easier refactor to offer a stable rule in the boilerplate code, favoring the application developer.

I hope this gets considered, it'd be nice to pass array options to Factories... Give factories a chance to respond to controller conditions for example.

What exception should throw in v2 and v3

Misconfigured aliases can trigger an infinite loop during resolution

While looking at the changes done in the 3.0.2 release (I like looking at the diff when a release is announced with a perf improvement), I saw that resolveAliases can very easily lead to an infinite loop. It is just a matter of creating circular aliases (which can easily happen by mistake):

while (isset($this->aliases[$name])) {

$config['aliases'] = [
    'a' => 'b',
    'b' => 'a',
]

On a side note, I don't understand why the method receives the aliases as argument, while still accessing the property (containing the same array) internally.

canonicalizeName(): use str_replace instead of strtr function

Hello,

After profiling my zf2 app, I saw that strtr() function in ServiceManager::canonicalizeName() was a little bit "too expensive": 3.41MB memory (48% of the memory used), almost 4ms CPU time (5% of the total time).
strtr function is actually called 500 times (in my app) from canonicalizeName method.

After some tests, it seems that str_replace function is far more efficient than strtr (in this particular case at least): 132KB for memory and 704µs for CPU time.

I'm not a suporter of "over-optimization", but I think this little enhancement could be interesting

I can create a PR if you want.

Benchmarks (BlackFire)

My app

Benchmark on a working zf2 app (499 services use the strtr function).

VS

strtr() vs str_replace()

Isolated benchmark of str and str_replace functions. Almost 4 millions iterations. Use services string from existing zf2 app.

VS


Arthur Schwaiger

Service manager captures exceptions thrown by Factories

This is not necessarily an problem, but the fact that service manager captures exceptions thrown by Factories makes it harder to debug, and hard to treat them as well. I would suggest that, as an improvement, we remove the mechanism of catching these exceptions letting the programmer free to treat them as it pleases him.

If there is some constraint or business rule I'm missing, please let me know.

Catch statement in service manager should handle any exception code

Hello ;

I've a service factory like this:

/**
 * Class DatabaseServiceFactory
 * @package iMSCP\Service
 */
class DatabaseServiceFactory implements FactoryInterface
{
    /**
     * Create database service
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @return Database
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $config = Registry::get('config');
        $imscpDbKeys = new ConfigFileHandler($config['CONF_DIR'] . '/imscp-db-keys');

        if (!isset($imscpDbKeys['KEY']) || !isset($imscpDbKeys['IV'])) {
            throw new \RuntimeException('imscp-db-keys file is corrupted.');
        }

        $db = Database::connect(
            $config['DATABASE_USER'],
            Crypt::decryptRijndaelCBC($imscpDbKeys['KEY'], $imscpDbKeys['IV'], $config['DATABASE_PASSWORD']),
            $config['DATABASE_TYPE'],
            $config['DATABASE_HOST'],
            $config['DATABASE_NAME']
        );

        $db->execute('SET NAMESS `utf8`');

        return $db;
    }
}

Here, if an error occurs, a PDOException is throw. The problem is that the underlying catch statement from the service manager don't handle PDOException code and thus, the following fatal error is raised:

Fatal error: Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]]) in /var/cache/imscp/packages/vendor/zendframework/zend-servicemanager/src/ServiceManager.php on line 950

Note: Here the wrong query SET NAMESS is intentional.

Conflict in doc and implementation

The documentation states that a factory stored in a class would implement FactoryInterface but it doesn't reference which one. In ZF3 there still exists the ZF2 FactoryInterface which requires a 'createService' method while the ZF3 interface requires '__invoke'.

It is confusing to still have the ZF2 implementation out there when the clear direction in the docs in ZF3. Perhaps it should be removed?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.