Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

346
Views
Laravel: resolución de una dependencia con una dependencia de constructor del contenedor

Quiero resolver una instancia de clase mediante una string que tiene dependencia en su constructor desde el contenedor. Quiero pasar la dependencia del constructor cuando resuelvo la clase.

Un ejemplo simple que probé: Foo es la clase que quiero resolver y $id es un argumento constructor:

 class Foo { public function __construct(public $id) {} }

Encuadernación en el contenedor de servicios:

 $this->app->bind('foo', function($app, $id) { return new Foo($id); });

Y resolviéndolo desde el contenedor:

 $foo = App::makeWith('foo', ['id' => 1]);

$foo se resuelve entonces como

 Foo { +id: ["id" => 1], }

Lo que muestra que la propiedad pública $id se establece como una matriz.

Sin embargo, ¿qué pasa si no quiero tener $id como matriz, sino un int?

Tendría que hacer el enlace de la siguiente manera:

 App::bind('foo', function($app, $arg) { return new Foo($arg['id']); });

Esto se siente extremadamente hacky. ¿Es esto un abuso del contenedor de servicios?

Algunos pueden argumentar que no es una buena idea pasar un argumento de constructor cuando se resuelve desde el contenedor de servicio, en lugar de hacerlo sin estado o usar un setter. Pero si se van a usar muchos métodos en Foo , digamos $id , es más conveniente y la mejor práctica pasar $id , como constructor, ¿verdad?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Como el usuario mrhn ya respondió con la solución, solo explicaré POR QUÉ está obteniendo una array en lugar de un int en su caso.

En primer lugar, SIEMPRE escriba la sugerencia que desee:

 class Foo { public function __construct(public int $id) {} }

Vea que he insinuado el tipo int para $id .

En segundo lugar, está obteniendo una matriz porque tiene un "instanciador" personalizado (un closure ), su error es que $id no es $id sino $parameters .

Vea el código fuente , está haciendo: $concrete($this, $this->getLastParameterOverride()); entonces, en su código (como se muestra a continuación), está pasando el primer parámetro ( $app ) como $this y el segundo ( $id ) como $this->getLastParameterOverride() y este último método devolverá la matriz, por lo tanto ['id' => 1] en lugar de 1 .

 $this->app->bind('foo', function($app, $id) { return new Foo($id); });

Entonces, como dijo el otro, SIEMPRE hace referencia a clases concretas, por lo tanto, app(Foo::class, ['id' => 1]); solucionará su problema (mi manera es menos engorrosa pero hace exactamente lo mismo).

over 4 years ago · Santiago Trujillo Report

0

Está haciendo enlaces personalizados y, por supuesto, allí tendría que analizar los argumentos usted mismo. En su lugar, ¿por qué no dejar que la encuadernación directa se encargue de todo? por ejemplo, elimine su enlace actual y use los enlaces de clase.

 app()->makeWith(Foo::class, ['id' => 1]);

No se necesita nada más que lo siguiente, probado y ejecutado en un proyecto Laravel 8 .

En segundo lugar, el diseño y los parámetros del contenedor siempre han sido escamosos por diseño. Provengo de experiencia en Java/C# en la academia y me mudo a Laravel en mi carrera profesional. A menudo me enfrentaba al mismo problema que tú aquí.

En mi opinión, la solución es evitar este enfoque y, a menudo, resolverlo con un diseño de servicio fluido.

 class Foo { private $id; public function setId($id) { $this->id = $id; } }

Establezca la identificación con un setter en su lugar, ahora tendrá una instancia de contenedor fácil, en su lugar, tiene que trabajar un poco invocando la clase.

 resolve(Foo::class)->setId($model->id);

Esto puede parecer redundante, pero creo que este código se ve mucho mejor que esto. El enfoque también alivia algunos de los problemas con los que puede encontrarse, si los constructores hacen tanto trabajo como Laravel como marco necesita instanciar clases para hacer ciertas cosas (las rutas necesitan instanciar controladores, viene a la mente).

 $foo = App::makeWith('foo', ['id' => 1]);
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!