Hi I have problem with Attribute class.
I created attribute class that takes RequestStack object as an argument. I need to check in this class if user was binded to request attributes, but there is no way to autowire it or pass an instance. If I pass it like, new RequestStack(), then I don't have access to any request, but there is no exception.
How can I fix it. I wanna use it like the symfony security bundle do it, Fe.
#[IsGranted('ROLE_USER')]
I tried:
configuring services.yaml
configuring in services.yaml arguments and binding service to it
rewriting it to annotaion, but result is the same
instancing RequestStack inside attribute class
I'm currently thinking to use reflection class, but I'm not sure if the RequestStack is going to contain all the requests (also the original/main one). It's important to me to keep track the request instance.
Related
I'm trying to do my own custom user provider,In Symfony tutorial From
"http://symfony.com/doc/current/security/custom_provider.html#create-a-user-class" This Site Tutorial But Couldn't Understand how to implement This site code in my localhost.Pleace help me some step by step process or a video process.
You have to create a class that implements this interface
Symfony\Component\Security\Core\User\UserProviderInterface
For that, you must create a public function called loadUserByUserName that receives as a parameter a string (the user name) then you have to implement the logic to get the user entity (you may need to call Doctrine and find it on the database or make some calls to an API...) whatever service you need must be injected.
You also have to implement the method refreshUSer() that I'm not sure when is used.
and finally, the suportsClass method that checks if a given classname is supported (usually you have to check it against your user class classname)
Once done, you have to setup this class as a service in tour services.yml file. Remember to inject here the dependencies (with setters or using the constructor, this is up to you)
Update 2020 (this should have been much sooner). There can be a new class for each controller action. Each controller can be named by the action it is going to do, with an Invoke() method. Consider "Action Domain Responder" (ADR).
Why do I want to do this? Controllers do not necessarily adhere to SRP, and I'm not about to go creating a new class for each of, what is effectively, a controller 'action'. Therefore, a controller should not have everything injected via constructor, but the relevant method being called should be able to state explicitly "I require these objects" and another method "these other objects".
As of Symfony 2.8, the Dependency Injection component now provides auto-wiring for your services if you provide autowire: true in services.yml.
I'm defining my controller as a service, like so:
test_controller:
class: AppBundle\Controller\TestController
autowire: true
My controller looks as follows:
class TestController
{
public function indexAction(TestClass1 $tc1, $id)
{
return new Response('The slug is: ' . $id);
}
}
You will notice I'm typehinting for TestClass, which is just an empty class. However, the following error appears when I refresh the page:
What do I need to change in my services.yml file to have auto wiring dependency injection in my controller method? Just a note, the issue isn't because I have an $id 'slug' afterwards. Removing it does nothing.
Edit: I've created a bundle allowing to do more or less what you want called DunglasActionBundle.
Disclaimer: I'm the author of the Symfony autowiring system.
The Symfony Dependency Injection Component (and the autowiring system is part of it) doesn't work that way. It only allows to automatically inject dependencies in the class constructor of services and knows nothing about controller classes, actions and other parts of the HttpKernel Component.
It's not currently possible to do what you want to do. Initially, the autowiring system has been designed for domain services, not for controllers.
It should be possible to bridge the autowiring system with controller parameters using a custom param converter. However, I'll suggest you take another way I've first described here:
There is another approach I want to discuss since several time but I
did not have the time to blog about it.
It's a derivate of/similar to the ADR pattern, applied to Symfony.
An action is a single class with a __invoke() method containing all it's
logic (should be only some lines of glue code to call the domain and
the responder).
Actions are registered as a service (it can be
automated using a compiler pass and some conventions, similar to how
we discover controllers right now, with the ability to override the
definition if needed)
On such action services, autowiring is enabled.
It means that almost as easy as current controllers to use for the
developper, but with an explicit dependency graph and a better
reusability. Only things that are really necessary are injected. In
fact, it's already doable to use such system with Symfony. We do it in
API Platform master. Here is one action for instance:
https://github.com/dunglas/DunglasApiBundle/blob/master/Action/PostCollectionAction.php
In this implementation I also rely a lof on kernel events to be able
to plug and play some sort of logic (persistence, validation...) in a
decoupled manner but it's out of scope.
http://laravel.com/docs/5.1/facades
Facades are listed on the linked page at the bottom. My question is... How do I override these service container bindings?
Example, the Request facade binds Illuminate\Http\Request with the key request. I want to create my own class which inherits from Illuminate\Http\Request and bind it with the request key, instead of the current class. And I can't find which service provider binds this.
So, I kind of did it. First I noticed these bindings were hardcoded in Illuminate\Foundation\Application::registerCoreContainerAliases() so I extended this class and overrode this method to change it. I also had to call this class now in bootstrap\app.php, but doing all this didn't help, I was still getting an instance of Illuminate\Http\Request.
So then I discovered that Illuminate\Http\Request was directly referenced in public\index.php so I tried changing it there to My\Very\Own\Http\Request and this worked, finally my implementation was being used.
Finally, I deleted my version of Application::registedCoreContainerAliases() and reverted bootstrap\app.php because everything is also working without this change.
I think the following answer would be very useful for you
https://stackoverflow.com/a/39648307/3912276
I quoted the most important part of the answer. It explains how you can replace/extend the Mailer facade
Write your own implementation of Mailer, extending Illuminate\Mail\Mailer, in which you can override the send method, implement your checks and call parent::send().
Write your own service provider (Extending Illuminate\Mail\MailServiceProvider), in particular re-implement the register method. It should create an instance of your own Mailer in place of Laravel's own. (You can copy most of the code from Laravel's register method).
Now, in your config/app.php file, in the providers array, replace Illuminate\Mail\MailServiceProvider::class, with your own provider.
You may access the (let's say) Doctrine service inside the controller, using:
$d = $this->getDoctrine()
now I want my controller to call another function (in another class) and I want that class to have access to all services. Is that possible without passing the services as variable?
You have to inject dependent services to your class or method. If you were thinking about some global object you might access everywhere than it's not the right way to go (and you can't actually access the container this way). You'd miss the whole point of dependency injection.
You can inject the services to your class two ways:
Manually
Let DIC do it
First solution requires you to pass the dependency yourself either way (constructor, setter, method).
The later solution means you define your class as a service and let container construct it and inject the dependencies. It can only be done if you can delegate object creation to DIC. It cannot be done with Entities for example.
Be careful with injecting whole container. It's not the best practice. You'd introduce dependency on a whole container which might have different services depending on the configuration. Dependencies wouldn't be clear.
I'm trying to pass the entity manager to a service but havent find a correct way yet. I want to complete remove the em from the controller so thats why I'm finding another way.
I was thinking of this options:
1. I could save it in the registry and then try to access it from the service object. can I access the registry from there?
2. Inject the em to a static variable of a base class for the services in the bootstrap.
What is the correct way yo do it?
thanks
I think generally the best way to do it is to pass the entitymanager as an argument to the constructor.
This allows you to easily replace the entitymanager for example when doing unit tests, and unlike your approaches of 1 and 2, it does not depend on behavior in a base class or global data (the registry is a lot like a global variable)
What you could do to avoid touching the EM in your controllers is using a dependency injection container, such as the one in Symfony2 or the one in ZF2 (not sure if that component is very stable yet).
Another perhaps slightly simpler approach would be to have a sort of a "service locator" object, which you would use in the controller to get instances of your services. You could initialize the locator in your bootstrap with the services, or perhaps with a factory class which creates them.
In any case you will probably require at least some kind of an intermediate object in the controller. Personally I don't really see an issue with simply using the EM itself, unless you have some other reasons besides just not wanting to.
There's nothing wrong, IMO, with letting your controllers know about the EM. I typically use a Zend_Application_Resource to bootstrap Doctrine. That resource facilitates a bootstrap resource called "doctrine" which has an EM available. The abstract controller implements and em() method, which returns the EM.
When instantiating service classes, the constructor simply injects the EM via a call to $this->em() at constructor time.
This is nice, as many times, simple controller actions don't need any special service class, but can instead get away with doing $entity = $this->em()->getRepository('Some\Entity')->find(1); In those cases, I don't see any reason for additional redirection via a service class.