Para demostrar cuán difícil es escribir un sitio web sin un framework de PHP escribiremos una aplicación web muy simple que consiste en tres páginas HTML: Home, Login y Logout. Para este ejemplo, no usaremos ningún framework e intentaremos usar solo PHP «puro».
No nos confundamos, escribir un sitio web con un framework de PHP puede ser difícil pero con un framework lo haremos de una manera segura y consistente.
Cuando escribimos un sitio web con PHP colocamos el código dentro de un archivo con extensión
.php
. Este archivo se llama script de PHP.
Primero vamos a implementar la página Home para nuestro sitio web. Para
hacer esto creamos el archivo index.php
en la carpeta raíz de documentos de
Apache y colocamos el siguiente código dentro de él.
Para entender el código de abajo necesitamos tener alguna experiencia con PHP. Si no tenemos experiencia con PHP sería bueno revisar algún tutorial de PHP como w3schools.com.
<?php
// index.php
session_start();
// If user is logged in, retrieve identity from session.
$identity = null;
if (isset($_SESSION['identity'])) {
$identity = $_SESSION['identity'];
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Home page</title>
</head>
<body>
<h1>Home</h1>
<?php if ($identity==null): ?>
<a href="login.php">Sign in</a>
<?php else: ?>
<strong>Welcome, <?= $identity ?></strong> <a href="logout.php">Sign out</a>
<?php endif; ?>
<p>
This is a simple website to demonstrate the advantages of a PHP framework
and disadvantages of "pure" PHP.
</p>
</body>
</html>
Si escribimos «http://localhost/index.php» en nuestro navegador web (como Firefox o Google Chrome) deberíamos ver una página como la siguiente:
Ahora vamos a implementar la página de Login. Esta página podría tener un formulario con los campos E-mail y Contraseña. Una vez que el usuario envía el formulario y pasa el proceso de autenticación su identidad se guarda en la variable de sesión de PHP. El script podría tener el siguiente aspecto:
<?php
// login.php
session_start();
// If user is logged in, redirect him to index.php
if (isset($_SESSION['identity'])) {
header('Location: index.php');
exit;
}
// Check if form is submitted.
$submitted = false;
if ($_SERVER['REQUEST_METHOD']=='POST') {
$submitted = true;
// Extract form data.
$email = $_POST['email'];
$password = $_POST['password'];
// Authenticate user.
$authenticated = false;
if ($email=='admin@example.com' && $password=='Secur1ty') {
$authenticated = true;
// Save identity to session.
$_SESSION['identity'] = $email;
// Redirect the user to index.php.
header('Location: index.php');
exit;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Login page</title>
</head>
<body>
<h1>Sign in</h1>
<?php if ($submitted && !$authenticated): ?>
<div class="alert">
Invalid credentials.
</div>
<?php endif; ?>
<form name="login-form" action="/login.php" method="POST">
<label for="email">E-mail</label>
<input type="text" name="email">
<br>
<label for="password">Password</label>
<input type="password" name="password">
<br>
<input type="submit" name="submit" value="Sign In">
</form>
</body>
</html>
Si abrimos la URL «http://localhost/login.php» en nuestro navegador deberíamos ver algo como:
Para iniciar sesión usamos el E-mail y contraseña
admin@example.com
ySecur1ty
respectivamente.
Y finalmente vamos a implementar la página Logout que limpiará la identidad del usuario:
<?php
// logout.php
session_start();
unset($_SESSION['identity']);
header('Location: index.php');
exit;
El código completo de este sitio web se puede encontrar en el ejemplo Pure PHP que acompaña a este libro.
El script de arriba no solo es un ejemplo típico de una sitio web con PHP «puro», además, es un ejemplo de como no deberíamos escribir nuestro sitio web (incluso un sitio web simple). Pero, ¿Que hay de malo con esto?
Los scripts index.php
y login.php
tienden a mezclar todo el código en
un solo archivo. No estamos aplicando separación de conceptos lo que hace
a nuestro código mucho más complejo. Intuitivamente podemos entender que
podría ser más conveniente separar el código responsable de la autenticación
del usuario y el código responsable de la presentación (impresión del HTML).
Las direcciones URL de nuestras páginas web no se ven bien (por ejemplo,
«http://localhost/index.php»). Nos gustaría esconder la extensión .php
.
Ademas, ¿que sucede cuando un usuario intenta visitar una página que no
existe? En este caso nos gustaría redirigir al usuario a una página de
error.
¿Que sucede si nuestro sitio web crece? ¿Como podríamos organizar el código? ¿un script PHP por cada página web? Y que si queremos reusar algunos de nuestros script PHP en otros sitios web sin cambiarlos? Intuitivamente podríamos entender que podría ser útil organizar el código en algún tipo de módulos reusables.
Ambos scripts, index.php
y login.php
, contienen código HTML común. ¿Por qué
copiar y pegar este código de presentación en cada script PHP? Nos
gustaría reusar la misma plantilla maestra en todas o en la mayoría de las
páginas.
El script login.php
tiene problemas de seguridad, porque no implementamos
ninguna validación para las variables POST. Igualmente las sesiones de PHP pueden
ser objeto de cracking. Además, el script PHP login.php
está dentro de la
carpeta raíz de documentos de Apache lo que no es muy seguro (es mejor
colocarlo en un lugar que no sea accesible para los usuarios web). Además, el
index.php
es inseguro porque no se filtra la salida PHP haciéndolo
vulnerable a ataques XSS.
Ninguno de estos scripts usa clases PHP. En teoría si se encapsulan funcionalidades dentro de clases el código estaría mejor estructurado y sería más fácil de mantener.
En estos scripts debemos escribir nuestra propia implementación de la autenticación y de la misma manera las otras funcionalidades. ¿Por qué reinventar la rueda y no usar una biblioteca bien diseñada para esto?
Los problemas de arriba se resuelven fácilmente cuando escribimos un sitio web con un framework (como Zend Framework 3):
En ZF3 usamos el patrón de diseño Modelo-Vista-Controlador separando el código PHP en modelos (el código responsable de la autenticación debería ir aquí), vistas (el código responsable de la impresión del HTML debería ir aquí) y los controladores (el código responsable de recuperar las variables POST debería ir aquí).
El enrutamiento de ZF3 permite tener URL con un aspecto profesional, esto
se consigue ocultando la extensión .php
. Como las URLs se pueden parecer,
se definen mediante reglas estrictas. Si un usuario intenta ver una página
que no existe, es automáticamente redirigido a la página de error estándar.
En ZF3 podemos usar el concepto de módulo. Este permite convenientemente separar nuestros modelos, vistas y controladores en unidades autónomas (módulos) y reusar con facilidad esta unidad en otro proyecto.
En ZF3 podemos definir una maqueta de plantilla de vista común y reusarla en todas o en la mayoría de las páginas web.
ZF3 nos provee de varias características de seguridad como filtros de
de formulario y validadores, escapar la salida, validadores de sesión,
algoritmos criptográficos, etc. En un sitio web con ZF3 solamente el index.php
es accesible para los usuarios web, todos los otros script de PHP se
almacenan fuera de la carpeta raíz de documentos de Apache.
En un sitio web con ZF3 colocamos el código dentro de clases dejándolo mejor organizado.
ZF3 nos provee de muchos componentes que podemos usar en nuestro sitio web: un componente de autenticación, un componente para trabajar con formularios, etc.
Ahora que tenemos una idea de las ventajas de usar Zend Framework 3 y lo que él puede hacer por nosotros dedicaremos la siguiente sección a describir ZF3 con más detalles.