Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

344
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda