Crea tu propio calendario personalizado en PHP

calendario
Calendario usado en smsvacaciones.com

¿Necesitas poner un calendario en tu web? Crea el tuyo propio.

Hoy en día los programadores con perfil Full-stack, es decir, los que tenemos que hacer todo cuando se habla de desarrollar una web solemos tirar de plugin, widget o bundles con demasiada facilidad. ¿Necesitamos hacer un banner slider de cortinilla?, plugin; ¿que hay que poner los perfiles de las redes sociales?, plugin; ¿que hay que validar un formulario (en el lado del cliente)?, plugin; ¿que hay que poner un calendario?: plugin...

Es cierto que conseguimos reducir mucho el tiempo de desarrollo, porque la tendencia es pensar que para que voy a programar algo que ya existe y en cierto modo muchas veces es mejor aprovechar un código ya testado y listo para funcionar, pero un abuso en la utilización de código externo termina por pasar factura, ya sea en tiempos de carga, en la seguridad, o por sobresaturación del equipo del cliente, sobre todo en los dispositivos móviles mas justitos, ya que la mayoría de estos plugin cargan una gran cantidad de código javascript y CSS que no vamos a utilizar. Sin contar que esos incrementos en los tiempos de carga tienen su impacto negativo en el posicionamiento en buscadores.

Si necesitas crear un calendario, simplemente para seleccionar una fecha puedes utilizar sin problema Datepicker de jQuery Ui, está muy bien optimizado y tienes la posibilidad de descargar tan solo ese Widget (como le llaman ellos), no necesitas cargar la librería completa con lo que los tiempos de carga se reducen considerablemente.

Ahora bien, existen casos en los que necesitas realizar un calendario más elaborado y personalizado, donde haya que introducir información en las celdas de alguno de los días, o bien cambiar de color algunas fechas señaladas. Un ejemplo, puede ser en una agencia de viajes online, donde queremos introducir el precio de un viaje para una salida determinada.

Hazlo tú mismo

Existen plugins en javascript que te crean este tipo de calendarios, personalizables dónde se suele utilizar Ajax para cargar esta información en las celdas correspondiente a los días que necesitamos modificar, pero es tan sencillo crear tu propio calendario, a tu gusto y totalmente personalizado que no es necesario utilizar ningún plugin externo para realizar algo tan simple. Tu mismo puedes usar la información que doy en este post para crear tu propia función, o mejor, clase para tener tu propio calendario que podrás usar en cualquiera de tus proyectos.

Nos vamos a centrar en la parte de PHP del calendario, dejando los estilos y las funciones javascript que se pueden implementar en estos calendarios para otro posible artículo.

Un calendario es una tabla

Un calendario es una tabla

Independientemente de que datos queremos mostrar dentro de los días de mi calendario, y de dónde provienen esos datos, vamos a plantearnos en primer lugar cómo podemos maquetar un calendario, y que datos necesitamos para hacerlo.

En definitiva para dibujar un calendario sólo vamos a necesitar conocer el mes y el año que queremos mostrar y pintar una tabla, si buceas un poco en el código fuente del calendario Datepicker de jQuery UI  verás que también lo hacen así, es la forma más sencilla de hacerlo, por lo que nosotros no nos vamos a complicar la vida. Un calendario es una tabla con una serie de filas y columnas. El número de columnas está claro, son siete sea cual sea el mes, una por cada día de la semana. La primera fila es también fija y aparecerá en todos los meses,  la montamos como una cabecera <thead></thead>, y cada celda corresponde con el nombre de los días de la semana, de la siguiente forma:

<table>
  <thead>
    <th>Lunes</th><th>Martes</th><th>Miercoles</th>
    <th>Jueves</th><th>Viernes</th><th>Sábado</th><th>Domingo</th>
  </thead>
  <tbody></tbody>
</table>

Para crear el cuerpo de la tabla <tbody></tbody>, vamos a necesitar conocer los siguientes datos del mes que estamos intentando pintar:

  1. Número de días que tiene el mes.
  2. Día de la semana que empieza el mes.
  3. Número de semanas que tiene el mes.

Todos estos datos los vamos a obtener utilizando la clase DateTime, cuya descripción la puedes encontrar en el manual de php.net

1. Numero de días que tiene el mes:

Inicialmente tenemos que crear un objeto con el mes que estamos intentando mostrar. Creamos el objeto pasando a la clase DateTime como parámetro el día 1 de ese mes con el formato YYYY-MM-DD

//Ejemplo: Queremos mostrar Marzo 2017
$ObjetoFecha = new DateTime("2017-03-01");

El número de días del mes lo obtenemos con el método format y el parámetro t, asi:

