Secciones

Vistas


Resumen

Las vistas representan la interfaz de usuario de su aplicación. Las vistas, son a menudo, archivos HTML con código PHP incrustado que realizan tareas relacionadas solamente a la presentación de datos. Las vistas formatean el contenido que necesita devolver al usuario/navegador web que inició la petición.

Phalcon\Mvc\View and Phalcon\Mvc\View\Simple are responsible for the managing the view layer of your MVC application.

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property View $view
 */
class InvoicesController extends Controller
{
    public function viewAction($invoiceId)
    {
        $this->view->invoiceId = $invoiceId;
    }
}

Constantes

Hay varias constantes que controlan el comportamiento del proceso de renderizado una vez establecido en la vista

Constante Descripción
LEVEL_ACTION_VIEW Nivel de Renderizado: A la vista de la acción
LEVEL_BEFORE_TEMPLATE Nivel de Renderizado: A las plantillas “anterior”
LEVEL_LAYOUT Nivel de Renderizado: A la disposición del controlador
LEVEL_MAIN_LAYOUT Nivel de Renderizado: A la disposición principal
LEVEL_NO_RENDER Nivel de Renderizado: No renderiza ninguna vista
LEVEL_AFTER_TEMPLATE Nivel de Renderizado: Renderiza a las plantillas “posterior”

Métodos

public function __construct(array options = [])

Constructor Phalcon\Mvc\View

public function __get(string $key): mixed | null

Método mágico para obtener las variables pasadas a la vista

echo $this->view->invoices;
public function __isset(string $key): bool

Método mágico para obtener si una variable está establecida en la vista

echo isset($this->view->invoices);
public function __set(string $key, var value)

Método mágico para pasar variables a las vistas

$this->view->invoices = $invoices;
public function cleanTemplateAfter(): View

Reestablece cualquier plantilla anterior de la disposición

public function cleanTemplateBefore(): View

Restablece cualquier disposición de “plantilla anterior”

public function disableLevel(mixed $level): ViewInterface

Deshabilita un nivel específico de renderizado

$this->view->disableLevel(
    View::LEVEL_ACTION_VIEW
);

Renderiza todos los niveles excepto el nivel ACTION

public function disable(): View

Deshabilita el proceso de auto-renderizado

public function enable(): View

Habilita el proceso de auto-renderizado

public function exists(string $view): bool

Comprueba si existe la vista

public function finish(): View

Finaliza el proceso de renderizado deteniendo el búfer de salida

public function getActionName(): string

Obtiene el nombre de la acción renderizada

public function getActiveRenderPath(): string | array

Devuelve la ruta (o rutas) de las vistas que se están renderizando actualmente

public function getBasePath(): string

Obtiene la ruta base

public function getContent(): string

Devuelve la salida desde otra etapa de vista

public function getControllerName(): string

Obtiene el nombre del controlador renderizado

public function getLayout(): string

Obtiene el nombre de la vista principal

public function getLayoutsDir(): string

Gets the current layouts subdirectory

public function getMainView(): string

Obtiene el nombre de la vista principal

public function getParamsToView(): array

Obtiene los parámetros de las vistas

public function getPartial(
    string $partialPath, 
    mixed $params = null
): string

Renderiza una vista parcial

echo $this->getPartial("shared/footer");

Recupera los contenidos de una parcial

echo $this->getPartial(
    "shared/footer",
    [
        "content" => $html,
    ]
);

Recupera los contenidos de una parcial con argumentos

public function getPartialsDir(): string

Gets the current partials subdirectory

public function getRender(
    string $controllerName, 
    string $actionName, 
    array $params = [], 
    mixed configCallback = null
): string

Realiza el renderizado automático devolviendo la salida como una cadena

$template = $this->view->getRender(
    "invoices",
    "show",
    [
        "invoices" => $invoices,
    ]
);
public function getVar(string $key)

Devuelve un parámetro previamente establecido en la vista

public function getViewsDir(): string | array

Devuelve el directorio de las vistas

protected function getViewsDirs(): array

Devuelve los directorios de las vistas

public function isDisabled(): bool

Si está habilitado el renderizado automático

