php - tutorial - ¿Cómo representar la vista ZF2 dentro de la respuesta JSON?
zend framework tutorial (4)
Como es habitual, el desarrollador de marcos tiene que ver con AJAX siguiendo la regla de por qué simple si podría ser complejo. Aquí hay una solución simple en el script del controlador.
public function checkloginAction()
{
// some hosts need to this some not
//header ("Content-type: application/json"); // this work
// prepare json aray ....
$arr = $array("some" => .....);
echo json_encode($arr); // this works
exit;
}
Esto funciona también en ZF1 y ZF2. No hay necesidad de ver nada en absoluto.
Si usas el consejo del creador de ZF2
use Zend/View/Model/JsonModel;
....
$result = new JsonModel($arr);
return $result;
AJAX se anuló como respuesta al menos en zf 2.0.0
Hasta ahora, he descubierto cómo devolver una respuesta JSON típica en Zend Framework 2. Primero, agregué ViewJsonStrategy
a la sección de strategies
de la configuración de view_manager
. Luego, en lugar de devolver una instancia de ViewModel
desde la acción del controlador, devuelvo una instancia de JsonModel
con todas mis variables establecidas.
Ahora que he descubierto la pieza, debo entender cómo representar una vista y devolverla dentro de esa respuesta JSON. En ZF1, pude usar $this->view->render($scriptName)
, que devolvió el HTML como una cadena. En ZF2, el método Zend/View/View::render(...)
devuelve void
.
Entonces ... ¿cómo puedo representar un script de vista HTML y devolverlo en una respuesta JSON en una solicitud?
Esto es lo que tengo ahora:
if ($this->getRequest()->isXmlHttpRequest()) {
$jsonModel = new JsonModel(...);
/* @todo Render HTML script into `$html` variable, and add to `JsonModel` */
return $jsonModel;
} else {
return new ViewModel(...);
}
En ZF 3 puedes lograr el mismo resultado con este código.
MyControllerFactory.php
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$renderer = $container->get(''ViewRenderer'');
return new MyController(
$renderer
);
}
MyController.php
private $renderer;
public function __construct($renderer) {
$this->renderer = $renderer;
}
public function indexAction() {
$htmlViewPart = new ViewModel();
$htmlViewPart
->setTerminal(true)
->setTemplate(''module/controller/action'')
->setVariables(array(''key'' => ''value''));
$htmlOutput = $this->renderer->render($htmlViewPart);
$json = /Zend/Json/Json::encode(
array(
''html'' => $htmlOutput,
''jsonVar1'' => ''jsonVal2'',
''jsonArray'' => array(1, 2, 3, 4, 5, 6)
)
);
$response = $this->getResponse();
$response->setContent($json);
$response->getHeaders()->addHeaders(array(
''Content-Type'' => ''application/json'',
));
return $this->response;
}
OK, creo que finalmente entendí lo que estás haciendo. He encontrado una solución que creo que coincide con sus criterios. Aunque estoy seguro de que hay margen de mejora, ya que hay que hacer un trabajo manual desagradable ...
public function indexAction()
{
if (!$this->getRequest()->isXmlHttpRequest()) {
return array();
}
$htmlViewPart = new ViewModel();
$htmlViewPart->setTerminal(true)
->setTemplate(''module/controller/action'')
->setVariables(array(
''key'' => ''value''
));
$htmlOutput = $this->getServiceLocator()
->get(''viewrenderer'')
->render($htmlViewPart);
$jsonModel = new JsonModel();
$jsonModel->setVariables(array(
''html'' => $htmlOutput,
''jsonVar1'' => ''jsonVal2'',
''jsonArray'' => array(1,2,3,4,5,6)
));
return $jsonModel;
}
Como puede ver, el templateMap i create es ... desagradable ... es molesto y estoy seguro de que se puede mejorar un poco. Es una solución de trabajo, pero no es limpia. Tal vez, de alguna manera, uno podría tomar el PhpRenderer predeterminado, probablemente ya instanciado, del ServiceLocator con su plantilla y mapeo de ruta y luego debería estar más limpio.
Gracias al comentario de @DrBeza, el trabajo que se necesita hacer podría reducirse en una cantidad justa. Ahora, como inicialmente quería, tomaremos al espectador con toda la asignación de la plantilla intacta y simplemente renderizaremos el ViewModel directamente. El único factor importante es que necesita especificar la plantilla completamente calificada para procesar (por ejemplo, "$ module / $ controller / $ action")
Espero que esto te ayude a empezar;)
PS: La respuesta se ve así:
Object:
html: "<h1>Hello World</h1>"
jsonArray: Array[6]
jsonVar1: "jsonVal2"
Puede usar una forma más fácil de renderizar la vista para su respuesta JSON.
public function indexAction() {
$partial = $this->getServiceLocator()->get(''viewhelpermanager'')->get(''partial'');
$data = array(
''html'' => $partial(''MyModule/MyPartView.phtml'', array("key" => "value")),
''jsonVar1'' => ''jsonVal2'',
''jsonArray'' => array(1, 2, 3, 4, 5, 6));
$isAjax = $this->getRequest()->isXmlHttpRequest());
return isAjax?new JsonModel($data):new ViewModel($data);
}
Tenga en cuenta que antes de usar la clase JsonModel necesita configurar View Manager en el archivo module.config.php de su módulo.
''view_manager'' => array(
.................
''strategies'' => array(
''ViewJsonStrategy'',
),
.................
),
Es un trabajo para mí y espero que te ayude.