I am learning to use symfony2 but i am having hard time in learning what is service layer and where it can be used.
How can i better understand about service layer in symfony2
I'll try my best to explain services, but the Symfony2 docs do a better job than I'll be able to.
At it's core, a service is simply a class. A class becomes a service when it is registered with Symfony2's Dependency Injection Container (or just Container for short.) At this point, the class is part of an application's Service Layer.
A service may have dependencies (and often times, it does), but it is not required to. A service is often used as a dependency for other services. Let me give you an example:
You have a class used to send email, called EmailSender
You have a class that contains the instructions on how to send email over SMTP, called SmtpTransport
EmailSender has a dependency in the form of SmtpTransport. In other words, for EmailSender to be able to do its job, it needs an instance of SmtpTransport to be injected into it. (Note that although EmailSender has a dependency, SmtpTransport does not.)
Say you need to use EmailSender in five different places in your app. In each spot, you may have code like this:
$emailSender = new EmailSender(new SmtpTransport());
$emailSender->send($email)
That's not a lot of code (since EmailSender only has one dependency), but what happens when you decide that instead of using SMTP, EmailSender should use a transport class for sendmail? You'd have to edit each block of code in order to update it.
The alternative is to register EmailSender and its dependencies as services.
Registration looks like this:
// YourApp/YourBundle/Resources/config/services.yml
services:
smtp_transport:
class: YourApp\YourBundle\Email\SmtpTransport
email_sender:
class: YourApp\YourBundle\Email\EmailSender
arguments:
- #smtp_transport
Now, to use it (from a container aware context):
$container->get('email_sender')->send($email);
Notice how much simpler and cleaner it is to actually use the class to send emails? Sure, you have to do the work to register the service first, but that's trivial and only has to be done once.
Imagine that EmailSender has three dependencies, instead of one. By using services, you only need to modify the service registration without having to change your implementation code (the code used to send the email).
In short, the service layer acts as a central repository for classes that a) have one or more dependencies b) need to be used in a 'global' scope. By fetching these service classes from the Dependency Injection Container, you end up with less redundant code and an easier way to make wide reaching changes.
I may be wrong, but I think Symfony2 is the first PHP framework to implement a dependency injection container. As such, a lot of PHP devs may be unfamiliar with the concept of services. I definitely suggest making sure you understand it fully, as you'll see that it's a very powerful tool. Plus, the concept of services is in no way limited to Symfony2 or even PHP - you'll be able to take advantage of this concept in a wide variety of frameworks and languages.
Try Fabien's series of articles on the subject: Dependency Injection.
Related
I have a question, why symfony use a service instead of "use" directly into a controller.
I have a class named DisplayManager and I declare this class as a service.
Why not use DisplayManager directly into a controller using "use DisplayManager"
Thanks
The advantage of thinking about "services" is that you begin to think about separating each piece of functionality in your application into a series of services. Since each service does just one job, you can easily access each service and use its functionality wherever you need it. Each service can also be more easily tested and configured since it's separated from the other functionality in your application. This idea is called service-oriented architecture and is not unique to Symfony or even PHP. Structuring your application around a set of independent service classes is a well-known and trusted object-oriented best-practice. These skills are key to being a good developer in almost any language.
http://symfony.com/doc/current/service_container.html
Questions that suggest define your class as service:
My class is used in several places in my application?
My class has many dependencies?
There is a good example for these topics here:
http://symfony.com/doc/current/service_container.html#what-is-a-service-container
Performance Advantage:
The service has a default condition that allows to the related class instantiate it only once.
Imagine a class with 5 dependencies (and these as well with their dependencies) and has been used in 20 parts of our system, what if we do not define this class as a service?
However define your class as a service is not required, this will always depend on the architecture of your system and the mission to be fulfilled its class, in addition to the dependencies you have.
Controllers are made only to take requests (http) and produce a response (http). No more. Never.
Services are totally independent classes that you can use everywhere. Moreover, with services, you can take advantage of DependencyInjection.
Services are more testable.
Services (like controllers and whatever) must have only a responsibility.
And so on ...
I have written my own logging class that I defined as a service and placed inside the AppBundle\Services namespace. I can access it easily inside the controller when I want to log something, but what about accessing it from other services?
I'd have to pass the logging service as a dependency injection, but what if I have more than 100 services defined (services, modules, event listeners etc. etc.), each of them having their own dependencies? It would create a mess.
I've been also thinking about extending some core service that defines the logging service, but then again - all my services, modules, event listeners, would have to extend one core class.
What's the best approach to solve this?
May be a good approach would be to rethink responsibilities in order to avoid the creation of too many services.
About the fact of consumming service itself, I think there are no problem to reuse as much as you need along the application lifecycle. In fact, symfony will handle the instantiation and you will be only consumming it as a service.
Another approach will be to create base classes for all your core objects, let these base classes to handle log services and final classes will log in a implicit way. This will not save service calls but almost will leave you to handle it manually.
If you think you will use your log feature in several projects then I recommend you to move to vendors folder and use it as external module, synchronised via composer to your github account. It will be like your own 3rd party product.
If you are not a symfony friend then you can break the law and create your own singleton pattern available by autoloading, but I think you should take advantage of the powerfull symfony service structure.
I'm trying to add Symfony 2.0 ACL to my frameworkless PHP application. Because of the lack of documentation on how to use Security component as standalone I've got totally confused and I've got stucked with questions: What class to include first? Which object to instance? Is it possible to be used without models and controllers?
Any suggestion on how to start or any good link?
Thanks
The SecurityServiceProvider for Silex might be a good place to start, as it integrates all of the essential component services in a single file. Although large, you'll probably find it much easier to digest than Symfony2's SecurityBundle.
In the interest of maintaining your sanity, you should consider using a service container to organize all of these objects. In the aforementioned provider class, the Silex Application class is a Pimple instance, so you should be able to port it stand-alone Pimple with modest effort. I saw this because integrating a Pimple service container into your application should be less invasive than adopting the Silex framework.
Once you have the essential security component classes working, you should be able to following along with the ACL documentation and add additional services to your container as needed. At that point, the ACL-specific sections of the SecurityBundle might prove helpful, as you can focus in on the relevant bits. Keep in mind that there are multiple cookbook entries for ACL in the documentation.
What class to include first?
You will most likely need to include at least parts if not all of the security core, then which ever ACL implementation that you are wanting to use. You can look at the dependencies that are listed in the beginning of the ACL implementation and see what they extend. For instance, the ACL/DBAL has the following dependencies called in the header:
namespace Symfony\Component\Security\Acl\Dbal;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Statement;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Domain\Acl;
use Symfony\Component\Security\Acl\Domain\Entry;
use Symfony\Component\Security\Acl\Domain\FieldEntry;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException;
use Symfony\Component\Security\Acl\Model\AclCacheInterface;
use Symfony\Component\Security\Acl\Model\AclProviderInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
But you would probably need to check each of those listed for their dependencies, and load those as well.
I would back-track through the dependencies, and keep track of what needs what. Cull those classes out into a separate location so that you have only what you need, and use some error trapping to determine that you have it all.
Which object to instance?
Your ACL. If the dependencies are all determined, and loaded, then you should be able to instantiate the ACL class object.
Is it possible to be used without models and controllers?
To be honest, I am not sure that using ACL outside of S2 is possible without a WHOLE lot of work, but if you can get it instantiated with everything it needs, then you should be able to use the object without an MVC model.
Unfortunately, from what I understand of S2, it is a full stack framework, and meant to be an all or nothing kind of thing. but if I were going to try and make it work, this would be the way I would go about it.
If u want to understand how to use use symfony2 component and how to integrate that within your project then read Fabien Potencier blog 'create your own framework'
post that will definitely help u to understand core of framework from and how to bootstrap symfony2 component in your project
there is also good document for ACL on symfony website
I'm currently refactoring my Zend Framework based PHP library from using a service locator to (constructor) dependency injection (DI). I feel that it improves my code a lot, but I'm not sure if I should inject all dependencies. A service locator seems easier for dependencies which are used a lot and are unspecific. I have the following dependencies which I still access using a service locator:
A Zend_Translate object (I need to translate messages everywhere).
A Zend_Locale object (stores the current language)
A Zend_Config object (a lot of things are configurable by ini-file)
Instances of utility classes (for array and string manipulation)
If I injected these dependencies, they'd clutter my constructors and distract from the specific dependencies. For testing, I can just set up these dependencies in my service locator before running the tests. The pragmatist in me says I'm doing just fine, but the purist says I should go all the way with DI.
Would you recommend DI for these types of objects or not?
When it comes to the concern about cluttering the constructors, it's most likely a code smell that the classes are violating the Single Responsibility Principle. Constructor Injection is very beneficial here because it make this much more obvious.
Some people also worry about injecting dependencies which are only rarely used, but that's not a problem either. When it comes to creating object graphs, performance is rarely a problem, and even if it is, the Virtual Proxy pattern can fix it.
In short, there's no reason to ever use a Service Locator. There's always a better alternative that involves proper inversion of control.
You've probably heard of the Fat Model/Thin Controller vs. Thin Model/Fat Controller distinction. I recently heard that you can have something in between where some of the logic from the model goes into a service layer. How common is this? and do you know of (or can think of) any real examples that illustrate it?
Martin Fowler describes the Service Layer pattern of his great book Patterns of Enterprise Application Architecture. If you care about questions like the one you asked, you should read this book.
One use that comes to my mind is managing database transactions. Some people try to encapsulate starting and committing transactions in their domain models. But then they get confused when domain models invoke other domain models that also try to start and commit db transactions. So which model really gets to decide if a transaction is committed or rolled back? And what do you do if a given model is used in different ways by different clients?
The Service Layer is a solution for this, because this is the layer in which you can start and commit work that involves multiple domain models.
As for how common this is, I don't think it's common at all. Most people using Zend Framework (or any other PHP or Ruby framework) have just barely moved from "Active Record solves everything" to the new shiny, "Data Mapper solves everything." It seems this community learns only one new pattern every five years. They won't get to Service Layer for a while.
Re comment from #ktutnik:
No, the Service Layer pattern is different from Repository pattern. Repository is about abstracting database access so you can use a database like a Collection. Service Layer is about encapsulating complex application operations.
Another way of thinking about them is their relationship to the Domain Model. The Repository is used between the Domain Model and the database. Whereas the Service Layer uses one or more Domain Models.
Service Layer ---> Domain Model(s) ---> Repository ---> DBAL
Service layer advocacy is relatively new and still subject to a variety of interpretations. I think it means having a layer that leverages multiple domain models which the controllers call (I may be simplifying it too much though). I recently developed a website making use of this and practical advantages I've encountered are:
Features as a service helps with scalability. If you have an image service that initially uses the local service to do it's work it becomes easier to have that service point to another server or some 3rd party without having to make sweeping updates
Flexibility. Half way through the project I decided to change a core piece of functionality and was able to do so painlessly; allowing me to quickly weigh the pros and cons of the update. This flexibility is useful when rapid prototyping and instills a certain confidence because if you need to revisit something it's not going to be a nightmare.
Extensibility. I have already identified services in my application what I can forsee opening to other developers or other widgets, mobile apps in the future. Doing so in theory is just a matter of adding authentication and authorization to the service (because the features are already in it's own layer and I don't have to spend time trying to decouple what I want to expose from the rest of the code base).
Services are easy to add and drop (maybe this belongs with one of the earlier points). I have services that a specific to a specific stage in the project (e.g. invite only stage) that I can drop once that phase is over.
I think it has practical advantages and a key to success in implementation is having a good way to manage the services in the application. I use symfony's dependency injection component
See ZFEngine it's cmf on ZF with service layer realisation