public function partial(
    string $partialPath, 
    mixed $params = null
)

Renderiza una vista parcial

$this->partial("shared/footer");

Muestra una parcial dentro de otra vista

$this->partial(
    "shared/footer",
    [
        "content" => $html,
    ]
);

Muestra una parcial dentro de otra vista con parámetros

public function pick(var renderView): View

Elige una vista diferente a renderizar en vez del último-controlador/última-acción

use Phalcon\Mvc\Controller;

class ProductsController extends Controller
{
    public function saveAction()
    {
        // ...

        $this->view->pick("invoices/list");
    }
}
public function registerEngines(
    array $engines
): View

Registra motores de plantillas

$this->view->registerEngines(
    [
        ".phtml" => \Phalcon\Mvc\View\Engine\Php::class,
        ".volt"  => \Phalcon\Mvc\View\Engine\Volt::class,
        ".mhtml" => \MyCustomEngine::class,
    ]
);
public function render(
    string $controllerName,
    string $actionName,
    array $params = []
): View | bool

Ejecuta el proceso de renderizado desde los datos de despacho

$view
    ->start()
    ->render("posts", "recent")
    ->finish()
;

Muestra la vista de mensajes reciente (app/views/posts/recent.phtml)

public function reset(): View

Resetea el componente vista a sus valores predeterminados de fábrica

public function setBasePath(
    string $basePath
): View

Establece la ruta base. Depending on your platform, always add a trailing slash or backslash

$view->setBasePath(__DIR__ . "/");
public function setContent(
    string $content
): View

Establece externamente el contenido de la vista

$this->view->setContent(
    "<h1>hello</h1>"
);
public function setLayout(
    string $layout
): View

Cambia la disposición a usar en vez de usar el nombre del último nombre de controlador

$this->view->setLayout("main");
public function setLayoutsDir(
    string $layoutsDir
): View

Establece el subdirectorio de disposiciones. Debe ser un directorio dentro del directorio de vistas. Depending on your platform, always add a trailing slash or backslash

$view->setLayoutsDir(
    "../common/layouts/"
);
public function setMainView(
    string viewPath
): View

Establece el nombre de la vista predeterminada. Debe ser un fichero sin extensión en el directorio de vistas

$this->view->setMainView("base");

Renderiza como vista principal views-dir/base.phtml

public function setPartialsDir(
    string $partialsDir
): View

Sets a partials subdirectory. Debe ser un directorio dentro del directorio de vistas. Depending on your platform, always add a trailing slash or backslash

$view->setPartialsDir(
    "../common/partials/"
);
public function setParamToView(
    string $key, 
    mixed $value
): View

Añade parámetros a las vistas (alias de setVar)

$this
    ->view
    ->setParamToView("invoices", $invoices)
;
public function setRenderLevel(
    int $level
): ViewInterface

Establece el nivel de renderizado de la vista

$this->view->setRenderLevel(
    View::LEVEL_LAYOUT
);

Renderiza solo la vista relacionada con el controlador

public function setTemplateAfter(
    mixed $templateAfter
): View

Establece una disposición de controlador “plantilla posterior”

public function setTemplateBefore(
    mixed $templateBefore
): View

Establece una plantilla anterior a la disposición del controlador

public function setVar(
    string $key, 
    mixed $value
): View

Establece un parámetro de vista único

$this
    ->view
    ->setVar("invoices", $invoices)
;
public function setVars(
    array $params, 
    bool $merge = true
): View

Establece todos los parámetros de renderizado

$this->view->setVars(
    [
        "invoices" => $invoices,
    ]
);
public function setViewsDir(
    mixed $viewsDir
): View

Establece el directorio de las vistas. Depending on your platform, always add a trailing slash or backslash

public function start(): View

Inicia el proceso de renderizado habilitando el búfer de salida

public function toString(
    string $controllerName,
    string $actionName,
    array params = []
): string

Renderiza la vista y la devuelve como una cadena

Activación

Debe registrar el componente vista en su contenedor DI para habilitar las vistas en su aplicación.

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\View;

$container = new FactoryDefault();

