{"action":"created","issue":{"url":"https://api.github.com/repos/zendframework/zf2/issues/7388","labels_url":"https://api.github.com/repos/zendframework/zf2/issues/7388/labels{/name}","comments_url":"https://api.github.com/repos/zendframework/zf2/issues/7388/comments","events_url":"https://api.github.com/repos/zendframework/zf2/issues/7388/events","html_url":"https://github.com/zendframework/zf2/issues/7388","id":65389289,"number":7388,"title":"Adding getServiceLocator() to ServiceLocatorInterface","user":{"login":"manuakasam","id":1087280,"avatar_url":"https://avatars.githubusercontent.com/u/1087280?v=3","gravatar_id":"","url":"https://api.github.com/users/manuakasam","html_url":"https://github.com/manuakasam","followers_url":"https://api.github.com/users/manuakasam/followers","following_url":"https://api.github.com/users/manuakasam/following{/other_user}","gists_url":"https://api.github.com/users/manuakasam/gists{/gist_id}","starred_url":"https://api.github.com/users/manuakasam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manuakasam/subscriptions","organizations_url":"https://api.github.com/users/manuakasam/orgs","repos_url":"https://api.github.com/users/manuakasam/repos","events_url":"https://api.github.com/users/manuakasam/events{/privacy}","received_events_url":"https://api.github.com/users/manuakasam/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":12,"created_at":"2015-03-31T07:44:52Z","updated_at":"2015-04-22T08:54:12Z","closed_at":null,"body":"Hey guys,\r\n\r\nso I was just reading the newest Blog by @samsonasik and it got me thinking. Here a link to the article https://samsonasik.wordpress.com/2015/03/31/zend-framework-2-using-__invokepluginmanager-manager-in-services-factory/\r\n\r\nBasically it teaches the approach of using Invokable classes as ServiceFactories. And I don't like it.\r\n\r\n# Where is the Problem?\r\n\r\nAs a community we are teaching newcomers to differentiate between two kinds of services: `invokables` and `factories`. If now the community starts to only use `invokables` because of proper type-hinting, then newcomers will simply be blown away with a bit of \"wtf?\".\r\n\r\nWhile it is perfectly fine to come up with new ways of doing things, I feel that the problem is of a different kind of nature and that we should rather focus on solving said problem than to find workarounds for it.\r\n\r\n# Analyzing the Problem\r\n\r\nService-Factories for the default `ServiceManager` we're writing a Factory like this:\r\n\r\n```php\r\nclass FooFactory implements FactoryInterface\r\n{\r\n    public function createService(ServiceLocatorInterface $sl) \r\n    {\r\n        return new FooService(\r\n            $sl->get('FooDependency')\r\n        );\r\n    }\r\n}\r\n```\r\n\r\nAll nice and clean. Both parties, Users and Code-Inspection, are very happy.\r\n\r\nHowever when we're outside the scope of the normal `ServiceManager`, for example when writing Controller-Factories, things are changing. Take a look at this example:\r\n\r\n```php\r\nclass BarControllerFactory implements FactoryInterface\r\n{\r\n    public function createService(ServiceLocatorInterface $sl) \r\n    {\r\n        /** @var $realSl ControllerManager\r\n        $realSl = $sl->getServiceLocator();\r\n        \r\n        return new BarController(\r\n            $realSl->get('BarDependency')\r\n        );\r\n    }\r\n}\r\n```\r\n\r\nAnd to me this is where we run into issues. While we're successfully tricking our IDE into giving us proper code-completion, code-inspection tools like Scrutinizer are analyzing the variable based on what we pass into the factory. That that's only the `ServiceLocatorInterface`. An interface that does not know about `getServiceLocator()`.\r\n\r\nFrom a programming point of view I do understand why we're using the shared interface. However the issue that I have - and I'm sure I can't be the only one - is, that we're relying on something that isn't defined by the interface. In essence that's bad design.\r\n\r\n# What can be done?\r\n\r\nNow I haven't given this many thorough thoughts yet, but as far as a quick brainstorm is concerned I see two possible solutions.\r\n\r\n## Create new Interfaces\r\n\r\nThis would mean we have a new Interface for each of the `ServiceManager`-aware Managers like the `ControllerManager`, `FormManager`, etc.., etc... This interface would then implement `getServiceLocator()`. In turn this would allow for  a better code-only-documentation and both users and code-tools would be more happy.\r\n \r\n## Add getSl to the ServiceLocatorInterface\r\n\r\nThis change - in my opinion - would be the one that has the least of effects. When adding `getServiceLocator()` to the `ServiceLocatorInterface` the problem with the hidden dependency on all other factories would be solved instantly. The new issue it raises is that the `ServiceManager` itself also implements the `ServiceLocatorInterface`. So we'd have to implement it like this:\r\n\r\n```php\r\nclass ServiceManager implements ServiceLocatorInterface\r\n{\r\n    public function getServiceLocator() \r\n    {\r\n        return $this;\r\n    }\r\n    \r\n    // rest of class...\r\n}\r\n```\r\n\r\nThis **obviously** isn't ideal. It would allow for ridiculous code-chaining like: \r\n\r\n```\r\n$sl->getServiceLocator()->getServiceLocator()->getServiceLocator()->getServiceLocator()->get('RickRolled')\r\n```\r\n\r\nthough personally I don't see it of this much as an issue. Would anyone really do this?\r\n\r\n# Summary\r\n\r\nTo sum it up:\r\n\r\n- The Framework implies the usage of something that isn't defined by an interface\r\n- Workarounds do exist but the raise yet another new learning barrier for starters\r\n- In my opinion we should change this fact, the way to do so should be open for discussion\r\n\r\nWhat are your thoughts about this? Do you share the concern? Got alternate solutions? Is this an issue at all?\r\n\r\nFeedback - as always - much appreciated.\r\n"},"comment":{"url":"https://api.github.com/repos/zendframework/zf2/issues/comments/95081234","html_url":"https://github.com/zendframework/zf2/issues/7388#issuecomment-95081234","issue_url":"https://api.github.com/repos/zendframework/zf2/issues/7388","id":95081234,"user":{"login":"RalfEggert","id":1562549,"avatar_url":"https://avatars.githubusercontent.com/u/1562549?v=3","gravatar_id":"","url":"https://api.github.com/users/RalfEggert","html_url":"https://github.com/RalfEggert","followers_url":"https://api.github.com/users/RalfEggert/followers","following_url":"https://api.github.com/users/RalfEggert/following{/other_user}","gists_url":"https://api.github.com/users/RalfEggert/gists{/gist_id}","starred_url":"https://api.github.com/users/RalfEggert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RalfEggert/subscriptions","organizations_url":"https://api.github.com/users/RalfEggert/orgs","repos_url":"https://api.github.com/users/RalfEggert/repos","events_url":"https://api.github.com/users/RalfEggert/events{/privacy}","received_events_url":"https://api.github.com/users/RalfEggert/received_events","type":"User","site_admin":false},"created_at":"2015-04-22T08:54:12Z","updated_at":"2015-04-22T08:54:12Z","body":"Should be marked for ZF3 milestone, shouldn't it?"}}