What the right/best way to use laravel's dependency injection system with multiple-instance objects like CRUD models?
Current fashion in some corners of PHP-land say the following code is "bad"
function someMethod()
{
/* .. stuff ... */
$object = new \App\SomeModel;
$object->some_prop = 'some value';
$object->save();
/* .. other stuff ... */
}
It's bad because this method is now dependent on that new object instantiation. The current fashion says objects ought to be injected via some sort of dependency injection system, like Laravel's automatic constructor dependency injection.
However -- injecting eloquent models seems problematic
/*...*
public function __construct(\App\SomeModel $object)
{
$this->someModel = $object;
}
function someMethod()
{
/* .. stuff ... */
$object = $this->someModel;
$object->some_prop = 'some value';
$object->save();
/* .. other stuff ... */
}
/*...*/
It's not clear if Laravel's automatic constructor dependency injection creates new instances each time, or if the objects injected are single instance objects. It also doesn't handle situations where you want to use Eloquent's static helpers
function someMethod($object_id)
{
//another dependency
\App\SomeModel::find($object_id);
//but this doesn't work
$this->someModel->find($object_id);
}
Is there a generally accepted way to handle this in a Laravel application? Some people say you should inject factories. Other people say repositories. I'd like to know what the general practice is with Laravel developers and if Laravel ships with anything that can help out here (base factory/repository implementations, etc.)
Thanks to some help from the LaraChat Slack I figured this one out on my own.
It turns out that, in addition to automatic constructor dependency injection, Laravel has a special form of dependency injection that works with any of a router's callback methods/functions.
Consider this code sample
Route::get('api/users/{user?}', function (App\User $user) {
return $user->email;
});
If you setup your route string with a variable ({user}
), Laravel will scan your route handler's (above, an anonymous function, but it works with controller methods as well) parameters for a type hint whose short class name matches the variable name (App\User
above). If found, instead of passing in the parameter from URL, Laravel will instantiate a loaded Eloquent object. If an optional parameter is ommited, you'll get a blank object of the specified type.
This extensive discussion of Laravel DI is great. Covers the use of classes and interfaces and more. Best reference I've found. https://gist.github.com/davejamesmiller/bd857d9b0ac895df7604dd2e63b23afe
Laravel has a powerful Inversion of Control (IoC) / Dependency Injection (DI) Container. Unfortunately the official documentation doesn't cover all of the available functionality, so I decided to experiment with it and document it for myself. The following is based on Laravel 5.4.26 - other versions may vary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With