$container->set(
    'view',
    function () {
        $view = new View();

        $view->setViewsDir('../app/views/');

        return $view;
    }
);

If no engine is defined, the Phalcon\Mvc\View\Engine\Php will be automatically registered for you. Estos son ficheros que contienen tanto código PHP como HTML y tienen la extensión .phtml. Para más información sobre el motor de plantilla Volt, consulte el documento correspondiente.

Vistas en Controladores

Phalcon automáticamente pasa la ejecución al componente vista tan pronto como un controlador particular haya completado su ciclo. El componente vista buscará en la carpeta vistas por una carpeta llamada con el mismo nombre del último controlador ejecutado y luego por un fichero llamado como la última acción ejecutada. For instance, if a request is made to the URL https://dev.phalcon.ld/admin/invoices/view/12345, Phalcon will parse the URL as follows:

Dirección del Servidor 127.0.0.1
Directorio Phalcon admin
Controlador invoices
Acción view
Parámetro 12345

El despachador buscará un InvoicesController y su acción viewAction. Un fichero de controlador simple para este ejemplo:

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property View $view
 */
class InvoicesController extends Controller
{
    public function viewAction($invoiceId)
    {
        $this->view->setVar('invoiceId', $invoiceId);
    }
}

El método setVar() nos permite crear variables de la vista bajo demanda, por lo que se pueden usar en la plantilla de la vista. El ejemplo anterior demuestra cómo pasar el parámetro $invoiceId a la respectiva plantilla de vista.

Renderizado Jerárquico

Phalcon\Mvc\View is the default component for rendering views in Phalcon and supports a hierarchy of files. Esta jerarquía permite puntos de composición común (vistas usadas normalmente), así como carpetas con el nombre del controlador definiendo sus respectivas plantillas de vistas.

El motor de renderizado por defecto para el componente vista es PHP. Como resultado, todos los ficheros relacionados con las vistas necesitan tener la extensión .phtml. Para el ejemplo anterior:

https://dev.phalcon.ld/admin/invoices/view/12345

Asumiendo que el directorio de vistas es app/views, el componente vista automáticamente encontrará los 3 siguientes ficheros de vistas:

Nombre Archivo Descripción
Vista de la Acción app/views/invoices/view.phtml Vista relacionada con la acción. Sólo será renderizada cuando la acción view se ejecute.
Disposición de Controlador app/views/layouts/invoices.phtml Vista relacionada con el controlador. Será renderizada para cada acción ejecutada en el InvoicesController.
Disposición Principal app/views/index.phtml Vista relacionada con la Aplicación. Se mostrará en cada controlador/acción de la aplicación

You are not required to implement all the files mentioned above. Phalcon\Mvc\View will simply move to the next view level in the hierarchy of files. Si los tres ficheros de vista se implementan, entonces se procesarán como sigue:

<!-- app/views/invoices/view.phtml -->

<h3>View Name: "view"</h3>

<p>I have received the parameter <?php echo $invoiceId; ?></p>
<!-- app/views/layouts/invoices.phtml -->

<h2>Controller view: "invoices"</h2>

<?php echo $this->getContent(); ?>
<!-- app/views/index.phtml -->
<html>
    <head>
        <title>Example</title>
    </head>
    <body>
        <h1>Main layout!</h1>

        <?php echo $this->getContent(); ?>

    </body>
</html>

NOTE: The call to $this->getContent() instructs Phalcon\Mvc\View on where to inject the contents of the previous view executed in the hierarchy.

Para el ejemplo anterior, la salida será:

El HTML generado será:

<html>
    <head>
        <title>Example</title>
    </head>
    <body>
        <h1>Main layout!</h1>

        <!-- app/views/layouts/invoices.phtml -->

        <h2>Controller view: "invoices"</h2>

        <!-- app/views/invoices/view.phtml -->

        <h3>View Name: "view"</h3>

        <p>I have received the parameter 12345</p>

    </body>
</html>

Plantillas

Las plantillas son vistas que se pueden usar para compartir código de vista común. Ellas actúan como disposiciones del controlador, así que necesita colocarlas en el directorio de disposiciones.

