Zend Framework define un helper de vista genérico placeholder() que
puede usar para tantos placeholders personalizados como necesite. También proporciona una variedad de
implementaciones específicas de placeholder para funcionalidades habitualmente necesarias, como especificar la
declaración DocType, el título del documento, y más.
Todos los placeholders funcionan aproximadamente de la misma manera. Son contenedores y, por tanto, le permiten operar sobre ellos como colecciones. Con ellos puede:
Añadir al final o añadir al principio elementos a la colección.
Reemplazar toda la colección con un único valor.
Especificar una cadena con la que anteponer la salida de la colección al renderizar.
Especificar una cadena con la que añadir al final de la salida de la colección al renderizar.
Especificar una cadena con la que separar los elementos de la colección al renderizar.
Capturar contenido hacia la colección.
Renderizar el contenido agregado.
Normalmente, llamará al helper sin argumentos, lo que devolverá un contenedor sobre el cual puede operar. Después, o bien mostrará este contenedor con echo para renderizarlo, o llamará a métodos sobre él para configurarlo o poblarlo. Si el contenedor está vacío, al renderizarlo simplemente devolverá una cadena vacía; de lo contrario, el contenido se agregará según las reglas con las que lo haya configurado.
Como ejemplo, vamos a crear una barra lateral que conste de varios "bloques" de contenido. Probablemente conozca de antemano la estructura de cada bloque; supongamos para este ejemplo que podría verse así:
<div class="sidebar">
<div class="block">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
consectetur aliquet odio ac consectetur. Nulla quis eleifend
tortor. Pellentesque varius, odio quis bibendum consequat, diam
lectus porttitor quam, et aliquet mauris orci eu augue.
</p>
</div>
<div class="block">
<ul>
<li><a href="/some/target">Link</a></li>
<li><a href="/some/target">Link</a></li>
</ul>
</div>
</div>
El contenido variará según el controlador y la acción, pero la estructura será la misma. Primero configuremos la barra lateral en un método de recurso de nuestro bootstrap:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
// ...
protected function _initSidebar()
{
$this->bootstrap('View');
$view = $this->getResource('View');
$view->placeholder('sidebar')
// "prefix" -> markup to emit once before all items in collection
->setPrefix("<div class=\"sidebar\">\n <div class=\"block\">\n")
// "separator" -> markup to emit between items in a collection
->setSeparator("</div>\n <div class=\"block\">\n")
// "postfix" -> markup to emit once after all items in a collection
->setPostfix("</div>\n</div>");
}
// ...
}
Lo anterior define un placeholder, "sidebar", que no tiene elementos. Sin embargo, configura la estructura básica de markup de ese placeholder según nuestros requisitos.
Ahora, supongamos que para el controlador "user" queremos que todas las acciones muestren un bloque en la
parte superior con cierta información. Podríamos lograr esto de dos maneras: (a) podríamos añadir el
contenido directamente al placeholder en el método preDispatch() del
controlador, o (b) podríamos renderizar un script de vista desde dentro del método
preDispatch(). Usaremos (b), ya que sigue una
separación de responsabilidades más adecuada (dejando la lógica y funcionalidad relacionadas con la vista dentro de un
script de vista).
Llamaremos al script de vista "user/_sidebar.phtml", y lo completaremos de la
siguiente manera:
<?php $this->placeholder('sidebar')->captureStart() ?>
<h4>User Administration</h4>
<ul>
<li><a href="<?php $this->url(array('action' => 'list')) ?>">
List</a></li>
<li><a href="<?php $this->url(array('action' => 'create')) ?>">
Create</a></a></li>
</ul>
<?php $this->placeholder('sidebar')->captureEnd() ?>
El ejemplo anterior hace uso de la funcionalidad de captura de contenido de los placeholders. Por defecto, el contenido se añade como un nuevo elemento en el contenedor, lo que nos permite agregar contenido. Este ejemplo hace uso de helpers de vista y HTML estático para generar el markup, y el contenido se captura y se añade después al propio placeholder.
Para invocar el script de vista anterior, escribiríamos lo siguiente en nuestro
método preDispatch():
class UserController extends Zend_Controller_Action
{
// ...
public function preDispatch()
{
// ...
$this->view->render('user/_sidebar.phtml');
// ...
}
// ...
}
Observe que no estamos capturando el valor renderizado; no hay necesidad, ya que la totalidad de esa vista se está capturando en un placeholder.
Ahora, supongamos que nuestra acción "view" en ese mismo controlador necesita presentar cierta
información. Dentro del script de vista "user/view.phtml", podríamos tener
el siguiente fragmento de contenido:
$this->placeholder('sidebar')
->append('<p>User: ' . $this->escape($this->username) . '</p>');
Este ejemplo hace uso del método append(), al que se le pasa un poco de
markup sencillo para agregar.
Finalmente, modifiquemos nuestro script de vista de layout, para que renderice el placeholder.
<html>
<head>
<title>My Site</title>
</head>
<body>
<div class="content">
<?php echo $this->layout()->content ?>
</div>
<?php echo $this->placeholder('sidebar') ?>
</body>
</html>
Para los controladores y acciones que no pueblan el placeholder "sidebar", no se renderizará
contenido alguno; para aquellos que sí lo hacen, sin embargo, al mostrar el placeholder con echo se renderizará el contenido
según las reglas que creamos en nuestro bootstrap, y el contenido que agregamos a lo largo de
la aplicación. En el caso de la acción "/user/view", y suponiendo un
nombre de usuario "matthew", obtendríamos el siguiente contenido para la barra lateral (formateado para
facilitar la lectura):
<div class="sidebar">
<div class="block">
<h4>User Administration</h4>
<ul>
<li><a href="/user/list">List</a></li>
<li><a href="/user/create">Create</a></a></li>
</ul>
</div>
<div class="block">
<p>User: matthew</p>
</div>
</div>
Hay una gran cantidad de cosas que puede hacer combinando placeholders y scripts de layout; experimente con ellos, y lea las secciones relevantes del manual para obtener más información.