sirve sabores que precio peligrosa para monster malo ingredientes efectos daños bebida php dependency-injection controller

php - sabores - Dónde cargar las clases de dependencia del controlador?



monster energy para que sirve (5)

Estoy creando mi propio framework MVC primitivo con PHP, y me pregunto dónde debería cargar / instanciar las dependencias de controlador correspondientes.

¿En el constructor de cada controlador (estrechamente acoplado) o inyectarlos (flojos)?

La única parte de la última de la que no estoy muy seguro es que las dependencias se instanciarán en el nivel de arranque, fuera del paradigma MVC, antes de ser inyectadas. No todos los controladores utilizan las mismas dependencias exactas además de los padres primarios predeterminados. Tendría que instanciarlos a todos, lo que también crearía muchos sobrecargas.

He visto algunos frameworks existentes como $this->load->model(''model''); // CodeIgniter $this->load->model(''model''); // CodeIgniter en el constructor, pero no tengo idea de por qué lo están haciendo así.


Sugeriría que inyectas las dependencias, por lo que tus controladores estarán menos acoplados a tu marco. Esto facilitará el cambio a otro marco.

Acerca de crear instancias de dependencias: sugiero que use (o implemente) un contenedor de inyección de dependencias . Este contenedor debe contener fábricas que puedan crear instancias de servicios.

En una situación ideal, sus controladores también son servicios (lo que significa que también tienen fábricas en el contenedor de inyección de dependencia).

De esta forma, solo se creará una instancia del controlador que necesite para una solicitud en particular y, por lo tanto, solo se crearán instancias de sus dependencias.
Al construir su propio marco, esto significa que después de la fase de enrutamiento (cuando se conoce el controlador correcto), el marco debe tomar ese controlador del contenedor. El contenedor se asegurará de que se proporcionen todas las dependencias necesarias.

Eche un vistazo a Pimple para ver un ejemplo de un contenedor de inyección de dependencia simple.

PD: Esa línea de CodeIgniter se parece mucho al patrón de localización de servicios . Este patrón es similar a la inyección de dependencia , pero no proporciona una inversión total del control .


Tal vez necesite definir la __autoload() antes de intentar cargar las Clases que aún no están cargadas. Me gusta:

function __autoload($className) { require "/path/to/the/class/file/$className.php"; }

Mi ejemplo es muy muy simple para requerir automáticamente el archivo en el que se encuentra la definición de la clase. También puede usar la instrucción if-else o switch declaración en esa función para adaptarla a sus propias situaciones de manera inteligente.

Se llama a la función __autoload() cuando PHP no encuentra la definición de clase, funciona para new , class_exists() , call_user_method() , etc., y absolutamente para sus clases de dependencias / padres. Si todavía no hay una definición de clase después de llamar a __autoload() , PHP generará un error.

O puede usar la función spl_autoload_register() lugar de __autoload() mayor gracia.

Para obtener más información, es posible que desee ver: http://php.net/manual/en/function.autoload.php http://php.net/manual/en/function.spl-autoload-register.php


Como soy desarrollador de Symfony, solo puedo darte una referencia a Symfony. Creo que deberías hacer lo que están haciendo en Symfony pensando en lo que necesitas en cada objeto del Controlador.

Al menos, necesitas:

  • un objeto Solicitud

  • y un objeto de cargador de modelos que le brinda todos los modelos que necesita.

Cree un BaseController que implemente estas pocas funciones y luego extiéndalo con Controladores personalizados. También puedes echar un vistazo a Silex: http://silex.sensiolabs.org/ a Micro Framework

Espero eso ayude.


¿Cuándo dices "En el constructor" quieres pasar el conatiner y extraer las dependencias de ellos (en el constructor)?