Las plantillas se pueden renderizar antes de la disposición (usando $this->view->setTemplateBefore()) o se pueden renderizar después de la disposición (usando this->view->setTemplateAfter()). En el siguiente ejemplo la plantilla (layouts/common.phtml) se renderiza después de la disposición principal (layouts/posts.phtml):

<?php

use Phalcon\Flash\Direct;
use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property Direct $flash
 * @property View   $view
 */
class InvoicesController extends Controller
{
    public function initialize()
    {
        $this->view->setTemplateAfter('common');
    }

    public function lastAction()
    {
        $this->flash->notice(
            'These are the latest invoices'
        );
    }
}
<!-- app/views/index.phtml -->
<!DOCTYPE html>
<html>
    <head>
        <title>Invoices</title>
    </head>
    <body>
        <?php echo $this->getContent(); ?>
    </body>
</html>
<!-- app/views/layouts/common.phtml -->

<ul class='menu'>
    <li><a href='/'>Home</a></li>
    <li><a href='/list'>List</a></li>
    <li><a href='/support'>Support</a></li>
</ul>

<div class='content'>
    <?php echo $this->getContent(); ?>
</div>
<!-- app/views/layouts/invoices.phtml -->

<h1>Invoices</h1>

<?php echo $this->getContent(); ?>
<!-- app/views/invoices/last.phtml -->

<article>
    <h2>This is a title</h2>
    <p>This is Invoice One</p>
</article>

<article>
    <h2>Another title</h2>
    <p>This is Invoice Two</p>
</article>

La salida final será la siguiente:

<!-- app/views/index.phtml -->
<!DOCTYPE html>
<html>
    <head>
        <title>Invoices</title>
    </head>
    <body>

        <!-- app/views/layouts/common.phtml -->

        <ul class='menu'>
            <li><a href='/'>Home</a></li>
            <li><a href='/list'>List</a></li>
            <li><a href='/support'>Support</a></li>
        </ul>

        <div class='content'>

            <!-- app/views/layouts/invoices.phtml -->

            <h1>Invoices</h1>

            <!-- app/views/invoices/last.phtml -->

            <article>
                <h2>This is a title</h2>
                <p>This is Invoice One</p>
            </article>

            <article>
                <h2>Another title</h2>
                <p>This is Invoice Two</p>
            </article>

        </div>

    </body>
</html>

Si hubiésemos usado $this->view->setTemplateBefore('common'), este sería la salida final:

<!-- app/views/index.phtml -->
<!DOCTYPE html>
<html>
    <head>
        <title>Blog's title</title>
    </head>
    <body>

        <!-- app/views/layouts/invoices.phtml -->

        <h1>Blog Title</h1>

        <!-- app/views/layouts/common.phtml -->

        <ul class='menu'>
            <li><a href='/'>Home</a></li>
            <li><a href='/articles'>Articles</a></li>
            <li><a href='/contact'>Contact us</a></li>
        </ul>

        <div class='content'>

            <!-- app/views/invoices/last.phtml -->

            <article>
                <h2>This is a title</h2>
                <p>This is the post content</p>
            </article>

            <article>
                <h2>This is another title</h2>
                <p>This is another post content</p>
            </article>

        </div>

    </body>
</html>

Niveles de Renderizado

As seen above, Phalcon\Mvc\View supports a view hierarchy. Podría necesitar controlar el nivel de renderizado producido por el componente vista. El método Phalcon\Mvc\View::setRenderLevel() ofrece esta funcionalidad.

Este método se puede invocar desde el controlador o desde una capa de vista superior para interferir en el proceso de renderizado.

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property View   $view
 */
class InvoicesController extends Controller
{
    public function findAction()
    {
        $this->view->setRenderLevel(
            View::LEVEL_NO_RENDER
        );

        // ...
    }

    public function viewAction($invoiceId)
    {
        $this->view->setRenderLevel(
            View::LEVEL_ACTION_VIEW
        );
    }
}

Los niveles de renderizado disponibles son:

Constante de Clase Descripción Orden
LEVEL_NO_RENDER Indica que se evite generar ningún tipo de presentación.  
LEVEL_ACTION_VIEW Genera la presentación a la vista asociada a la acción. 1
LEVEL_BEFORE_TEMPLATE Genera plantillas de presentación antes que el diseño del controlador. 2
LEVEL_LAYOUT Genera la presentación en el diseño del controlador. 3
LEVEL_AFTER_TEMPLATE Genera la presentación a las plantillas después del diseño del controlador. 4
LEVEL_MAIN_LAYOUT Genera la presentación del diseño principal. Fichero views/index.phtml 5

Deshabilitar Niveles de Renderizado

Puedes deshabilitar niveles de renderizado temporal o permanentemente. Un nivel podría deshabilitarse permanentemente si no se utiliza en toda la aplicación:

<?php

use Phalcon\Mvc\View;

$container->set(
    'view',
    function () {
        $view = new View();

        // Disable several levels
        $view->disableLevel(
            [
                View::LEVEL_LAYOUT      => true,
                View::LEVEL_MAIN_LAYOUT => true,
            ]
        );

        return $view;
    },
    true
);

O deshabilitarlo temporalmente en alguna parte de la aplicación:

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property View   $view
 */
class InvoicesController extends Controller
{
    public function findAction()
    {
        $this->view->disableLevel(
            View::LEVEL_MAIN_LAYOUT
        );
    }
}

Deshabilitar la Vista

Si su controlador no produce ninguna salida en la vista (o ni siquiera tiene una) puede deshabilitar el componente vista evitando un procesamiento innecesario:

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property View   $view
 */
class InvoicesController extends Controller
{
    public function processAction()
    {
        $this->view->disable();
    }
}

Alternativamente, puede devolver false para producir el mismo efecto:

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property View   $view
 */
class InvoicesController extends Controller
{
    public function processAction()
    {
        return false;
    }
}

Puede devolver un objeto response para evitar deshabilitar la vista manualmente:

<?php

use Phalcon\Http\Response;
use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property Response $response
 * @property View     $view
 */
class InvoicesController extends Controller
{
    public function processAction()
    {
        return $this
            ->response
            ->redirect('index/index')
        ;
    }
}

Renderizado Simple

Phalcon\Mvc\View\Simple is an alternative component to Phalcon\Mvc\View. It keeps most of the philosophy of Phalcon\Mvc\View but lacks of a hierarchy of files which is, in fact, the main feature of its counterpart.

Este componente le permite tener el control de cuando se renderiza una vista y su ubicación. Además, este componente puede aprovechar la herencia de vista disponible en motores de plantillas como Volt y otros.

El componente por defecto se debe reemplazar en el contenedor de servicio:

<?php

use Phalcon\Mvc\View\Simple;

$container->set(
    'view',
    function () {
        $view = new Simple();

        $view->setViewsDir('../app/views/');

        return $view;
    },
    true
);

El renderizado automático se debe deshabilitar en Phalcon\Mvc\Application (si es necesario):

<?php

use Phalcon\Di\FactoryDefault;;
use Phalcon\Mvc\Application;

try {
    $container   = new FactoryDefault();
    $application = new Application($container);

    $application->useImplicitView(false);

    $response = $application->handle(
        $_SERVER["REQUEST_URI"]
    );

    $response->send();
} catch (Exception $e) {
    echo $e->getMessage();
}

Para renderizar una vista es necesario llamar explícitamente al método de renderizado indicando la ruta relativa a la vista que quieres mostrar:

<?php

use Phalcon\Http\Response;
use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property Response $response
 * @property View     $view
 */
class InvoicesController extends Controller
{

    public function indexAction()
    {
        // 'views-dir/index.phtml'
        echo $this->view->render('index');

        // 'views-dir/posts/show.phtml'
        echo $this->view->render('posts/show');

        // 'views-dir/index.phtml' passing variables
        echo $this->view->render(
            'index',
            [
                'posts' => Invoices::find(),
            ]
        );

        // 'views-dir/invoices/view.phtml' passing variables
        echo $this->view->render(
            'invoices/view',
            [
                'posts' => Invoices::find(),
            ]
        );
    }
}

This is different to the render that Phalcon\Mvc\View implements, which uses controllers and actions as parameters:

<?php

use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Simple;

$params = [
    'invoices' => Invoices::find(),
];

// Phalcon\Mvc\View
$view = new View();
echo $view->render('invoices', 'view', $params);

// Phalcon\Mvc\View\Simple
$simpleView = new Simple();
echo $simpleView->render('invoices/view', $params);

Selección de Vistas

As mentioned above, when Phalcon\Mvc\View is managed by Phalcon\Mvc\Application, the view rendered is the one related with the last controller and action executed. Podría sobreescribir esto usando el método pick():

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property Response $response
 * @property View     $view
 */
class InvoicesController extends Controller
{
    public function listAction()
    {
        // Pick 'views-dir/invoices/search' as view to render
        $this->view->pick('invoices/search');

        // Pick 'views-dir/invoices/list' as view to render
        $this->view->pick(
            [
                'invoices',
            ]
        );

        // Pick 'views-dir/invoices/search' as view to render
        $this->view->pick(
            [
                1 => 'search',
            ]
        );
    }
}

Parciales

Las plantillas parciales son otra forma de romper el proceso de renderizado en trozos más sencillos y manejables que se pueden reutilizar por diferentes partes de la aplicación. Con un parcial, puede mover el código para renderizar una pieza particular de una respuesta a su propio fichero.

Una forma de usar parciales es tratarlas como fragmentos HTML que se pueden inyectar donde se necesite con cualquier parámetro necesario:

<div class='top'>
    <?php $this->partial('shared/ad_banner'); ?>
</div>

<div class='content'>
    <h1>Invoices</h1>

    <p>Check out our specials!</p>
    ...
</div>

<div class='footer'>
    <?php $this->partial('shared/footer'); ?>
</div>

The partial() method does accept a second parameter as an array of variables/parameters that only will exist in the scope of the partial:

<?php 
    $this->partial(
        'shared/ad_banner', 
        [
            'id'   => $site->id, 
            'size' => 'big'
        ]
    ); 
?>

Valores

Phalcon\Mvc\View is available in each controller using the view variable ($this->view). Puede usar ese objeto para establecer variables directamente a la vista desde una acción de controlador usando el método setVar().

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;

/**
 * @property View $view
 */
class InvoicesController extends Controller
{
    public function viewAction($invoiceId)
    {
        $invoice = Invoices::findFirst(
            [
                'conditions' => 'inv_id = :id:',
                'bind'       => [
                    'id' => abs(intval($invoiceId)),
                ]
            ]
        );
        $customer = $invoice->getRelated('customer');

        $this->view->setVar('invoice', $invoice);

        $this->view->customerId = $customer->cst_id;

        $this->view->setVars(
            [
                'name_first' => $customer->name_first,
                'name_last'  => $customer->name_last,
            ]
        );
    }
}

Una variable con el nombre del primer parámetro de setVar() se creará e la vista, lista para usar. The variable can be of any type, from a simple string, integer etc. variable to a more complex structure such as array, collection etc.