$numeroDias = $ObjetoFecha->format('t');

2. Día de la semana que empieza el mes:

De la misma forma, utilizando el objeto del día 1 creado antes, vamos a obtener a que día de la semana pertenece el día 1, eso se hace con el mismo método format y con el parámetro w (ojo: minúscula).

$diaSemana = $ObjetoFecha->format('w’);

Aquí hay que tener cuidado, ya que este método nos devuelve un 0 si el día es el Domingo. Para adaptarlo a nuestro calendario, donde el Domingo se encuentra al final de la semana simplemente convertimos en un 7 el resultado si ha sido un 0, de esta forma:

$diaSemana = $diaSemana == 0 ? 7 : $diaSemana;

3. Número de semanas que tiene el mes

Éste es el único dato un poco mas complicado, porque no hay ningún parámetro en la clase DateTime que nos diga directamente el número de semanas que tiene el mes, por tanto hay que calcularlo. Si que existe, en cambio, un parámetro que nos dice la semana del año en la que está nuestra fecha y es por aquí por donde tenemos que atacar, el parámetro es la W mayúscula. Obteniendo la semana del último dia del mes y la del primero ya tenemos el número de semanas que tiene nuestro mes. Teniendo especial cuidado con el mes de Enero, ya que normalmente nos da como resultado la última semana del año anterior, en lugar de la semana cero y no nos sirve para nuestro cálculo, pero tiene muy fácil solución.

//Sacamos la semana del día uno usando el objeto creado en el punto 1.
//Si es Enero directamente lo inicializamos a cero
$semanaPrimerDia = $ObjetoFecha->format('n') == 1 ? 0 : $ObjetoFecha->format('W');

//Nos da la semana del año en la que estamos
//El parámetro n nos indica el mes en el que 
//estamos sin ceros iniciales: Enero = 1.

Por cierto, si no estas acostumbrado a trabajar con el operador Ternario ? en PHP, la expresión anterior es lo mismo que lo siguiente:

if($ObjetoFecha->format('n') == 1)
{
   $semanaPrimerDia = 0;
}
else
{
   $semanaPrimerDia = $ObjetoFecha->format('W');
}

Una vez tenemos la semana del primer día, nos movemos por el objeto hasta el ultimo dia del mes, esto se realiza con el método modify de la siguiente forma:

//Movemos la fecha hacia delante el numero de días
//que tiene el mes menos uno.
$intervalo = $numeroDias -1;
$ObjetoFecha->modify("+" . $intervalo . " days");

//Y sacamos la semana en la que estamos
$semanaUltimoDia = $ObjetoFecha->format('W');
$numeroSemanas   = $semanaUltimoDia-$semanaPrimerDia+1;
//sumamos 1 porque la primera semana tambien hay que contarla

Pintar el Calendario.

Ya tenemos todos los datos que necesitamos para pintar nuestro calendario, lógicamente, este es un ejemplo básico, lo podemos completar y complicar todo lo que queramos. Normalmente yo creo una clase con distintos métodos, para poder modificar el mes, para cambiar los estilos de la celda (clase) antes de pintar dependiendo del contenido del dia a representar. Un ejemplo de calendario de este tipo lo tengo implementado en smsvacaciones.com, donde por ejemplo se muestra de un color verde la celda para las salidas garantizadas.

Para este ejemplo mostramos lo mas básico, que es dibujar nuestra tabla sin estilos ni nada.

La cabecera con los días de la semana ya la tenemos de antes, vamos a centrarnos en el <tbody> que mostrara los días del mes. Esto se hace con un par de bucles for, uno para sacar  el numero de filas y otro para el numero de columnas, que para un calendario serán siempre siete.

En nuestro ejemplo cada día será una celda que va a tener dentro otra tabla con tres filas, la primera para mostrar el dia en numero, la segunda y tercera para poder escribir contenido, por ejemplo, un precio tachado y un precio sin tachar, como indicando que existe un descuento para esa fecha. Estos datos los vamos a extraer de un array inventado, que bien podemos haber sacado de una base de datos.

A continuación pongo el código en imagen para ver con mas claridad. Al final del artículo hay un resumen con el código en texto para que puedas copiarlo y probarlo.

 

Habría que definir en una hoja de estilos las clases que hemos usado para poder definir los colores, tipo de letra, tamaño y posición del texto dentro de la celda, pero ese no es el objetivo de este articulo.

Espero que te haya resultado sencillo crear un calendario PHP, si creas alguno para un proyecto basándote en los consejos de este artículo déjanos un mensaje en los comentarios para que podamos echarle un vistazo. Yo tengo calendarios funcionando de este tipo en http://smsvacaciones.com y en http://www.viajeaafrica.es

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *