Zend 2: how much can I expose to a Router? - php

I have a best practices question relating to building a custom router in Zend 2. I would like to use the service manager to get something in my router which would allow me to connect to an arbitrary data source (without exposing any info to my router) so that I can determine whether or not I can match that route.
For example, I would do something like this in my match() method:
$serviceManager->get('site_manager')->locateByRequest($request);
However, there isn't a clear way to access the service locator in a router. I found this article which essentially creates a custom factory so that you inject the service locator into your router:
http://www.zendexperts.com/2012/12/09/custom-routing-in-zend-framework-2/
Is this the best way to do this? Are there any other ideas or suggestions?
The main thing here is to NOT allow my router to know anything about the implementation of my so-called site_manager which may use a JSON text file, or MongoDB backend, or anything else for that matter. I want no dependencies and I want to expose no more than the method call from my above code example.
Ideas, comments, suggestions?

I think that injecting the whole service manager is just too much. I think it is ok to inject it in contollers, or in other helpers than could need to access many services, but for a helper component with a responsability as defined and as narrow as the router, i would prefer to:
create an interface, that defines what behavior should have the class that the router will work with.
inject just the service that the router needs, that could be any class implementing that interface.
With this, you can change the behavior of how the router resolve routes, changing the service that you are using to do it, but without having to change the routers code to access to something that should not be more than a configuration issue. With this you will get a better decoupling and have a more pure dependency injection.
Take a look at this article about Service Locator, Dependency Injection, and their differences
Also, it can be also interesting to take a look at the Strategy Pattern . This is more or less what im talking about. Instead of giving the router the knowledge and the ability to decide, it is just expecting a dependency to be injected, and inside that dependency is the implementation of some processes that the router needs, but which strategy to achieve the same result could be different, and the router doesn't really care about which one is being used.

Related

What the best way to use services with Symfony2

I got a huge Symfony project. I created many service and subservices to epurate the Controller and Services code.
In my code i instantiate these services with:
$this->get('MyServiceName')->myMethod($foo);
One of my coworker use the new keyword to instantiate the class:
$myservice = new Service();
$refid = $myservice->mymethod($foo);
So i wondering, is it a best practice? Should i rewrite that codeĀ ? What are the impact of this kind of code on the maintenability and the performance of the application?
If the service is defined in the Ioc container, then by all means use it from there, because it will be constructed by the container. It takes the responsibility of instantiating new classes away from the developer. If the explicit dependencies change, you will only need to change them in container, not hunt them in the whole project code. This also in most cases has the performance benefit, because some classes need to be instantiated only once. In any way, talk to your co-worker, why he does it like this.
I always use the first way (ie. using the service container) because with Symfony's dependency injection you don't need to worry about dependecies and/or parameters; I've never used the second way (ie. instantiating a service "by hand" with the new keyword) and I'm pretty sure that it is the worst way.
By the way, you should check out the official "best practices" guide and these blog posts by Fabien Potencier.

Testing behaviour of classes with deep nested dependencies

I am starting using Behat and I was thinking what is the correct way to do something like this:
I am testing system behaviour with Behat (the domain, not web) and i want to test behaviour that uses UserService class. UserService takes UserRepository (Interface) as an argument. Should i create the UserService object in the context or should i take it from some dependency injection container (which i currently don't have since i want to model the domain first)? Or should i maybe create a factory to construct the UserService? Should I mock those dependencies?
The problem here is, that there may be multiple implementations of UserRepository and i want to test the one the system uses (hence taking UserService from DI container). I do not know which implementation i am going to use at the time of writing the feature file/context. Probably just some dummy FilesystemUserRepository just to pass the tests.
If I used the FilesystemUserRepository in contexts, then after i decide to move to DatabaseUserRepository later in development i would have to rewrite all the contexts that use UserService class.
Is there some best practice how to do this?
I usually start with creating everything in my context's constructor, as it's a phase I move back and forward a lot and I don't want to be distracted by having to create service definitions. At this phase code might change a lot, so it would be rather inefficient anyway.
Later on, I create service definitions in the application's container. With the Symfony container it is very easy to inject those services directly into your context. Another advantage is that with Symfony environments you can actually replace some services in test environment. I actually use this a lot, as I prefer to use in-memory repositories in acceptance tests, rather than those based on a database.
On some projects I didn't take the second step, and left all the service initialization in Behat's context class. It worked well too.

Understanding Zend DI example from tutorial

I cannot to understand this example:
// inside a bootstrap somewhere
$di = new Zend\Di\Di();
$di->instanceManager()->setParameters('MyLibrary\DbAdapter', array(
'username' => $config->username,
'password' => $config->password
));
// inside each controller
$movieLister = $di->get('MyMovieApp\MovieLister');
foreach ($movieLister as $movie) {
// iterate and display $movie
}
How another part of source code ("inside each controller") knows about $di variable?
Is it not completed example? Can anyone show how I can to use DI container in my controllers?
Tutorial page: http://framework.zend.com/manual/2.0/en/modules/zend.di.quick-start.html
Examples in Zend Framework 2 tutorials describe how to use particular component outside of whole framework environment to let you understand better its features.
One of basic ideas of Zend's developers was always to create a package of independent libraries (with only some dependencies between them when needed) to let you choose which part of framework you want to use. For example you could take DI class and use it in some other framework. It would work fine. When they say
inside controller
they mean
not necessarily our controller you any others too
Please note that ZendSkeletonApplication is just an example of use for ZF2, but it doesn't actually belongs to the framework itself.
So the way that you will get Di object in any place depends on your application architecture. If you think in context of using whole ZF2, then you probably won't create Di object on your own at all. Di will be used by ServiceLocator which will let you manage your services (objects, factories etc.).
I think you should read this one to get a perceptive for a future research :
http://zend-framework-community.634137.n4.nabble.com/Services-Instances-Dependencies-in-ZF2-td4584632.html
You also should check out :
https://github.com/zendframework/ZendSkeletonApplication
Roughly speaking , ServiceManager in Zend/Mvc/Application does lots of Di work.
The example is missing the indication on how to configure the controller to have MyMovieApp\MovieLister injected into it, rather than invoking Zend\Di\Di::get(); the latter assumes that the DIC itself has been injected into the controller, which is indeed an anti pattern.
To be honest, that's actually a downside of the current default implementation of ZF2 mvc controllers, which have the ServiceManager (which has superseded Di mainly for performance reasons) injected into them. This issue has been discussed extensively and it will very likely be dealt with in ZF3.
For the time being, just use the ServiceManager, ignore the fact that it is injected into controllers, and use constructor injection inside concrete service factories. That is the best acknowledged way to do IoC in ZF2 at the moment, it's solid and by no means a bad practice.

Is there a good way to keep the number of parameters (dependencies) passed to a controller down?

So in Silex, I am attempting to get the $app parameter out of my controller actions and just pass in the dependencies that are relevant to the controller/action.
Generally my controllers have these shared dependencies:
Template engine
Session provider
Translation provider
URL generator
Validation provider
I've got a base Controller class to accept these on the constructor by default. The controllers inheriting from it also end up taking those parameters as well. Additionally they take other parameters, such as an object repository/store (such as a user repository in an authentication or user controller).
I end up registering the controllers in Silex with at least 5 parameters to the constructor when it seems like I don't see a lot of that in other applications. Feels like I'm doing it wrong.
I also realize that I'm complaining about the same thing that the Pimple DI container "fixes," but using it also seems not quite true to the DI philosophy.
My question: Is there a better way to do what I'm doing?
Yes there are alternative solutions.
The first one is to "group" your parameters into new classes like ControllerUtil or things of the sort. That's not always easy or possible though, so I'm not a particular fan of that.
Benjamin Eberlei explains this approach in this blog post: Extending Symfony2: Controller Utilities
The second is to use alternative to constructor injection, like property or setter injection. This is not as clean as constructor injection, but it is extremely practical.
Given controllers are generally not the kind of components you want to reinject, reuse or unit-test a lot, so this is an acceptable compromise IMO. I've been using that method for about a year and I can't go back.
Here is a related blog post I wrote on that subject: Controllers as services?

How do I properly inject dependencies (services) into non-service classes in Symfony2?

I have read the service container chapter in the Symfony2 book multiple times and read SO answers and other resources regarding the topic, but I still just don't seem to get it.
So far, everything I've read has drilled one main truth into my head: the container itself should (practically) never be directly injected into a dependent. This seems to work fine for providing dependencies to other services, but what if an entity in my model wants to inspect the current security context, for instance?
I'm aware that I can implement ContainerAwareInterface and then call setContainer() from a container-aware context to gain access to the container itself in this case, but isn't this the same as injecting the container from the service configuration which is to be avoided at all costs?
What you describe is just bad design. Your model shouldn't be dependent on the service container. If you need to perform some security checks then you would create a service that has the necessary dependencies injected to it and then pass your model objects to it.
By your example it sounds like you're trying to do validation which is described here http://symfony.com/doc/master/book/validation.html and works much like I stated.

Categories