<?php class SomeController { public function __construct($container) { $this->service1 = $contanier->get(''service1); } //... }

Recomiendo eso , aunque más simple y fácil será conectar los controladores al contenedor utilizando un ServiceLocator en lugar de una verdadera inversión de control.

Si desea que sus controladores sean fáciles de probar por unidad, debe usar la inversión de control:

class SomeController { public function __construct($service1) { $this->service1 = $service1; } //... }

E incluso puede crear su controlador como un servicio dentro del contenedor:

// this uses Pimple notation, I hope you get the point $container[''controller''] = function($c) { return SomeController($c[''service1'']); }

Usa los servicios de proxy para cargarlos de forma perezosa

Además, si sus controladores necesitan más que algunos servicios y usted no los usará todos, puede:

1) Usar servicios proxy para cargar el servicio de forma perezosa solo cuando realmente se necesitan

<?php class ProxyService { /** * @var Service1Type */ private $actualService; public function __construct() { $this->actualService = null; } private function initialize() { $this->actualService = new Service1(); // This operation may take some time thus we deferred as long as possible } private function isInitialized() { return $this->actualService === null; } public function someActionOnThisService() { if (!$this->isInitalized()) { $this->initalize(); } $this->actualService->someActionOnThisService(); }

Ahí tienes un objeto proxy simple con carga diferida. Es posible que desee comprobar la fantástica Biblioteca de Proxy Manager si desea ir por esa ruta

2) divide tu controlador

Si su controlador tiene demasiadas dependencias, puede dividirlo.

De hecho, es posible que desee leer la propuesta de Paul M. Jones (desarrollador principal de Aura Framework) sobre MVC-Refinement , en mi humilde opinión es una buena lectura, aunque es posible que no esté totalmente de acuerdo con ella.

Incluso si divide el controlador para reducir las dependencias, la carga lenta de sus dependencias es una buena idea (obviamente, tendrá que controlar el clima si es factible en su contexto: más trabajo para ganar más velocidad).


P: ¿Dónde debo cargar / instanciar las dependencias de controlador correspondientes?

Hay varias formas. Los conceptos de carga e instanciación son básicamente "antes / afuera" y "después / dentro".

Antes y fuera significa que carga el archivo que contiene una clase (que desea instanciar y pasar al controlador), antes de cargar el controlador. Pero, ¿cómo sabe usted qué necesita el controlador antes de cargar el controlador? Uh ...

  • Archivos de descripción de dependencia

Un archivo de descripción entra en juego, describiendo el cableado entre su controlador y sus dependencias. En otras palabras, puede ver las dependencias de su controlador mirando su archivo de descripción de dependencia. Este concepto es utilizado a menudo por las herramientas de Inyección de Dependencia, que analizan el objeto y extraen los nombres de las dependencias automáticamente. También es posible mantener dicho archivo de configuración de cableado manualmente. Pero es tedioso

  • Localizador de servicio

Un localizador de servicios es una instancia de ayuda para las dependencias. Básicamente, contiene la misma información, como un archivo de descripción de dependencia, pero esta vez en forma de registry . El enlace entre las partes de su aplicación se convierte en este registro.

Ambas estrategias introducen gastos generales. Es una compensación. Cuando cambias la perspectiva y observas las cosas desde una aplicación con más de 500 clases, entonces te das cuenta de que una herramienta de inyección de dependencia a veces vale la pena.

  • Inyección manual

a través de la inyección de Constructor.

Después y dentro significa que carga el archivo que contiene su controlador y luego comienza a preocuparse por las dependencias.

En este punto, la clase aún no está instanciada, pero el autocargador podría hacer sus acciones sucias detrás de la escena. Él evalúa las instrucciones de use en la parte superior de su archivo de controlador. Las instrucciones de use declaran clases de espacio de nombres, que el autocargador resuelve en archivos reales y los carga. Entonces puede comenzar a utilizar estas clases como dependencias en su controlador. Esta es probablemente la forma más fácil de resolver su problema y le sugiero que investigue los temas de carga automática con espacios de nombres y declaraciones de uso.

Cuando se crea una instancia de la clase, tiene las siguientes posibilidades: el uso puede utilizar Inyección Setter o Inyección de referencia para establecer las dependencias del objeto. Esto requiere que sus Dependencias de Constructor ya estén resueltas o su constructor esté vacío. Es posible combinar estas estrategias.

P: ¿Qué hace esto $this->load->model(''model''); // CodeIgniter $this->load->model(''model''); // CodeIgniter ?

CodeIgniter es un marco de aplicación heredado. Se creó en momentos en que la carga automática con espacios de nombres no estaba disponible. $this->load es un asistente de carga de clase básica. Esto es lo opuesto a un cargador "automático", (sorpresa, sorpresa) carga cosas automáticamente.

La clase de cargador CodeIgniters se usa para cargar otras clases, como bibliotecas o archivos desde la vista, ayudantes, modelos o cosas definidas por el usuario. Este es nuevamente el concepto de un registro. Aquí el registro simplemente sabe dónde están las cosas en el diseño de su aplicación y las resuelve. Entonces $this->load->model(''model''); significa que la función del model debe tener algunas partes de información, sobre la posición de los archivos de modelo en su aplicación. Proporcione un nombre de modelo y la ruta del archivo se construye por model . Y esto es exactamente lo que hace (excepto un poco de sobrecarga): https://github.com/EllisLab/CodeIgniter/blob/develop/system/core/Loader.php#L223 .