There are many questions regarding loading custom helper classes in Laravel. However, none of them focus on the loading them with proper initialization.
As of Laravel version 5.3 we can use psr-4 autoloading which is autoloading the entire app/ directory. However, classes are loading but never initialized.
I have my helper class inside the app/helpers/support.php. This class has a constructor, where I want to load some important configuration in order to make the helper usable.
So how can I load my helper but ALSO initialize it properly in Laravel? Right now I am simply working-around the problem by using new \App\Helper\Support(); inside AppServiceProvider.php.
Edit: I'm using the following approach to maintain my helper class:
Best practices for custom helpers on Laravel 5
It seems like what you have is a service. Rather than creating an instance, you can declare it in your app service provider and inject it as a dependency when you need it.
In your register method:
$this->app->bind(\App\Helper\Support::class);
You can now use dependency injection to get an instance of your class. You can also make an instance like this:
app()->make(\App\Helper\Support::class);
If you only want one instance to exist at any given time, use singleton rather than bind.
I recommend reading the service container documentation:
https://laravel.com/docs/5.5/container
Related
I have some issues regarding the zf2 to zf3 migration of my application. I've gone through the migration guides and started the migration process as describe there.
According to the migration guide, there is no serviceLocator available into controllers anymore. And I used to use it within each and every controller action to inject the config variable array (located in module.config.php), Doctrine MongoDB DocumentManager and the Doctrine EntityManager into the Models where they are needed. Now I'm getting so many deprecated warnings messages as below;
PHP Deprecated: Usage of
Zend\ServiceManager\ServiceManager::getServiceLocator is deprecated
since v3.0.0; please use the container passed to the factory instead
in
/var/www/html/LeapX/vendor/zendframework/zend-servicemanager/src/ServiceManager.php
on line 169
Since I need to access config variables and inject the Doctrine DocumentManager and Doctrine EntityManager into my Models, I had to call $this->getServiceLocator() within my controllers. Let me know how to fix this issue. Is there any possibility to directly inject these dependencies into my Model classes? Should I need to use factories for Models?
And the other question is when it comes to factories regarding the controllers, Should I need to create individual factory for each and every controller of my application? There are quite a lot of number of controllers spread within few Modules in the application. If I add dedicated factory for each and every controller there will be double the number. Let me know the best way to do this.
From what i have read myself, it is no longer possible to call getServiceLocator() from controllers, they removed it since it promotes antipattern.
Here's a blog post from Matthew himself on this issue:
https://mwop.net/blog/2016-04-26-on-locators.html
Another explanation from the guy himself here (shorter, might be easier to digest):
https://github.com/zendframework/zend-mvc/issues/89
I am currently also in the process of trying to migrate a ZF2 (2.4.10) project to ZF3 and face the same issue.
I personally agree with the recommendation to explicitly define dependencies of your classes and controllers instead of (over)using getServiceLocator() method, though depending on your code, refactoring lots of code for this purpose might seem to be a PITA.
Alternatively, this can probably help (though, i can't say for sure since i haven't tried this myself):
http://circlical.com/blog/2016/3/9/preparing-for-zend-f
I'm a novice developer working on an existing Laravel app. I'm looking through the project and I don't see any controllers constructed anywhere but the controllers all have constructor functions.
Is this a Laravel thing or am I just missing something? Is controller instantiation handled in the routes or something? If so, is it bad practice to call a controller constructor manually?(although I can't think of a case offhand where you would want to do this)
From the docs: "The Laravel service container is used to resolve all Laravel controllers."
And: I often create a base controller in my apps, therefore I also have constructor in my extended controllers. It could also be useful to inject dependencies "properly" like shown in this example:
https://laravel.com/docs/5.2/controllers#dependency-injection-and-controllers
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.
Without using CodeIgniter I would normally just do;
require_once("object");
test = new object();
How would I go about doing this in CodeIgniter?
Edit: for example this class could be a video game object. It might be holding a number of variables, for example title, age,description etc. There would also be variable get/set methods for the above variables.
For example, I might use this class to help contain the information created by a database search.
Codeigniter uses the Singleton design pattern and most of your classes are loaded using the loader class (as needed, in a constructor, or in the autoload config file) and are then available via the Codeigniter Super Object $this->my_model. As Kai Qing noted, using a Model would typically entail:
// In the constructor, controller method, or autoload
$this->load->model('my_model');
// Then to use a method simply
$this->my_model->my_method();
In Codeigniter classes are more like utility classes to group like functionality. However, you can always use native PHP in Codeigniter to require a class and then instantiate your own objects.
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.