Exemple Calendari. OOP
Calendari, utilitzant la potència dels objectes DateTimeImmutable i DateInterval. Aquesta aproximació manté el codi dins del bloc PHP principal, però utilitza l'OOP per a la manipulació de dates, la qual cosa el fa més segur i menys propens a errors de fus horari.
A continuació, tens el codi utilitzant només objectes de data.
<?php
// index.php
// ----------------------------------------------------
// 1. Configuració i Inicialització de Dades
// ----------------------------------------------------
// Configuració del fus horari (CRÍTIC per a la fiabilitat de dates)
date_default_timezone_set('Europe/Madrid');
// Data d'avui i objectes base (Immutables per seguretat)
$dataAvui = new DateTimeImmutable('today');
// Primer dia del mes que volem mostrar (Setembre 2025)
$dataMesActual = new DateTimeImmutable('first day of this month');
// Últim dia del mes
$darrerDiaMes = new DateTimeImmutable('last day of this month');
// ----------------------------------------------------
// 2. Càlcul de la Data d'Inici (Primer Dilluns Visible)
// ----------------------------------------------------
// Dia de la setmana del 1r dia del mes (N: 1=Dl, 7=Dg)
$diaSetmanaPrimerDia = (int)$dataMesActual->format('N');
// Dies a restar per arribar al Dilluns anterior (o el mateix Dilluns)
$diesARestar = $diaSetmanaPrimerDia - 1;
$dataIteracio = $dataMesActual->modify("-$diesARestar days");
// ----------------------------------------------------
// 3. Càlcul de la Data de Finalització (Últim Diumenge Visible)
// ----------------------------------------------------
// Dia de la setmana de l'últim dia del mes (N: 1=Dl, 7=Dg)
$diaSetmanaDarrerDia = (int)$darrerDiaMes->format('N');
// Dies a sumar per arribar al diumenge (dia 7)
// Si acaba en Diumenge (7), sumem 0 dies. Si acaba en Dissabte (6), sumem 1 dia.
$diesASumar = 7 - $diaSetmanaDarrerDia;
// Data de finalització de la graella (l'últim diumenge de la setmana del mes)
$dataFiGraella = $darrerDiaMes->modify("+$diesASumar days");
// Interval per avançar dia a dia dins del bucle
$intervalDia = new DateInterval('P1D');
?>
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<title>Calendari Ajustat: <?php echo $dataMesActual->format("F - Y"); ?></title>
<style>
.calendari-taula {
border-collapse: collapse;
width: 400px;
text-align: center;
}
.calendari-taula th, .calendari-taula td {
padding: 8px;
border: 1px solid #ccc;
}
.altre-mes {
color: #aaa;
background-color: #f7f7f7;
}
.avui {
background-color: #ffe0b2;
font-weight: bold;
}
</style>
</head>
<body>
<h3> Calendari Ajustat: <?php echo $dataMesActual->format("F - Y"); ?></h3>
<table class="calendari-taula" cellspacing="0" cellpadding="0">
<tr>
<th>Dl</th><th>Dm</th><th>Dc</th><th>Dj</th><th>Dv</th><th>Ds</th><th>Dg</th>
</tr>
<?php
// ----------------------------------------------------
// 4. Bucle d'Iteració
// ----------------------------------------------------
while ($dataIteracio < $dataFiGraella) {
// Comença una nova fila cada dilluns (N=1)
if ($dataIteracio->format('N') == 1) {
echo "<tr>";
}
// --------------------------------------
// Determinació d'Estils
// --------------------------------------
$classe = '';
// A) És el dia actual?
if ($dataIteracio->format('Y-m-d') === $dataAvui->format('Y-m-d')) {
$classe = 'avui';
}
// B) És del mes que estem mostrant?
elseif ($dataIteracio->format('m') !== $dataMesActual->format('m')) {
$classe = 'altre-mes';
}
// Pintar la cel·la (j: dia del mes sense zero inicial)
echo "<td class='$classe'>";
echo $dataIteracio->format('j');
echo "</td>";
// Tanca la fila cada diumenge (N=7)
if ($dataIteracio->format('N') == 7) {
echo "</tr>";
}
// Avançar al dia següent
$dataIteracio = $dataIteracio->add($intervalDia);
}
?>
</table>
</body>
</html>
Explicació OOP
-
Fiabilitat amb
DateTimeImmutable: En lloc d'utilitzar múltiples crides adate()i la funció ambiguastrtotime(), ara tens un objecte$dataMesActualque representa el mes, i un objecte$dataIteracioque es modifica utilitzant el mètode->modify()o->add()juntament ambDateInterval. -
Càlculs Clars: El càlcul del primer dilluns (
$dataIteracio = $dataMesActual->modify("-$diesARestar days")) és molt més explícit i fiable que les manipulacions de strings de l'exemple inicial. -
Iteració Sencilla: El bucle
whileavança dia a dia utilitzant$dataIteracio = $dataIteracio->add($intervalDia), aprofitant la lògica de dates de PHP per gestionar canvis de mes i anys automàticament. -
Consistència: Es calcula la
$dataFiGraellaper garantir que la taula del calendari sempre tingui sis setmanes completes (6 * 7 dies), evitant que la taula es redimensioni segons el dia de la setmana en què acabi el mes.