2010-10-23 18 views
46

Pregunta realmente rápida pero simple, pero no puedo encontrar una respuesta decente a esto: ¿cuál es la mejor manera de pasar datos de un controlador a un bloque en Magento.Magento - Transmisión de datos entre un controlador y un bloque

En caso que se hace una diferencia, yo estoy cargando la disposición de la siguiente manera:

$this->loadLayout(array('default', 'myModule_default')); 

    $this->_initLayoutMessages('customer/session') 
     ->_initLayoutMessages('catalog/session') 
     ->renderLayout(); 

debo añadir, que he estado usando el registro de la siguiente manera:

En el controlador:

Mage::register('data', $data); 

En el bloque:

$data = Mage::registry('data'); 

No estoy seguro si esta es la mejor manera de hacerlo.

Respuesta

79

No es así.

En el enfoque MVC de Magento, no es responsabilidad del controlador establecer variables para la vista (en el caso de Magento, la vista es Diseño y bloques). Los controladores establecen valores en Modelos, y luego Bloques leídos de esos mismos modelos. En la visión del mundo de Magento, tener un Bloque confiando en que el controlador haga algo específico es un acoplamiento estricto, y debe evitarse.

El trabajo de su controlador es hacer ciertas cosas a los Modelos, y luego decirle al sistema que es el tiempo de renderizado del diseño. Eso es. Es su trabajo de Diseño/Bloques para mostrar una página HTML de cierta manera dependiendo del estado de los Modelos del sistema.

Por lo tanto, si quisiera emular comportamientos tradicionales PHP MVC me había

  1. crear un sencillo modelo de clase hereda de los Varien_Object

  2. En el controlador, que instanciar objetos utilizando el Mage::getSingleton('foo/bar')

  3. Establezca valores en el modelo utilizando el captador/definidor de magia (se obtiene en objetos que heredan de Varien_Object) o setData, e tc.

  4. En los bloques, crear una nueva instancia del modelo con Mage::getSingleton('foo/bar') y leer los valores de nuevo.

Al crear una instancia de una maqueta con Mage::getSingleton(...) Magento será una instancia del objeto como un conjunto unitario. Por lo tanto, si vuelve a crear una instancia de un objeto (nuevamente con Mage::getSingleton('foo/bar')), recibirá el mismo objeto.

+1

Gracias, esto aclara mi confusión después de venir de las aplicaciones Zend MVC estándar. –

+2

@Neil Sí, hay un mucha confusión por ahí. Magento usa algunos componentes de zend framework, pero es, en sí mismo, un framework. –

+0

+1 a esta respuesta. Sin embargo, creo que la respuesta de Vinai también es buena, especialmente cuando estás en las fases iniciales de desarrollo y necesita ver que sus datos se cargan y pasan correctamente. Personalmente, recomendaría usar el método de "ultra desacoplado" en una etapa posterior, para evitar tener demasiadas cosas para prueba a la vez. – Diego

2

Está en el camino correcto utilizando el enfoque Mage::registry(). La otra opción es usar getters y setters automáticos, p. $this->setRandomVariableName($data) en el controlador y luego en el bloque use $this->getRandomVariableName(). No he investigado si terminan en la misma ubicación en la pila (supongo que en la sesión, ya que son específicos de la solicitud), pero logran el mismo objetivo en el código.

El uso de getters y setters ocasionalmente puede resultar confuso, ya que puede parecer que está accediendo a los datos a través del ORM en lugar de una variable de sesión "temporal", por lo que puede tomar una decisión de coherencia al usar Mage::registry para aquellos tipos de variables. Tu elección realmente.

+0

He intentado esto anteriormente, suponiendo que hubiera getters y setters mágicos - Sin embargo, siempre obtengo un error de método indefinido. –

+0

Hmm, quizás necesites un modelo instanciado para realizar la activación/activación automática de magia. Es posible que no funcione en $ this en un contexto de controlador. Si su controlador ya tiene un objeto creado por 'Mage :: getModel ('module/model'), entonces debería poder usar eso. Probablemente también le dé a la variable más contexto, lo cual es bueno ... –

+2

Magic getPropName y setPropName solo funcionan en objetos que heredan de Varien_Object. –

4

Lo que ha funcionado para mí en el es establecer la variable en el controlador haciendo:

Mage::register('variable', 'value'); 

Y luego, en la vista que se recuperaría el valor mediante el siguiente código:

$variable = $this->getVariable(); 
34

Si está utilizando bloques que heredan Mage_Core_Block_Template (es decir, que utilizan una plantilla para mostrar) puede asignar datos utilizando el método de asignación(), una vez que los bloques se han instanciado por loadLayout()

$this->loadLayout(array('default', 'myModule_default')); 

$this->getLayout()->getBlock('your.block.name.in.the.layout')->assign('data', $data); 

a continuación, en la plantilla .phtml, puede simplemente usar

<?php echo $data ?> 

Esto no se usa muy a menudo en magento, pero como se implementó como método público y por lo tanto se declaró estable, creo que está bien hacerlo. Esa es también la razón por la que la convención inicia las variables declaradas en una plantilla con un guión bajo (por ejemplo, $_product = $this->getProduct()), por lo que se pueden distinguir de las variables asignadas.

+1

Interesado por el uso de 'assign()' es mejor que magic setter, p. 'setData()'? –

+0

No, yo diría que son equivalentes. – Vinai

+0

@JonathanDay Evito los métodos mágicos como la peste porque los IDEs modernos que realizan análisis estáticos se ahogan con el código "mágico" que no está complementado por anotaciones (la mayoría de Magento). Intellisense es un plus también. –

0

Puede usar el par setData/getData para algunos valores. Utilicé setData en el controlador y getData en el bloque.

0

@Drew Con algo de experiencia en Java Server Faces y bastante nuevo en PHP/Magento Me gustaría decir que el

" 'no comparten nada' arquitectura de PHP",

ver PHP is not Java: Session Management Whitepaper", conduce a la hecho de que todos los objetos (e incluso las clases) en PHP tienen el alcance "solicitud".

Si llegué punto alanos entonces se aconseja utilizar

  • un 'stateful' modelo de objetos que tiene algunos datos en sus atributos que no necesariamente se almacenan en la base de datos
  • y el patrón Singleton, por el uso de Mage :: getSingleton, para hacer este modelo con estado, que se instancia en el controlador, accesible al bloque y, por lo tanto, en la plantilla real que representa la salida.

Y dado que una herramienta como MTool reduce el tiempo para crear un nuevo modelo, esto realmente parece tener sentido.

Cuestiones relacionadas