plantillas - php mvc puro
¿Cómo manejar plantillas para sitios web de MVC? (8)
¿Hay alguna razón en particular por la cual no estés usando un framework MVC como Symfony o CakePHP ?
Sé que esto no responde la pregunta directamente, pero podría ser útil.
Tengo esto marcado como PHP, pero solo porque estaré usando código PHP para mostrar mi problema.
Así que tengo un código como este para el controlador:
switch ($page)
{
case "home":
require "views/home.php";
break;
case "search":
require "views/search.php";
break;
}
Obviamente hay más páginas, pero esto debería ilustrar mi problema. Hay un encabezado común, navegación y pie de página para ambas páginas (y para todas las páginas del sitio). ¿Debería usar múltiples declaraciones requeridas? Mi primera suposición sería:
switch ($page)
{
case "home":
require "templates/header.php";
require "templates/navigation.php";
require "views/home.php";
require "templates/footer.php";
break;
case "search":
require "templates/header.php";
require "templates/navigation.php";
require "views/search.php";
require "templates/footer.php";
break;
}
De alguna manera, mi instinto me dice que esto no es correcto.
Aquí hay una versión simplificada de cómo hago plantillas con mi proyecto actual, si es de alguna utilidad:
class Template {
var $pagename = ''index'';
function __construct() {
$this->pagename = basename($_SERVER[''SCRIPT_NAME''], ''.php'');
register_shutdown_function(array($this, ''do_output''));
}
function do_output() {
$this->header();
$this->display($this->pagename);
$this->footer();
}
function __call($template, array $params) {
call_user_func(array($this, ''display''), $template, params);
}
function display($template, array $params = null) {
include "templates/$template.php";
}
}
La idea detrás de esto es que puede escribir "incluir ''Template.inc''; nueva plantilla;" y organiza que do_output () se ejecute al final del script automáticamente. Le quedan algunas cosas como el método utilizado para pasar variables a la plantilla.
Has mencionado que no estás usando PHP, y hay algunos PHP-ismos: register_shutdown_function () se asegura de que las plantillas sean llamadas antes de los objetos destructores pero después del script principal, y las llamadas a $ this-> header () / footer () son llamadas de función mágica que solo se muestran (''encabezado'') y pantalla (''pie de página''), están destinadas a ser anuladas.
Por supuesto, no hay nada de malo con el uso de un interruptor como el ejemplo que ha publicado, pero no necesita los encabezados / pies de página dentro de cada declaración de caso. Algo como esto haría lo mismo:
require "templates/header.php";
require "templates/navigation.php";
switch ($page)
{
case "home":
require "views/home.php";
break;
case "search":
require "views/search.php";
break;
}
require "templates/footer.php";
... o podría reemplazar el interruptor () con algo basado en el nombre de archivo como he usado anteriormente, si funciona para la configuración de sus páginas. Sin embargo, un cambio es la forma más segura si planea hacerlo a través de parámetros de URL.
El controlador solo debe configurar los datos para la vista y elegir qué vista mostrar. La vista debe ser responsable del diseño de la página, incluidas las páginas compartidas. Me gusta tu primera muestra sobre la segunda.
Sí, deberías dividir el encabezado, el pie de página, etc.
Para el ejemplo particular que muestra, ¿no funcionaría mejor?
require "templates/header.php";
require "templates/navigation.php";
require "views/$page.php";
require "templates/footer.php";
(Donde $ página es ''inicio'', ''búsqueda'', etc.)
Si está utilizando páginas PHP directas como sus plantillas, esencialmente podría establecer una variable global / sesión para contener la página que desea. Tendría una página php de "plantilla principal" que incluye los elementos de encabezado y pie de página, y luego llama a incluir para $ $. Algo así en el controlador:
$_SESSION[''page''] = sanitize_input($_GET[''page'']);
require "templates/main.php";
y luego en el archivo de plantilla main.php:
require "templates/header.php";
require "templates/navigation.php";
require "views/{$_SESSION[''page'']}.php";
require "templates/footer.php";
Estás repitiendo el código. Esto está al lado de nunca una buena idea. Para estar cerca de su ejemplo inicial, algo como esto seguramente sería preferible:
require "templates/header.php";
require "templates/navigation.php";
switch ($page) {
case "home":
require "views/home.php";
break;
case "search":
require "views/search.php";
break;
}
require "templates/footer.php";
Es difícil dar más consejos sin saber más acerca de su enfoque arquitectónico. Por ejemplo, sería aconsejable tener esta parte del controlador, que simplemente prepara la salida, en un lugar muy central y para iniciar el almacenamiento en búfer de salida antes de incluir las plantillas de visualización. De esta forma, podría almacenar el resultado en una variable que tal vez quiera procesar más antes de devolver su contenido en la respuesta HTTP.
Estoy de acuerdo con tvanfosson y quiero explicar por qué y cómo se relaciona con MVC.
El problema con su segundo ejemplo es que el controlador está expuesto a cómo se construye la vista. En un sentido estricto, el controlador clasifica las entradas para la vista y las pasa a ellas, y nada más.
Una forma práctica de pensar esto es si la vista cambia según los requisitos de la aplicación o las entradas mismas. Por ejemplo, si la vista que se genera es para una ventana emergente de JavaScript, podría (y probablemente usará) un conjunto diferente de encabezados, pies de página, CSS, meta, etc. Con su segundo ejemplo, todo lo que está expuesto al controlador . En el primero, es la vista quién sabe cómo generar la vista, que es exactamente el punto.
Para seguir mi ejemplo, imagine que la ventana emergente de JavaScript se rediseña para ser una vista de página completa, o se refactoriza para AJAX (o la pregunta emergente / página / AJAX está determinada por entradas, como un elemento oculto en una campo). Ahora estás destruyendo el controlador porque la vista ha cambiado. No es tanto que hayas violado el MVC, pero no deberías haberte molestado desde el principio.
Si todos los nombres de sus archivos coinciden con su solicitud de vista / página como se muestra en su ejemplo, solo necesita una línea y ninguna declaración de switch
:
require "templates/header.php";
require "templates/navigation.php";
require ''views/'' . $page . ''.php''; // <-- one-liner
require "templates/footer.php";