<h1>
    Invoices [Customer #]
</h1>

<div class='invoice'>
<?php

    foreach ($invoices as $invoice) {
        echo '<h2>', $invoice->inv_title, '</h2>';
    }

?>
</div>

Motores de Plantillas

Los Motores de Plantillas ayuda a los diseñadores a crear vistas sin el uso de una sintaxis complicada. Phalcon incluye un motor de plantillas poderoso y rápido llamado Volt que ayuda con el desarrollo de la vista sin sacrificar la velocidad de procesamiento.

PHP

The Phalcon\Mvc\View\Engine\Php is the default template engine, if none has been specified.

<?php

use Phalcon\Mvc\View;

$container->set(
    'view',
    function () {
        $view = new View();

        $view->setViewsDir('../app/views/');

        return $view;
    },
    true
);

Volt

Podría querer usar Volt como su motor de plantillas. Para configurarlo necesita registrar el motor y pasarlo al componente vista.

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Di\DiInterface;
use Phalcon\Mvc\ViewBaseInterface;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Volt;

$container = new FactoryDefault();

$container->setShared(
    'voltService',
    function (ViewBaseInterface $view) {
        $volt = new Volt($view, $this);
        $volt->setOptions(
            [
                'always'    => true,
                'extension' => '.php',
                'separator' => '_',
                'stat'      => true,
                'path'      => appPath('storage/cache/volt/'),
                'prefix'    => '-prefix-',
            ]
        );

        return $volt;
    }
);

$container->set(
    'view',
    function () {
        $view = new View();

        $view->setViewsDir('../app/views/');

        $view->registerEngines(
            [
                '.volt' => 'voltService',
            ]
        );

        return $view;
    }
);

Mustache/Twig/Smarty

If you like to use Mustache, Twig or Smarty as your template engine, you can visit our incubator repository for examples on how to activate these engines in your application

Personalizado

When using an external template engine, Phalcon\Mvc\View provides exactly the same view hierarchy, and it is still possible to access the API inside these templates. Si quiere crear su propio motor de plantillas, puede aprovechar el API para realizar las operaciones que necesite.

A template engine adapter is a class that acts as bridge between Phalcon\Mvc\View and the template engine itself. Normalmente, solo necesita dos métodos implementados: __construct() y render(). The first one receives the Phalcon\Mvc\View instance that creates the engine adapter and the DI container used by the application.

El método render() acepta una ruta absoluta al fichero de vista y el conjunto de parámetros de la vista usando $this->view->setVar(). Podría leerlo o requerirlo cuando fuese necesario.

<?php

use Phalcon\Di\DiInterface;
use Phalcon\Mvc\View\Engine\AbstractEngine;
use Phalcon\Mvc\View;

class CustomEngine extends AbstractEngine
{
    /**
     * @param View        $view
     * @param DiInterface $container
     */
    public function __construct($view, DiInterface $container)
    {
        parent::__construct($view, $container);
    }

    /**
     * @param string $path
     * @param array $params
     */
    public function render(string $path, $params)
    {
        // Access view
        $view = $this->view;

        // Options
        $options = $this->options;

        // Render the view
        // ...
    }
}

Ahora puede reemplazar el motor de plantillas con el suyo en la parte de su código de configuración de la vista. Siempre puede usar más de un motor al mismo tiempo. Para lograr esto necesita llamar a Phalcon\Mvc\View::registerEngines() que acepta un vector con las instrucciones de configuración de los motores a registrar. La clave de cada motor es la extensión de los ficheros que necesita procesar. No puede registrar dos motores con la misma clave.

El orden en el que se definen los motores de plantillas con Phalcon\Mvc\View::registerEngines() establece la prioridad de ejecución. If Phalcon\Mvc\View finds two views with the same name but different extensions, it will only render the first one.

<?php

use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Php;

$container->set(
    'view',
    function () {
        $view = new View();

        $view->setViewsDir('../app/views/');

        $view->registerEngines(
            [
                '.my-html' => \CustomEngine::class,
            ]
        );

        $view->registerEngines(
            [
                '.my-html' => \CustomEngine::class,
                '.phtml'   => Php::class,
            ]
        );

        return $view;
    },
    true
);

Inyección de Dependencias

Dado que nuestra vista se registra en nuestro contenedor de Inyección de Dependencias, los servicios disponibles en el contenedor también están disponibles en la vista. Cada servicio está disponible desde una propiedad con el mismo nombre que el servicio definido.

<script type='text/javascript'>

$.ajax({
    url: '<?php echo $this->url->get('invoices/get'); ?>'
})
.done(function () {
    alert('Done!');
});

</script>

In the example above, we are utilizing the Phalcon\Url component in our javascript code, to correctly set up the URL in our application. El servicio está disponible en la vista accediendo a $this->url.

Independiente

You can also use the view as a glue component in your application. Solo necesitará tener la configuración adecuada y luego usar la vista para devolver los resultados procesados.

Renderizado Jerárquico

Una vez configurada la vista con las opciones que necesita su aplicación, puede pasarle variables, como se ha visto arriba, luego llame a start(), render() y finish(). Esto permitirá a la vista compilar los datos y prepararlos para usted. Puede imprimir el contenido producido llamando a getContent().

<?php

use Phalcon\Mvc\View;

$view = new View();

$view->setViewsDir('../app/views/');

//...

$view->setVar('invoices', $invoices);
$view->setVar('isAdmin', true);

$view->start();
$view->render('invoices', 'list');
$view->finish();

echo $view->getContent();

O usando una sintaxis más corta:

<?php

use Phalcon\Mvc\View;

$view = new View();

echo $view->getRender(
    'invoices',
    'list',
    [
        'invoices' => $invoices,
        'isAdmin'  => true,
    ],
    function ($view) {
        $view->setViewsDir('../app/views/');

        $view->setRenderLevel(
            View::LEVEL_LAYOUT
        );
    }
);

Renderizado Simple

You can also use the much smaller Phalcon\Mvc\View\Simple as a stand-alone component. Este componente es extremadamente útil cuando quiere renderizar una plantilla que no siempre está ligada a la estructura de su aplicación. Un ejemplo es renderizar código HTML requerido por emails.

<?php

use Phalcon\Mvc\View\Simple;

$view = new Simple();

$view->setViewsDir('../app/views/');

echo $view->render('templates/welcome');

echo $view->render(
    'templates/welcome',
    [
        'email'   => $email,
        'content' => $content,
    ]
);

En el ejemplo anterior, configuramos el motor y luego mostramos una plantilla renderizada por pantalla (templates/welcome). También podemos enviar parámetros a la plantilla emitiendo un vector como segundo parámetro. Las claves son los nombres de las variables.

Eventos

Phalcon\Mvc\View and Phalcon\Mvc\View\Simple are able to send events to an Events Manager if it is present. Los eventos se disparan usando el tipo view. Si un evento devuelve false puede parar la operación activa. Se soportan los siguientes eventos:

Nombre de evento Disparado Puede detenerse
afterRender Después de completar el proceso de renderizado No
afterRenderView Después de renderizar una vista existente No
beforeRender Antes de iniciar el proceso de renderizado Si
beforeRenderView Antes de renderizar una vista existente Si
notFoundView Cuando no se encuentra una vista No

En el ejemplo siguiente se muestra cómo adjuntar oyentes (listeners) a este componente:

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Events\Event;
use Phalcon\Events\Manager;
use Phalcon\Mvc\View;

$container = new FactoryDefault();
$container->set(
    'view',
    function () {
        $manager = new Manager();

        $manager->attach(
            'view',
            function (Event $event, $view) {
                echo $event->getType(), ' - ', 
                     $view->getActiveRenderPath(), PHP_EOL;
            }
        );

        $view = new View();

        $view->setViewsDir('../app/views/');

        $view->setEventsManager($manager);

        return $view;
    },
    true
);

The following example demonstrates how you can create a plugin that tidies up your HTML produced by the render process using Tidy.

<?php

use Phalcon\Events\Event;

class TidyPlugin
{
    public function afterRender(Event $event, $view)
    {
        $tidyConfig = [
            'clean'          => true,
            'output-xhtml'   => true,
            'show-body-only' => true,
            'wrap'           => 0,
        ];

        $tidy = tidy_parse_string(
            $view->getContent(),
            $tidyConfig,
            'UTF8'
        );

        $tidy->cleanRepair();

        $view->setContent(
            (string) $tidy
        );
    }
}

y ahora podemos adjuntarlo a nuestro gestor de eventos:

<?php

$manager->attach(
    'view:afterRender',
    new TidyPlugin()
);

Excepciones

Any exceptions thrown in the view components (Phalcon\Mvc\View or Phalcon\Mvc\View\Simple) will be of type Phalcon\Mvc\Exception or Phalcon\View\Engine\Volt\Exception if you are using Volt. Puede usar esta excepción para capturar selectivamente sólo las excepciones lanzadas desde este componente.

<?php

use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Exception;

try {

    $view = new View();

    echo $view->getRender(
        'unknown-view',
        'list',
        [
            'invoices' => $invoices,
            'isAdmin'  => true,
        ],
        function ($view) {
            $view->setViewsDir('../app/views/');

            $view->setRenderLevel(
                View::LEVEL_LAYOUT
            );
        }
    );
} catch (Exception $ex) {
    echo $ex->getMessage();
}