Esta entrada es la número 1 en una serie de entradas de 2 partes. A continuación puedes ver las demás entradas:
- Creando un sistema de notas – Parte 1 – Entrada actual
- Creando un sistema de notas – Parte 2
Para llevar a cabo este tutorial, es necesario un conocimiento avanzado de PHP (Programación Orientada a Objetos, Métodos Estáticos y la librería MySQLi), asumiendo que se tenga conocimiento de las demás tecnologías empleadas.
Planificación
Comencemos organizando nuestras ideas. Primero de todo, vamos a crear un sistema de notas, las cuales serán almacenadas en una base de datos. De aquí sacamos dos conclusiones:
- Necesitaremos un lenguaje del lado del servidor para acceder a nuestras notas.
- Para no estar recargando la página continuamente y simular el acceso directo a la base de datos, implementaremos AJAX mediante la librería jQuery.
En esta primera parte del tutorial, nos dedicaremos exclusivamente al PHP y MySQL.
Organización de ficheros
Necesitaremos:
- Tres archivos PHP: la configuración, la librería y el archivo que recibirá las peticiones AJAX.
- Un archivo HTML.
- Dos archivos CSS: nuestros estilos y un reset.
- Cuatro archivos JavaScript: las librerías jQuery y jQuery UI (de la cual utilizaremos el componente de
sortable
), el plugin jQuery TMPL para almacenar la maquetación que utilizaremos posteriormente en la misma página y nuestroscript.js
que pondrá en funcionamiento todo lo anterior.
Nuestros ficheros quedarán pues organizados de la siguiente manera:
css/ /reset.css /style.css js/ /jquery.js /jquery-ui.js /jquery.tmpl.js /script.js img/ ajax.php config.php core.php index.html
La teoría
Los usuarios llamarán al archivo index.html
, y este, cargará script.js
que realizará una petición al archivo ajax.php
, el cual obtendrá las notas de la base de datos y las devolvera a modo de cadena JSON.
De igual manera, cuando añadamos, editemos, eliminemos… una nota, se realizará una petición al archivo ajax.php
, que ejecutará la acción y devolverá el resultado.
La acción se especificará mediante GET, mientras que los datos irán como POST.
Preparando la base de datos
En nuestro servidor, entraremos dentro de la base de datos que deseemos y ejecutaremos el siguiente código:
CREATE TABLE `notes` ( `id` int(8) NOT NULL AUTO_INCREMENT, `position` int(8) NOT NULL, `text` text COLLATE utf8_unicode_ci NOT NULL, `date` int(10) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=90 ;
Esto creará una nueva tabla llamada notes
.
Campo | Explicación |
---|---|
id | Contiene el número de indentificación de la nota. Se incrementará automáticamente. |
position | Contiene la posición actual de la nota. |
text | Contiene el texto de la nota. |
date | Fecha de creación de la nota en formato timestamp . |
Creando nuestros scripts
config.php
Comenzaremos nuestro sistema definiendo algunas variables de configuración, entre ellas los datos de acceso a la base de datos y el formato de las fechas.
<?php // Errores. error_reporting( 0 ); // Base de datos. $hostname = ''; $username = ''; $password = ''; $database = ''; // Formato de las fechas. $date_format = 'E\l j/m/y \a \l\a\s h:i A'; ?>
core.php
En este archivo incluiremos todas las funciones que utilizaremos posteriormente en ajax.php
. Empezaremos creando un objeto que contendrá las funciones del manejo de notas.
final class Notes { // Prevenimos la instanciación. private function __construct() {} // Funciones }
En su interior añadiremos las funciones principales del manejo de notas. $id
correspondrá al identificador de la nota, $text
a su contenido, $date
a la fecha y $positions
al array
que jQuery UI nos devuelve al ordenar una nota.
/** * Añade una nueva nota. */ public static function add( $text ) { global $mysqli; // Obtenemos la posición de la última nota. if ( $query = $mysqli->query( 'SELECT MAX(position) FROM notes' ) ) { $row = $query->fetch_row(); // La posición de la nueva nota. $position = $row[0] + 1; // Insertamos la nota nueva. if ( $stmt = $mysqli->prepare( 'INSERT INTO notes (text, date, position) VALUES (?, ?, ?)' ) ) { $date = time(); $stmt->bind_param( 'sii', $text, $date, $position ); $stmt->execute(); echo self::serialized_return( $mysqli->insert_id, $text, $date ); } else { show_error( 'Error al intentar añadir la nota.' ); } } else { show_error( 'Error al intentar añadir la nota.' ); } } /** * Ordena las notas actuales. */ public static function rearrange( $positions ) { global $mysqli; // Creamos la consulta, WHEN id THEN posición+1 foreach ( $positions as $position => $id ) $sql .= ' WHEN ' . (int)$id . ' THEN ' . ( (int)$position + 1 ); // La ejecutamos. if ( $stmt = $mysqli->prepare( 'UPDATE notes SET position = CASE id ' . $sql . ' END' ) ) { $stmt->execute(); show_success( 'Las notas fueron ordenadas correctamente.' ); } else { show_error( 'Error al intentar ordenar las notas.' ); } } /** * Elimina una nota. */ public static function delete( $id ) { global $mysqli; // Eliminamos la nota. if ( $stmt = $mysqli->prepare( 'DELETE FROM notes WHERE id = ?' ) ) { $stmt->bind_param( 'i', $id ); $stmt->execute(); show_success( 'La nota se eliminó correctamente.' ); } else { show_error( 'Error la intentar eliminar la nota.' ); } } /** * Edita una nota. */ public static function edit( $id, $text, $date ) { global $mysqli; // Editamos la nota. if ( $stmt = $mysqli->prepare( 'UPDATE notes SET text = ?, date = ? WHERE id = ?' ) ) { $stmt->bind_param( 'sii', $text, $date, $id ); $stmt->execute(); show_success( 'La nota fue editada correctamente.' ); } else { show_error( 'Error la intentar editar la nota.' ); } }
Ahora añadiremos las dos funciones secundarias, que devolveran los datos de las notas como un array
o como una cadena JSON.
/** * Devuelve los datos de la nota como un array asociativo. */ public static function unserialized_return( $id, $text, $date ) { return array( 'id' => $id, 'text' => $text, 'date' => date( $GLOBALS['date_format'], $date ) ); } /** * Devuelve los datos de una nota como JSON. */ public static function serialized_return( $id, $text, $date ) { return json_encode( array( self::unserialized_return( $id, $text, $date ) ) ); }
Para finalizar con nuestro archivo, añadiremos las funciones show_error()
y show_success()
, las cuales nos ayudarán a la hora de manejar errores o mensajes de éxito.
/** * Imprime un error en pantalla. */ function show_error( $message, $code = 500 ) { $errors = array( 500 => 'Internal Server Error' ); header( "HTTP/1.1 {$code} {$errors[$code]}" ); exit( $message ); } /** * Imprime un mensaje de suceso. */ function show_success( $message ) { echo '{"success":"' . $message . '"}'; }
ajax.php
Este archivo se encargará de recojer las peticiones de nuestro sistema. La acción a realizar se recojerá desde la variable $_GET['action']
y los datos de las notas mediante POST.
<?php // Comprobar si la página se cargo con AJAX. if ( strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) != 'xmlhttprequest' ) { die( 'No acceda a esta página directamente desde su navegador.' ); } // Tipo de archivo: JSON. header( 'Content-type: application/json' ); // Incluimos otros archivos. require_once 'config.php'; require_once 'core.php'; // Realizamos la conexión con la base de datos. $mysqli = new mysqli( $hostname, $username, $password, $database ); if ( $mysqli->connect_errno ) { show_error( 'Error de conexión.' ); } // Codificación de caracteres. $mysqli->set_charset( 'utf8' ); // Comparamos la variable action en la URL con las diferentes acciones. switch ( $_GET['action'] ) { // Obtener todas las notas. case 'getAll' : if ( $query = $mysqli->query( 'SELECT * FROM notes ORDER BY position ASC' ) ) { $arr = array(); while ( $row = $query->fetch_assoc() ) { $arr[] = Notes::unserialized_return( $row['id'], $row['text'], $row['date'] ); } echo json_encode( $arr ); } break; // Reorganizar. case 'rearrange' : Notes::rearrange( $_POST['positions'] ); break; // Añadir. case 'add' : Notes::add( '¡Aquí está su nueva nota! Puede eliminarla o editarla utilizando los botones a la izquierda.' ); break; // Eliminar. case 'delete' : Notes::delete( $_POST['id'] ); break; // Editar. case 'edit' : Notes::edit( $_POST['id'], $_POST['text'], $_POST['date'] ); break; // No se especificó ninguna de las acciones anteriores. default : show_error( 'La acción especificada no es correcta.' ); break; } ?>
Continuará
Y con estos últimos fragmentos de código terminamos la primera parte del tutorial. La página está lista para recibir las peticiones. En la parte dos veremos todo lo relativo al lado del cliente. ¡Nos vemos!