{"action":"created","issue":{"url":"https://api.github.com/repos/zendframework/zf2/issues/7133","labels_url":"https://api.github.com/repos/zendframework/zf2/issues/7133/labels{/name}","comments_url":"https://api.github.com/repos/zendframework/zf2/issues/7133/comments","events_url":"https://api.github.com/repos/zendframework/zf2/issues/7133/events","html_url":"https://github.com/zendframework/zf2/pull/7133","id":54676423,"number":7133,"title":"[WIP - ZF3] Refactored SM","user":{"login":"bakura10","id":1198915,"avatar_url":"https://avatars.githubusercontent.com/u/1198915?v=3","gravatar_id":"","url":"https://api.github.com/users/bakura10","html_url":"https://github.com/bakura10","followers_url":"https://api.github.com/users/bakura10/followers","following_url":"https://api.github.com/users/bakura10/following{/other_user}","gists_url":"https://api.github.com/users/bakura10/gists{/gist_id}","starred_url":"https://api.github.com/users/bakura10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bakura10/subscriptions","organizations_url":"https://api.github.com/users/bakura10/orgs","repos_url":"https://api.github.com/users/bakura10/repos","events_url":"https://api.github.com/users/bakura10/events{/privacy}","received_events_url":"https://api.github.com/users/bakura10/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":23,"created_at":"2015-01-17T21:40:45Z","updated_at":"2015-01-28T23:40:26Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/zendframework/zf2/pulls/7133","html_url":"https://github.com/zendframework/zf2/pull/7133","diff_url":"https://github.com/zendframework/zf2/pull/7133.diff","patch_url":"https://github.com/zendframework/zf2/pull/7133.patch"},"body":"Hi everyone :),\r\n\r\nUntil we have proper split of components, let me submit a refactored service manager. There are a few features that I have not completley backported (proxy and delegators). As all my other refactors, this emphasize on performance, and I've tested it carefully with BlackFire.\r\n\r\nThe main changes is a change of interfaces: now everything is a factory, and each factory is callable, so this removes all the needed check against FactoryInterface or callable.\r\n\r\nFurthermore, there is no longer concept of invokables: invokables are implemented as a built-in factory:\r\n\r\n```php\r\nreturn [\r\n   'service_manager' => [\r\n       'factories' => [\r\n             MyInvokable::class => InvokableFactory::class\r\n       ]\r\n  ]\r\n];\r\n```\r\n\r\nIn one of my previous idea, I've introduced the concept of \"abstract_factories_map\". In this refacotr, I've been able to remove this additional concept while keeping the idea of being able to map multiple class names to the same factory. This is make possible because the interface of a factory now has the requested class name as second parameter.\r\n\r\n\r\nFinally, this introduce a simplification to plugin manager, and remove the need of calling \"getServiceLocator\". While using ZF2 extensively, I've realized that, in a factory of a plugin maanger, I nearly never need to fetch other deendencies from this plugin manager, but rather calling dependencies from the main service locator. This refactor therefore changes the context of the factory in a plugin manager.\r\n\r\nIn ZF2, if you fetched a service from a plugin manager, you had to call \"getServiceLocator\" to retrieve the main service locator. In this refactor, the service locator is actually the main service locator.\r\n\r\nFinally (bis), this removes aliases from the main service manager for performance reasons. Now that we have ::class, the only reason to use alaises is for very specific plugin managers, like view plugin managers or controller plugin managers. Therefore, I've introduced an addditional, more specialized plugin manager called \"AliasesPluginMAnager\", that brings back the aliases.\r\n\r\nThis make the component MUCH MUCH more efficient (tbh I think there is no other way to make it faster while preserving all features), and more coherent, especially when it comes to plugin maangers."},"comment":{"url":"https://api.github.com/repos/zendframework/zf2/issues/comments/71940605","html_url":"https://github.com/zendframework/zf2/pull/7133#issuecomment-71940605","issue_url":"https://api.github.com/repos/zendframework/zf2/issues/7133","id":71940605,"user":{"login":"bakura10","id":1198915,"avatar_url":"https://avatars.githubusercontent.com/u/1198915?v=3","gravatar_id":"","url":"https://api.github.com/users/bakura10","html_url":"https://github.com/bakura10","followers_url":"https://api.github.com/users/bakura10/followers","following_url":"https://api.github.com/users/bakura10/following{/other_user}","gists_url":"https://api.github.com/users/bakura10/gists{/gist_id}","starred_url":"https://api.github.com/users/bakura10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bakura10/subscriptions","organizations_url":"https://api.github.com/users/bakura10/orgs","repos_url":"https://api.github.com/users/bakura10/repos","events_url":"https://api.github.com/users/bakura10/events{/privacy}","received_events_url":"https://api.github.com/users/bakura10/received_events","type":"User","site_admin":false},"created_at":"2015-01-28T23:40:26Z","updated_at":"2015-01-28T23:40:26Z","body":"To be honest I cannot really talk about Di because I have never used this component (except at the very beginning of ZF2 development when we didn't have the Service Manager).\r\n\r\nActually, regarding the key, I want to encourage people to use ::class, but it's just a key. You can still use \"doctrine.foo\" if you want, as soon as it resolves to a factory that is able to create it. The only use case is for invokables.\r\n\r\nIn this refactor, everything is a factory (it simplifies implementation and avoid many checks during creation). \r\n\r\nBefore:\r\n\r\n```php\r\nreturn [\r\n        'invokables' => [\r\n\t\tMyInvokable::class => MyInvokable::class\r\n\t],\r\n\t'factories' => [\r\n\t\tMyObject::class => MyObjectFactory::class\r\n\t]\r\n]; \r\n```\r\n\r\nAfter:\r\n\r\n```php\r\nreturn [\r\n\t'factories' => [\r\n\t\tMyInvokable::class => InvokableFactory::class,\r\n\t\tMyObject::class => MyObjectFactory::class\r\n\t]\r\n];\r\n```\r\n\r\nInvokableFactory is a built-in factory, and it expects that the service key is actually the FQCN of the class.\r\n\r\n> Code should be reusable and subtyping a class just for retrieving a different parameterized shared instance (i.e. another DocumentManager or db adapter) is awful.\r\n\r\nActually, this refactor comes with a solution to that. The `get` method always accept an optional second parameter for options. Contrary to ZF2 where it was only transferred to invokable, in this refactor it is transferred everywhere (even for delegators). This means that your factory is aware of the creation (it is the third parameter of the factory interface), and you can therefore parameterized creation:\r\n\r\n```php\r\n$instance1 = $this->serviceLocator->get(MyObject::class, ['foo' => 'bar']);\r\n```\r\n\r\nThe only limitation for now is that the service must be marked as non-shared (otherwise, the second time you call the get method, it will return the same instance, without going back to the factory. Actually, I think that we could be smarter here, and assume that if we have options, *there are chances* that it will be called with another set of options, and hence make this as a criteria to not cache the service. Just an idea, though."}}