¿Cuál es la forma correcta/mejor de usar el sistema de inyección de dependencia de laravel con objetos de múltiples instancias como los modelos CRUD?
La moda actual en algunos rincones de PHP-land dice que el siguiente código es "malo"
function someMethod() { /* .. stuff ... */ $object = new \App\SomeModel; $object->some_prop = 'some value'; $object->save(); /* .. other stuff ... */ }
Es malo porque este método ahora depende de la instanciación de ese nuevo objeto. La moda actual dice que los objetos deben inyectarse a través de algún tipo de sistema de inyección de dependencia, como la inyección automática de dependencia del constructor de Laravel.
Sin embargo, inyectar modelos elocuentes parece problemático
/*...* public function __construct(\App\SomeModel $object) { $this->someModel = $object; } function someMethod() { /* .. stuff ... */ $object = $this->someModel; $object->some_prop = 'some value'; $object->save(); /* .. other stuff ... */ } /*...*/
No está claro si la inyección automática de dependencias del constructor de Laravel crea nuevas instancias cada vez, o si los objetos inyectados son objetos de una sola instancia. Tampoco maneja situaciones en las que desea utilizar los ayudantes estáticos de Eloquent.
function someMethod($object_id) { //another dependency \App\SomeModel::find($object_id); //but this doesn't work $this->someModel->find($object_id); }
¿Existe una forma generalmente aceptada de manejar esto en una aplicación Laravel? Algunas personas dicen que deberías inyectar fábricas. Otras personas dicen repositorios. Me gustaría saber cuál es la práctica general con los desarrolladores de Laravel y si Laravel viene con algo que pueda ayudar aquí (implementaciones base de fábrica/repositorio, etc.)
Gracias a la ayuda de LaraChat Slack , descubrí esto por mi cuenta.
Resulta que, además de la inyección automática de dependencias del constructor, Laravel tiene una forma especial de inyección de dependencias que funciona con cualquiera de los métodos/funciones de devolución de llamada de un enrutador .
Considere este ejemplo de código
Route::get('api/users/{user?}', function (App\User $user) { return $user->email; });
Si configura su cadena de ruta con una variable ( {user}
), Laravel escaneará los parámetros de su controlador de ruta (arriba, una función anónima, pero también funciona con métodos de controlador) en busca de una sugerencia de tipo cuyo nombre de clase corto coincida con el nombre de la variable ( App\User
arriba). Si lo encuentra, en lugar de pasar el parámetro de la URL, Laravel creará una instancia de un objeto Eloquent cargado . Si se omite un parámetro opcional, obtendrá un objeto en blanco del tipo especificado.
Esta extensa discusión de Laravel DI es genial. Cubre el uso de clases e interfaces y más. La mejor referencia que he encontrado. https://gist.github.com/davejamesmiller/bd857d9b0ac895df7604dd2e63b23afe
Laravel tiene un poderoso Contenedor de Inversión de Control (IoC) / Inyección de Dependencia (DI). Desafortunadamente, la documentación oficial no cubre todas las funciones disponibles, así que decidí experimentar con ella y documentarla por mí mismo. Lo siguiente se basa en Laravel 5.4.26; otras versiones pueden variar.
Jugué un poco con esto (sin pruebas serias) y parece que es posible; de hecho, me gusta hacerlo de esta manera, y lo espero en el futuro. Muestra (no probada) a continuación:
use App/Models/Foo; class FooController { private $model; public function __construct(Foo $model) { $this->model = $model; } public function show(Request $request, $id) { $foo = $this->model->where($this->model->getKeyName(), '=', $id)->first(); dd($foo); } public function store(Request $request) { $foo = $this->model->newInstance(); $foo->bar = $request->get('baz'); $foo->save(); } }
Los asistentes de búsqueda que están en las fachadas elocuentes, como find, son agradables, pero esencialmente bajo el capó son un estándar where(...)->get()->first().