1. PHP bàsic

Introducció

PHP és un llenguatge de programació interpretat i del costat del servidor, creat per Rasmus Lerdorf el 1994, inicialment com Personal Home Page, avui significat PHP: Hypertext Preprocessor. Ha evolucionat millorant rendiment, seguretat i suport a la programació orientada a objectes, arribant a les versions 8.x.

Sintaxi i comentaris

El codi PHP s’escriu dins de <?php ... ?> i cada instrucció acaba amb ;.
Comentaris:

Mostrar informació

Variables

Comencen amb $ i PHP assigna el tipus automàticament.
Tipus habituals: string, integer, float, boolean, array, objecte, null
Exemple: $nom = "Joan"; $edat = 25; $actiu = true;

Introducció

Introducció

PHP és un llenguatge de programació interpretat del costat del servidor i d’ús general que s’adapta especialment al desenvolupament web. Va ser creat inicialment pel programador danès-canadenc Rasmus Lerdorf l’any 1994. En l’actualitat, la implementació de referència de PHP és produïda per The PHP Group. Originalment, PHP significava Personal Home Page (Pàgina personal), però ara significa l’inicialisme recursiu PHP: Hypertext Preprocessor.

El codi PHP sol ser processat en un servidor web per un intèrpret PHP desenvolupat com a mòdul, daemon o com a executable d’interfície d’entrada comuna (CGI). En un servidor web, el resultat del codi PHP interpretat i executat —que pot ser qualsevol tipus de dades, com l’HTML generat o dades d’imatges binàries— formaria la totalitat o part d’una resposta HTTP. Existeixen diversos sistemes de plantilles, sistemes de gestió de continguts i frameworks que poden emprar-se per organitzar o facilitar la generació d’aquesta resposta. D’altra banda, PHP pot utilitzar-se per a moltes tasques de programació fora del context web, com aplicacions gràfiques autònomes i el control de drons. També es pot interpretar i executar qualsevol codi PHP a través d’una interfície de línia d’ordres (CLI).

L’intèrpret estàndard de PHP, impulsat pel Zend Engine, és un programari lliure publicat sota Llicència PHP. PHP ha estat àmpliament portat i pot ser desplegat en la majoria de servidors web en gairebé tots els sistemes operatius i plataformes, de manera gratuïta.

El llenguatge PHP va evolucionar sense una especificació formal escrita ni un estàndard fins al 2014, amb la implementació original actuant com l’estàndard de facto que altres implementacions intentaven seguir. Des del 2014, s’ha treballat per crear una especificació formal de PHP.

Visió general

PHP pot ser desplegat en la majoria dels servidors web i en tots els sistemes operatius i plataformes sense cap cost. El llenguatge PHP es troba instal·lat en més de 20 milions de llocs web i en un milió de servidors. Migrar els serveis basats en PHP cap a les noves tecnologies que apareixen suposa un cost que cal justificar monetàriament (sobretot en termes de maquinari i rendiment). Per això, es parla de si el nombre de llocs basats en PHP s’ha vist reduït progressivament en els darrers anys, amb l’aparició de noves tecnologies com Node.js, Golang, ASP.NET, etc.

PHP com tot, està evolucionant avui dia, hi ha disponibles noves llibreries, l’ús de matrius, la gestió de nombres enters, el tractament de la criptografia quan s’utilitza un Base64, el web scraping, la indexació de webs, el precuinat de dades, big data, conjunts de dades, la supervisió de dades i conjunts de proposicions dimensionals. Com veiem, una visió general d’aquest llenguatge és molt més complexa que afirmar que és un llenguatge per al desenvolupament web.  El lloc web de la Viquipèdia està desenvolupat en PHP. És també el mòdul Apache més popular entre els ordinadors que utilitzen Apache com a servidor web.

La gran semblança que té PHP amb els llenguatges més comuns de programació estructurada, com C i Perl, permet a la majoria dels programadors crear aplicacions complexes amb una corba d’aprenentatge molt curta. També els permet involucrar-se en aplicacions de contingut dinàmic sense haver d’aprendre tot un nou conjunt de funcions.

Tot i que en el seu disseny tot està orientat a facilitar la creació de llocs web, és possible crear aplicacions amb una interfície gràfica d’usuari, utilitzant alguna extensió com pot ser PHP-Qt, PHP-GTK, WxPHP, WinBinder, Roadsend PHP, Phalanger, Phc o HipHop VM. També pot ser utilitzat des de la línia d’ordres, de la mateixa manera que Perl o Python poden fer-ho; a aquesta versió de PHP se l’anomena PHP-CLI (Command Line Interface).

Quan el client fa una petició al servidor perquè li enviï una pàgina web, el servidor executa l’intèrpret de PHP. Aquest processa l’script sol·licitat, que generarà el contingut de manera dinàmica (per exemple, obtenint informació d’una base de dades). El resultat és enviat per l’intèrpret al servidor, que al seu torn l’envia al client.

Permet la connexió a diferents tipus de servidors de bases de dades, tant SQL com NoSQL, com ara MySQL, PostgreSQL, Oracle, ODBC, DB2, Microsoft SQL Server, Firebird, SQLite o MongoDB.

PHP també té la capacitat de ser executat en la majoria dels sistemes operatius, com Unix (i derivats, com Linux o Mac OS X) i Microsoft Windows, i pot interactuar amb els servidors web més populars, ja que existeix en versió CGI, com a mòdul per a Apache i com a ISAPI.

PHP és una alternativa a les tecnologies de Microsoft ASP i ASP.NET (que utilitza C# i Visual Basic .NET com a llenguatges), a ColdFusion de l’empresa Adobe, a JSP/Java, CGI/Perl i a Node.js/JavaScript. Tot i que la seva creació i desenvolupament es produeix en l’àmbit dels sistemes lliures, sota la llicència GNU, existeix també un entorn de desenvolupament integrat comercial anomenat Zend Studio.

Història

Va ser originalment dissenyat en Perl, a partir de l’escriptura d’un grup de CGI binaris escrits en llenguatge C pel programador danès-canadenc Rasmus Lerdorf l’any 1994 per mostrar el seu currículum vitae i desar certes dades, com la quantitat de trànsit que la seva pàgina web rebia. El 8 de juny de 1995 es va publicar Personal Home Page Tools després que Lerdorf el combinés amb el seu propi Form Interpreter per crear PHP/FI.

Dos programadors israelians del Technion, Zeev Suraski i Andi Gutmans, van reescriure l’analitzador sintàctic (parser, en anglès) el 1997 i van crear la base del PHP3, i van canviar el nom del llenguatge per PHP: Hypertext Preprocessor. Immediatament van començar les experimentacions públiques de PHP3, i es va publicar oficialment el juny de 1998. L’any 1999, Suraski i Gutmans van reescriure el codi de PHP i van produir el que avui es coneix com a motor Zend. També van fundar Zend Technologies a Ramat Gan, Israel.

El maig de 2000, es va llançar PHP 4 sota la potència del motor Zend 1.0. El 13 de juliol de 2007 es va anunciar la suspensió del suport i desenvolupament de la versió 4 de PHP, i, malgrat el que s’havia anunciat, es va alliberar una nova versió amb millores de seguretat, la 4.4.8, publicada el 13 de gener de 2008, i posteriorment la versió 4.4.9, publicada el 7 d’agost de 2008. Segons aquesta notícia, se li va donar suport a errors crítics fins al 9 d’agost de 2008.

El 13 de juliol de 2004 es va llançar PHP 5, utilitzant el motor Zend Engine 2.0 (o Zend Engine 2). Inclou tots els avantatges que ofereix el nou Zend Engine 2, com ara:

A l’abril de 2020, més de la meitat dels llocs web que feien servir PHP continuaven en la versió discontinuada 5.6 o anterior, i amb la versió 7.0 i 7.1 més del 68 %, que no estan oficialment suportades per The PHP Development Team, mentre que el suport de seguretat és proporcionat per tercers, com Debian (fins al juny de 2020 per a PHP 5). A més, la versió 7.2, la versió amb suport més popular, va deixar de rebre actualitzacions de seguretat el 30 de novembre de 2020.

El 26 de novembre de 2020 es presenta l’actualització del llenguatge PHP a la seva versió 8.0, amb més recursos i optimitzacions, incloent-hi arguments amb nom, tipus d’unió, atributs, promoció de propietats constructives, expressions match, operador nullsafe, JIT (traducció dinàmica) i també millores en el sistema de tipus, gestió d’errors i consistència en general. Aquesta versió va finalitzar el novembre de 2023. També cal considerar que a partir del llançament de PHP 8.2, el 8 de novembre de 2022, WordPress va aconseguir ser compatible l’endemà, 9 de desembre de 2022, seguit del framework CodeIgniter, que va expulsar PHP 7.4 de les seves compatibilitats en les noves actualitzacions.

Al gener de 2023, segons W3Techs, PHP s'utilitzava pel 77,8 % de tots els llocs web que s’executen al costat del servidor. També diu que només el 8% dels usuaris de PHP utilitzen les versions 8.x actualment suportades. L’última versió publicada de PHP és PHP 8.4.

Introducció

Versions

Versión Fecha de lanzamiento Fin de soporte Notas
1.0 08-06-1995   Llamada oficialmente «Personal Home Page Tools (PHP Tools)». Es la primera versión en usar el nombre «PHP».
2.0 01-11-1997   Considerada por sus creadores la «herramienta más rápida y sencilla» para crear páginas web dinámicas.
3.0 06-06-1998 20-10-2000 Zeev Suraski y Andi Gutmans reescribieron la base para esta versión.
4.0 22-05-2000 23-01-2001 Se añadió un sistema de parsing de dos fases llamado motor Zend.
4.1 10-12-2001 12-03-2002 Se introducen 'superglobales' ($_GET$_POST$_SESSION, etc.)
4.2 22-04-2002 06-09-2002 Se deshabilitan register_globals por defecto. Datos recibidos por la red no son insertados en el espacio de nombres global, cerrando posibles agujeros de seguridad en las aplicaciones.
4.3 27-12-2002 31-03-2005 Se introduce CLI, y CGI.
4.4 11-07-2005 07-08-2008 Se añaden páginas man para phpize y php-config.
5.0 13-07-2004 05-09-2005 Motor Zend II con un nuevo modelo de objetos.
5.1 24-11-2005 24-08-2006 Mejoras de rendimiento con la introducción de variables de compilador para el nuevo motor de PHP.
5.2 02-11-2006 06-01-2011 Actividad extensión de filtro por defecto. Soporte JSON nativo.
5.3 30-06-2009 14-08-2014 Soporte para espacios de nombres, enlace estático en tiempo de ejecución, etiqueta de salto (GOTO limitada), Clausuras nativas, Soporte nativo para archivos PHP (phar), recolección de basura para referencias circulares, soporte mejorado para Windows, sqlite3, mysqlnd como reemplazo a libmysql como biblioteca para extensiones que funcionan con MySQL, fileinfo como reemplazado de mime_magic para mejor soporte MIME, extensión de Internacionalización, y etiqueta ereg obsoleta.
5.4 01-03-2012 15-09-2015 Soporte para Trait y sintaxis abreviada de array. Elementos eliminados: register_globalssafe_modeallow_call_time_pass_referencesession_register()session_unregister() y session_is_registered(). Servidor web incorporado. Varias mejoras a características existentes y al rendimiento, y requerimientos de memoria menores.
5.5 20-06-2013 20-06-2016 Nuevos generadores para bucles, empty() soporta expresiones. Se pierde el soporte para Windows XP y Windows Server 2003.
5.6 20-08-2014 31-12-2018 Constantes con expresiones escalares, listas de argumentos de longitud variable y exponencial mediante el operador **.
6     El desarrollo de PHP 6 ha sido retrasado porque los desarrolladores decidieron que el enfoque actual para tratar cadenas Unicode no es correcto, y están considerando formas alternas para la siguiente versión. Las mejoras planeadas para PHP 6 fueron añadidas en su lugar en PHP 5.3.0 (Soporte para espacios de nombre, enlace estático en tiempo de ejecución, funciones lambda, clausuras, goto) y 5.4.0 (traits, revinculación de clausura).

Se abandonó la versión 6 de PHP siendo la siguiente versión la 7.

7.0 03-12-2015 03-12-2018 Mejoras de rendimiento , declaración de tipos de retorno en funciones
7.1 01-12-2016 01-12-2019 Tipo de retorno vacío, Clase constante modificadores de visibilidad, Tipos nullable, iterable de tipo seudo, Captura múltiples tipos de excepciones.
7.2 30-11-2017 30-11-2020 Nuevo tipo de retorno «object»,​ integración de Libsodium como una extensión del núcleo
7.3 6-12-2018 6-12-2021 Sintaxis flexible para Nowdoc y Heredoc, soporte para referencias y deconstrucción de arrays con list(), soporte para PCRE2, función hrtime()
7.4 28-11-2019 28-11-2022 PHP 7.4 llegó al final de su vida útil el 28 de noviembre de 2022.
8.0 26-11-2020 26-11-2023 Ingresadas Nuevas características e incremento de rendimiento
8.1 25-11-2021 25-11-2024 Propiedades «readonly», «enums», «fiber» y nuevas sintaxis
8.2 08-12-2022 08-12-2025 Creación de propiedades dinámicas esta desaprobada y es agregado el atributo AllowDynamicProperties
8.3 23-11-2023 23-11-2026 Tipado de constantes, atributo override y nuevos métodos para obtener valores aleatorios.
8.4 21-11-2024 31-12-2026 Limpieza de código obsoleto, y nuevas características como hooks y visibilidad asimétrica
8.5 20-11-2025 31-12-2027

https://es.wikipedia.org/wiki/PHP

Introducció

Sintaxi bàsica

La sintaxi de PHP es fonamenta en els principis de programació de C.

L’intèrpret de PHP només executa el codi que es troba entre els seus delimitadors. Els delimitadors més comuns són <?php per obrir una secció PHP i ?> per tancar-la. La finalitat d’aquests delimitadors és separar el codi PHP de la resta de codi, com per exemple l’HTML. En els fitxers que contenen només codi PHP, el delimitador ?> es pot ometre. De fet, PHP-FIG, a través de les seves recomanacions estàndard per a PHP, recomana ometre el delimitador ?>, ja que així no s’envia contingut HTML de manera accidental. Per exemple, si s’envia un caràcter «no PHP» (que no és processat per l’intèrpret de PHP), no es podran executar certes accions com enviar capçaleres HTTP mitjançant la funció header(), ja que el procés de resposta ja ha començat.

Les variables es prefixen amb el símbol del dòlar ($) i no és necessari indicar-ne el tipus. Les variables, a diferència de les funcions, distingeixen entre majúscules i minúscules. Les cadenes de caràcters poden estar encapsulades tant amb cometes dobles com amb cometes simples, encara que en el cas de les primeres, es poden inserir variables directament a la cadena, sense necessitat de concatenació.

Els comentaris es poden escriure bé amb dues barres (//) al principi de la línia, o amb un coixinet (#). També permet comentaris multilínia encapsulats entre /* */.

Quant a les paraules clau, PHP comparteix amb la majoria d’altres llenguatges amb sintaxi C les condicions amb if, els bucles amb for i while i els retorns de funcions. Habitualment, en aquest tipus de llenguatges, les sentències han d’acabar amb punt i coma (;).

PHP dins HTML

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Exemple bàsic PHP</title>
</head>

<body>
  <?php
    echo 'Hola món';
  ?>
</body>

</html>

Aplicació PHP mónolitica

<?php

// Àrea de capçaleres, constants i includes (inicialització de l’aplicació)
// Capçalera només per a demostració, no és necessària
header('Content-Type: text/html; charset=UTF-8');

$resposta = '';

// Lògica de l’aplicació, com obtenir usuari de la sessió, contingut, etc.
// Aquest codi podria venir d’una plantilla externa per a una fàcil reutilització
$resposta .= '<!DOCTYPE html>';
$resposta .= '<html lang="ca">';
$resposta .= '';
$resposta .= '<head>';
$resposta .= '  <meta charset="UTF-8" />';
$resposta .= '  <meta name="viewport" content="width=device-width, initial-scale=1.0" />';
$resposta .= '  <title>Exemple bàsic de PHP</title>';
$resposta .= '</head>';
$resposta .= '';
$resposta .= '<body>';
$resposta .= '  <h1>Hola món!</h1>';
$resposta .= '</body>';
$resposta .= '';
$resposta .= '</html>';

// Envia resposta
echo $resposta;

// No es tanca l’"etiqueta" <?php. PHP-FIG recomana aquesta pràctica en
// fitxers que contenen només codi PHP per tal de no enviar contingut HTML de
// manera accidental.

 

Introducció

Els comentaris

En PHP, els comentaris serveixen per afegir notes o explicacions dins del codi que no són executades per l’intèrpret. Són útils per documentar què fa un fragment de codi, recordar idees o facilitar la lectura a altres programadors.

Comentaris d’una sola línia

Amb doble barra //

// Això és un comentari d’una sola línia
$nom = "Maria"; // També es pot posar després d’una instrucció

També pot ser amb #

# També és un comentari d’una sola línia

Comentaris multilínia

Amb /* ... */ s'inicia el comentari amb el símbol /* i es finalitza el bloc de comentari amb */

/* 
  Aquest és un comentari
  que ocupa més d’una línia
*/

 

Introducció

PHP Info

La funció phpinfo() és una de les més conegudes de PHP i s’utilitza principalment per a mostrar informació detallada de la configuració del sistema i del propi PHP.

Quan s’executa dins d’un script, genera una pàgina HTML amb dades com:

Un exemple bàsic seria:

<?php 
  phpinfo();

Aquest codi en un fitxer (per exemple, info.php), si s’executa des del navegador, ens mostrarà una pàgina amb tota la informació del entorn PHP on s'està executant.

Important:
Per motius de seguretat, no és recomanable deixar aquest fitxer accessible en un servidor públic, ja que mostra dades sensibles que poden ser útils per a un atacant (com configuracions internes del sistema).

Introducció

Mostrar informació

En PHP tenim diverses formes senzilles de mostrar informació per pantalla (sobretot en aplicacions web).

echo

És la més comuna i ràpida, en ella podem posar més d'una cadena de text si és precis. Així mateix funciona diferent si el string que es passa com a paràmetre està entre " o està entre '

echo "Hola món!";         
echo "Nom: ", " Maria";

En PHP, <?= ... ?> és una forma abreujada d’escriure <?php echo ... ?>, és a dir, serveix per mostrar directament el valor d’una expressió per pantalla.

<?php
$nom = "Maria";
?>
<p>Hola, <?= $nom ?>!</p>

seria equivalent a,

<?php
$nom = "Maria";
?>
<p>Hola, <?php echo $nom; ?>!</p>

print

És igual que un echo pero només accepta una expressió i retorna 1

print "Hola món!";

print_r()

Aquesta instrucció és un print recursiu, que ens permet mostrar el contingut de variables complexes, ja siguin arrays, arrays multidimensionals, objectes, etc..

$fruites = ["poma", "pera", "plàtan"];
print_r($fruites);

var_dump()

Mostra informació detallada sobre una variable: tipus, longitud i valor

$edat = 25;
var_dump($edat);

die() o exit()

La instrucció die en PHP té una funcionalitat molt clara i senzilla: Atura immediatament l’execució del programa. Si no té paràmetres, només atura l'execució del script i si rep un missatge o variable com a paràmetre, el mostra per pantalla i després acaba l’execució. Resulta una funció molt útil per gestionar errors (per exemple, quan falla una connexió a la base de dades) o per depurar mostrant informació i parant el codi en aquell punt.

<?php

// Aturar l'execució d'un programa
echo "Abans de die.";
die();
echo "Això no s’executarà.";


// Mostrar informació abans d'aturar-se
$missatge = "Error: connexió fallida a la base de dades.";
die($missatge);


// Utilització com a mecanisme de depuració o informació
$usuari = ["nom" => "Maria", "edat" => 30];
die(print_r($usuari, true));


 

Introducció

Variables

Les variables en PHP ens serveixen per emmagatzemar dades i que poden canviar durant l'execució del programa. 

Característiques

// String. Cadena de caràcters o text
$fruita = "poma";

// Integer. Nombres enters
$edat = 30;

// Float/Double. Nombres decimals
$preu = 19.99;

// Boolean. Pot ser true o false
$actiu = true;

// Array. Llistes de valors de qualsevol tipus
$colors = ["vermell", "verd", "blau"];

// Objectes. Instàncies a classes
$persona = new Persona();

// NULL. Variable sense valor assignat
$resposta = null;
// Les variables poden canviar en valor
// i fins i tot de tipus
$var = "Joan";
$var = 23;
$nom = "Joan";
echo "Hola, $nom"; // Mostra: Hola, Joan

amb cometes simples, s'imprimeix literalment i no s'interpreten les variables

echo 'Hola, $nom'; // Mostra: Hola, $nom

Recomanacions

Snake case

$nom_usuari = "Joan";
$edat_usuari = 25;

Camel case

$nomUsuari = "Joan";
$edatUsuari = 25;

Hungarian case

$strNom = "Joan";   // str = string
$intEdat = 25;      // int = integer
$arrFruites = ["poma","pera"]; // arr = array

Exemple

<?php
// ----------------------------
// 1. Snake case
// Les paraules es separen amb guions baixos
$nom_usuari = "Joan";
$edat_usuari = 25;
$correu_usuari = "joan@example.com";

echo "Snake case: $nom_usuari té $edat_usuari anys i el correu és $correu_usuari.<br>";

// ----------------------------
// 2. Camel case
// La primera paraula en minúscula, les següents amb majúscula
$nomUsuari = "Maria";
$edatUsuari = 30;
$correuUsuari = "maria@example.com";

echo "Camel case: $nomUsuari té $edatUsuari anys i el correu és $correuUsuari.<br>";

// ----------------------------
// 3. Hungarian case
// Prefix que indica el tipus de dada
$strNom = "Pere";       // string
$intEdat = 40;          // integer
$strCorreu = "pere@example.com"; // string

echo "Hungarian case: $strNom té $intEdat anys i el correu és $strCorreu.<br>";

Operacions bàsiques

Assignació

<?php
$nom = "Joan";
$edat = 25;

Aritmètiques

<?php
$a = 10;
$b = 3;

$suma = $a + $b;         // 13
$resta = $a - $b;        // 7
$producte = $a * $b;     // 30
$divisio = $a / $b;      // 3.333...
$modul = $a % $b;        // 1 (residu)
$potencia = $a ** $b;    // 1000

Operacions amb strings

<?php
// Concatenació
$nom = "Maria";
$missatge = "Hola " . $nom . "!"; // "Hola Maria!"

// Interpolació
$missatge = "Hola $nom!"; // "Hola Maria!"

// Interpolació NOMES AMB "
$missatge = 'Hola $nom'; // "Hola $nom"

Operacions assignació composta

<?php
$x = 5;
$x += 3;  // $x = $x + 3 = 5 + 3 = 8
$x -= 2;  // $x = 8 - 2 = 6
$x *= 4;  // $x = 6 * 4 = 24
$x /= 6;  // $x = 24 / 4 = 6

$str = 'hola ';
$str .= 'mon'; // $str = $str . 'mon' = 'hola ' . 'mon' = 'hola mon'

Increment i decrement

<?php
$comptador = 1;
$comptador++; // 2 (incrementa en 1)
$comptador--; // 1 (disminueix en 1)  

Introducció

Spread operator (Arrays)

El Operador Spread (o Operador de Desplegament), representat per tres punts consecutius (...), és una característica d'una gran potència en PHP que permet expandir o "desplegar" un objecte iterable (normalment una matriu o un objecte Traversable) en els seus elements individuals.

A PHP, s'utilitza principalment en dos contextos diferents:

  1. En crides de funcions/mètodes (Argument Unpacking, introduït a PHP 5.6).

  2. En definicions de matriu (Array Unpacking, introduït a PHP 7.4).

Argument Unpacking

Aquesta funcionalitat permet passar tots els elements d'una matriu com a arguments separats a una funció o mètode. És l'alternativa moderna a la funció obsoleta call_user_func_array().

Com Funciona?

Quan es col·loca l'operador Spread (...) davant d'una matriu en una crida a una funció, PHP tracta cada element de la matriu com un argument individual.

Imaginem que tenim una funció que suma tres nombres:

PHP
<?php
// Funció que requereix tres arguments separats
function sumar_tres_numeros(int $a, int $b, int $c): int {
    return $a + $b + $c;
}

// Matriu amb els valors que volem utilitzar
$arguments = [10, 20, 30];

// Ús de l'Operador Spread:
// La matriu $arguments es desplega a: sumar_tres_numeros(10, 20, 30)
$resultat = sumar_tres_numeros(...$arguments);

echo "El resultat de la suma és: " . $resultat; // Sortida: 60
?>

Array Unpacking / Merging

Aquesta funcionalitat permet inserir tots els elements d'una matriu dins d'una altra matriu. És una manera molt concisa de fusionar matrius.

Com Funciona?

L'operador Spread es col·loca dins de la sintaxi de definició d'una matriu ([]) per extreure els elements d'una matriu existent i afegir-los a la nova.

PHP
<?php
$fruites = ['poma', 'plàtan'];
$verdures = ['pastanaga', 'enciam'];

// Creació d'una nova matriu fusionant $fruites i $verdures
$cistella = [
    'pa',        // Element normal
    ...$fruites,   // Desplega els elements de $fruites
    'aigua',     // Element normal
    ...$verdures   // Desplega els elements de $verdures
];

print_r($cistella);
/*
Sortida:
Array
(
    [0] => pa
    [1] => poma
    [2] => plàtan
    [3] => aigua
    [4] => pastanaga
    [5] => enciam
)
*/
?>

 

Casos avançats: Regles importants

 

Cas d'Ús Explicació Codi d'Exemple
Matrius Indexades Si les dues matrius són numèriques (indexades), es fusionen sense problemes i la numeració dels índexs es reinicia. ['a', ...['b', 'c'], 'd'] -> ['a', 'b', 'c', 'd']
Matrius Associatives (PHP 8.1+) A partir de PHP 8.1, l'operador Spread es pot utilitzar amb matrius associatives. Les claus repetides de la matriu desplegada sobreescriuen la clau anterior. ['a' => 1, ...['b' => 2, 'a' => 3]] -> ['a' => 3, 'b' => 2]
Alternativa a array_merge() El Spread Operator és generalment més ràpid que la funció array_merge() per a la fusió de matrius simples. [...$arr1, ...$arr2]

Desplegament en la definició de funcions (Argument Packing / Variadic Functions)

Tot i que tècnicament no és el mateix concepte d'operador Spread, la sintaxi ... també s'utilitza en la definició de funcions per capturar un nombre il·limitat d'arguments en una única matriu. Això es coneix com a Argument Packing (Funcions Variàdiques).

PHP
<?php
// Ús de ...$nums per capturar tots els arguments restants
function sumar_qualsevol_quantitat(...$nums): int {
    $total = 0;
    foreach ($nums as $num) {
        $total += $num;
    }
    return $total;
}

// Podem passar 2, 5 o 100 arguments
echo sumar_qualsevol_quantitat(1, 2, 3, 4); // Sortida: 10
?>

Estructures bàsiques

En qualsevol llenguatge de programació, les estructures bàsiques són els blocs fonamentals que permeten controlar el flux d’execució d’un programa.

En PHP, aquestes estructures es divideixen principalment en:

  1. Condicionals: Permeten prendre decisions dins del codi segons si es compleix o no una condició. 

  2. Iteradors o bucles: Permeten repetir blocs de codi diverses vegades de forma controlada. S’utilitzen per processar col·leccions de dades, repetir operacions o recórrer arrays i objectes. Aquestes estructures permeten automatitzar tasques repetitives i prendre decisions intel·ligents segons les dades que es processen.

Estructures bàsiques

Condicionals

Comparadors

<?php
$a = 10;
$b = 20;

var_dump($a == $b);  // false (igualtat)
var_dump($a != $b);  // true  (diferent)
var_dump($a < $b);   // true
var_dump($a >= $b);  // false

// Comparador estricte === o !==
$a = 5;       // enter
$b = "5";     // cadena

var_dump($a == $b);   // true  → només compara el valor (5 == "5")
var_dump($a === $b);  // false → compara valor i tipus (enter ≠ cadena)

$c = 10;
$d = 10;

var_dump($c === $d);  // true → mateix valor i mateix tipus

Operador Significat Exemple ($a = 5; $b = "5";)
== Igualtat de valor true (5 és igual a "5")
!= Diferent (per valor) false
<, > Menor / Major Depèn dels valors
>=, <= Major/menor o igual Depèn dels valors
=== Igualtat estricta (valor + tipus) false
!== Diferent estricta (valor o tipus) true

Condicionals

Els condicionals en PHP són instruccions que permeten executar diferents blocs de codi segons si es compleix una condició (true o false)

if

<?php
  
$edat = 18;

if ($edat >= 18) {
    echo "Ets major d’edat.";
}

if...else

<?php
$login_correcte = false;

if ($login_correcte) {
    echo "Benvingut!";
} else {
    echo "Error: usuari o contrasenya incorrectes.";
}

if...elseif...else

<?php
$nota = 7;

if ($nota >= 9) {
    echo "Excel·lent";
} elseif ($nota >= 5) {
    echo "Aprovat";
} else {
    echo "Suspès";
}

switch

Alternativa a tenir molts if...elseif. Permet comparar una variable amb diferents casos

<?php
$dia = "dilluns";

switch ($dia) {
    case "dilluns":
        echo "Comença la setmana!";
        break;
    case "dissabte":
    case "diumenge":
        echo "És cap de setmana!";
        break;
    default:
        echo "Un altre dia qualsevol.";
}

Important: Cal el break per evitar que continuï executant els següents casos

Operador ternari (?:)

És la forma abreujada de tenir un if...else

<?php
$edat = 20;
$resultat = ($edat >= 18) ? "Major d’edat" : "Menor d’edat";
/*
if ($edat>=18) 
  $resultat="Major d'edat";
else 
  $resultat="Menor d'edat";
*/
echo $resultat;

Operador null coalescing (??)

Aquest operador verifica si una variable està definida i no és null. Sinó, dona un valor per defecte.

<?php
$usuari = $_GET['usuari'] ?? "Anònim";
echo "Hola, $usuari!";

/*************************************************
  Comprovar si la variable existeix i no és null
  - Si a l’URL tenim ?usuari=Maria, mostrarà “Hola, Maria!”.
  - Si no hi ha cap usuari, mostrarà “Hola, Anònim!”.
***************************************************/

if (isset($_GET['usuari']) && $_GET['usuari'] !== null) {
    $usuari = $_GET['usuari'];
} else {
    $usuari = "Anònim";
}
echo "Hola, $usuari!";

match (PHP 8+)

Simillar a switch, però més net i amb retorn de valors directament

<?php
$nota = 8;

$resultat = match (true) {
    $nota >= 9 => "Excel·lent",
    $nota >= 5 => "Aprovat",
    default => "Suspès",
};

echo $resultat;

Estructures bàsiques

Bucles

for

Aquest tipus de bucle, com en d'altres llenguatges de programació s'utilitza quan sabem el numero d'iteracions necessitem (un index numèric)

<?php
// Exemple: imprimir nombres de l'1 al 5
for ($i = 1; $i <= 5; $i++) {
    echo $i . " ";
}
// Sortida: 1 2 3 4 5

while

<?php
$n = 1;
while ($n <= 5) {
    echo $n . " ";
    $n++;
}
// Sortida: 1 2 3 4 5

do...while

<?php
$n = 10;
do {
    echo "Executat almenys una vegada\n";
} while ($n < 5);
// Sortida: Executat almenys una vegada

foreach

Aquest resulta ideal per recórrer arrays i objectes iterables, resulta la forma més comuna d'iterar un array sobretot quan treballem amb bases de dades.

<?php
$fruites = ["poma", "pera", "plàtan"];

// Només valors
foreach ($fruites as $fruita) {
    echo $fruita . " ";
}
// Sortida: poma pera plàtan

$n_elements = count ($fruites);
for ($i=0;$i<$n_elements;$i++)
{
    echo $fruites[$i] . " ";  
}
// Sortida: poma pera plàtan

// Claus i valors (arrays associatius)
$usuari = ["nom" => "Anna", "edat" => 28];
foreach ($usuari as $clau => $valor) {
    echo "$clau: $valor\n";
}
// Sortida:
// nom: Anna
// edat: 28

foreach (array associatiu)

El bucle foreach a PHP és una eina útil per recórrer fàcilment els elements d'un array, ja sigui indexat (cas anterior) o associatiu. A diferència d'un bucle for tradicional, no necessites mantenir un comptador ni conèixer la grandària de l'array per avançat. Simplement, itera sobre cada element de l'array, de principi a fi.

Els foreach resulten especialment útils quan treballes amb arrays associatius ja que permet accedir tant a la clau com al valor de cada parell.

<?php
$edats = array("Pere" => 35, "Anna" => 28, "Joan" => 42);
foreach ($edats as $nom => $edat) {
    echo "L'edat de " . $nom . " és " . $edat . " anys.<br>";
}
// Sortida:
// L'edat de Pere és 35 anys.
// L'edat de Anna és 28 anys.
// L'edat de Joan és 42 anys.
Arrays associatius

Els arrays associatius són arrays on els elements s'identifiquen mitjançant una clau (key), que pot ser una cadena de text o un nombre, en lloc d'un índex numèric. Aquesta estructura és perfecta per guardar dades on cada valor té un nom o una etiqueta descriptiva.

El foreach amb la sintaxi de clau i valor és la manera ideal de processar aquest tipus d'arrays. La clau ($nom a l'exemple anterior) et serveix per identificar l'element, i el valor ($edat) és la dada que hi ha associada.

<?php
$ciutats_paissos = [
    "París" => "França",
    "Tòquio" => "Japó",
    "Barcelona" => "Espanya",
    "Nova York" => "EUA"
];

echo "<h3>Ciutats i països:</h3>";

//*****************************************
// foreach ( $coleccio as $clau => $valor)
//*****************************************
foreach ($ciutats_paissos as $ciutat => $pais) {
    echo "La ciutat de **" . $ciutat . "** es troba a **" . $pais . "**.<br>";
}
// Sortida:
// La ciutat de París es troba a França.
// La ciutat de Tòquio es troba a Japó.
// La ciutat de Barcelona es troba a Espanya.
// La ciutat de Nova York es troba a EUA.

foreach per referència (modificar l'array)

<?php
$nums = [1, 2, 3];
foreach ($nums as &$n) {
    $n *= 2; // modifica l'array original
}
unset($n); // IMPORTANT: trencar la referència per evitar efectes laterals
print_r($nums);
// Sortida: Array ( [0] => 2 [1] => 4 [2] => 6 )

Atenció: després d’un foreach amb referencia sempre fes unset($varReferencia) per evitar que la variable segueixi apuntant a l’últim element.

Bucles anidats

<?php
// Taula de multiplicar 1..3
for ($i = 1; $i <= 3; $i++) {
    for ($j = 1; $j <= 3; $j++) {
        echo $i * $j . " ";
    }
    echo PHP_EOL;
}
// Sortida:
// 1 2 3
// 2 4 6
// 3 6 9

Sintaxi embedida

Per quan barreges HTML i PHP (for: / endfor;, / foreach: / endforeach;, while : / endwhile;, if: / endif;):

<?php $items = ["a","b","c"]; ?>
<ul>
<?php foreach ($items as $item): ?>
    <li><?= $item ?></li>
<?php endforeach; ?>
</ul>

Paràmetres en HTTP

El Hypertext Transfer Protocol s'utilitza en la comunicació web, com es gestionen els paràmetres és crucial per a la seva funcionalitat. Aquests paràmetres s'envien principalment per dos mètodes de sol·licitud: GET i POST

Mètode GET

S'utilitza per demanar dades al servidor, la característica principal és que els paràmetres s'incorporen a l'URL, fent-los visibles a la barra d'adreces del navegador i en l'historial. https://exemple.com/cerca?q=programacio&cat=web.

Els paràmetres formen parelles clau=valor separades per un &, són ideals per a consultes que no modifiquen l'estat del servidor: cerques, filtres, navegació... Són operacions que repetint la sol·licitud s'obté el mateix resultat sense efectes secundaris. Un avantatge notable és que les URLs amb paràmetres GET es poden compartir i ser indexades pels motors de cerca. No obstant això, tenen una limitació de longitud i, a causa de la seva visibilitat, no són aptes per a dades sensibles com contrasenyes.

Mètode POST

S'utilitza per enviar dades al servidor, crear o actualitzar un recurs. Els paràmetres s'envien al cos de la sol·licitud HTTP, no a la URL. Això els fa invisibles i molt més segurs per a informació privada o confidencial.

És el preferit per formularis de contacte, inici de sessió, o càrrega d'arxius, ja que permeten enviar dades sense restriccions de longitud de GET. L'ús de POST s'utilitza per a accions que modifiquen l'estat del servidor: registrar un nou usuari... L'inconvenient de les URL és no poder compartir-les ni desar com a marcadors.

Paràmetres en HTTP

El protocol HTTP

El protocol HTTP (Hypertext Transfer Protocol) és el llenguatge que utilitzen els navegadors web i els servidors per comunicar-se a Internet. És un protocol client-servidor sense estat, el que significa que cada intercanvi de dades és independent i el servidor no guarda informació sobre les sol·licituds anteriors.

El funcionament es basa en un cicle simple de sol·licitud i resposta:

  1. El client (el navegador) envia una sol·licitud HTTP. Aquesta sol·licitud conté un mètode (com GET per obtenir dades o POST per enviar-les), la URL del recurs que es vol, i diverses capçaleres que proporcionen informació addicional sobre el client (per exemple, el tipus de navegador).

  2. El servidor web rep i processa la sol·licitud. Llegeix el mètode i la URL per determinar quina acció ha de fer.

  3. El servidor envia una resposta HTTP. La resposta inclou un codi d'estat que informa sobre el resultat de la sol·licitud (per exemple, 200 OK si tot ha anat bé, o 404 Not Found si el recurs no existeix), capçaleres amb informació del servidor i, finalment, el cos de la resposta, que és el contingut sol·licitat (com ara el codi HTML d'una pàgina web, una imatge o un arxiu).

image.png

image.png image.png

Els mètodes HTTP són verbs d'acció que defineixen el tipus d'operació que un client vol realitzar sobre un recurs a un servidor web. Són una part fonamental del protocol HTTP i guien la comunicació entre el navegador i el servidor. 

El concepte d'idempotència es refereix a una operació que pot ser executada múltiples vegades sense canviar el resultat final més enllà de la primera execució. En altres paraules, aplicar la mateixa operació una vegada o mil vegades produeix el mateix efecte sobre el recurs o l'estat del sistema.

Mètodes HTTP

Mètode Funció principal Dades a la URL? Seguretat Idempotent?
GET Obtenir un recurs Baixa ✅ Sí
POST Enviar dades per crear un recurs No Alta ❌ No
PUT Actualitzar o crear un recurs complet No Alta ✅ Sí
DELETE Eliminar un recurs No Alta ✅ Sí
HEAD Obtenir només les capçaleres del recurs Baixa ✅ Sí
PATCH Modificar parcialment un recurs No Alta ❌ No
OPTIONS Retorna els mètodes per un recurs Baixa ❌ No

Existeixen altres mètodes i fins i tot, altres protocols que s'han basat en HTTP com WebDAV afegeixen mètodes addicionals.

Codis de resposta

Categoria 1xx: Informació 

Indiquen que la sol·licitud ha estat rebuda i el procés continua. Normalment no es veuen al navegador.

Categoria 2xx: Èxit

Indiquen que la sol·licitud s'ha processat correctament.

Categoria 3xx: Redirecció 

Indiquen que es necessita una acció addicional per completar la sol·licitud, generalment redirigint el navegador a una nova URL.

Categoria 4xx: Error del Client 

Indiquen que hi ha hagut un error a causa d'una sol·licitud incorrecta per part del client.

Categoria 5xx: Error del Servidor 

Indiquen que el servidor ha fallat en processar una sol·licitud vàlida.

Paràmetres en HTTP

Mètode GET

El mètode GET és el més comú i es fa servir per a sol·licitar dades d'un servidor. Els paràmetres s'envien com a part de la URL i són visibles a la barra d'adreces del navegador. La sintaxi és la següent:

URL_base?clau1=valor1&clau2=valor2

Quan un usuari fa clic a un enllaç o escriu una adreça amb paràmetres GET, el navegador envia una sol·licitud al servidor que inclou aquesta URL completa. El servidor web rep la sol·licitud i un llenguatge de programació com PHP pot accedir a aquests paràmetres a través de l'array associatiu $_GET.

Avantatges:

Inconvenients:

El mètode GET exemplifica visibilitat i simplicitat

Com funciona?

Quan fas una sol·licitud GET, el navegador inclou els paràmetres com a part de l'adreça, després d'un signe d'interrogació (?). Cada parell de clau=valor es separa amb un ampersand (&).

Exemple: https://exemple.com/productes.php?categoria=roba&preu_max=50

Aquí, el servidor sap que ha de buscar productes de la categoria "roba" amb un preu màxim de "50".

<!DOCTYPE html>
<html lang="ca">
<head>
    <meta charset="UTF-8">
    <title>La nostra Botiga</title>
</head>
<body>

<h1>Llista de Productes</h1>

<?php

// Primer, comprovem si els paràmetres 'categoria' i 'preu_max' existeixen a la URL.
// Això prevé errors si algú accedeix a la pàgina sense filtres.
if (isset($_GET['categoria']) && isset($_GET['preu_max'])) {
    
    // Accedim als valors de l'array superglobal $_GET
    $categoria_filtre = $_GET['categoria'];
    $preu_maxim_filtre = $_GET['preu_max'];

    // Simulem una base de dades amb un array
    $productes = [
        ['nom' => 'Samarreta', 'categoria' => 'roba', 'preu' => 25],
        ['nom' => 'Pantalons', 'categoria' => 'roba', 'preu' => 60],
        ['nom' => 'Sabates esportives', 'categoria' => 'calçat', 'preu' => 85],
        ['nom' => 'Jaqueta texana', 'categoria' => 'roba', 'preu' => 45],
        ['nom' => 'Vestit', 'categoria' => 'roba', 'preu' => 70],
    ];

    echo "<p>Mostrant productes de la categoria **'{$categoria_filtre}'** ";
    echo "amb un preu màxim de **{$preu_maxim_filtre}€**.</p>";
    echo "<ul>";

    // Recorrem el nostre array de productes i apliquem els filtres
    foreach ($productes as $producte) {
        if ($producte['categoria'] === $categoria_filtre && $producte['preu'] <= $preu_maxim_filtre) {
            echo "<li>{$producte['nom']} ({$producte['preu']}€)</li>";
        }
    }

    echo "</ul>";

} else {
    // Si no s'han passat paràmetres, mostrem un missatge d'avís
    echo "<p>Si us plau, utilitza la URL amb paràmetres per filtrar els ";
    echo "productes, per exemple: <br><br>";
    echo "<code>https://exemple.com/productes.php?categoria=roba&preu_max=50</code></p>";
}

?>
</body>
</html>

Paràmetres en HTTP

Mètode POST

El mètode POST s'utilitza per enviar dades al servidor per crear o actualitzar un recurs. Els paràmetres no s'envien a la URL, sinó que s'incorporen al cos de la sol·licitud HTTP. Aquesta informació no és visible a la barra d'adreces i és més segura per transmetre dades sensibles.

El mètode POST és l'estàndard per a formularis web que impliquen:

A PHP, el servidor rep aquestes dades en una variable superglobal diferent: $_POST, que també és un array associatiu.

Avantatges:

Inconvenients:

El mètode POST exemplifica la seguretat i la privacitat

Com funciona?

Quan envies un formulari amb el mètode POST, el navegador recull les dades introduïdes per l'usuari i les empaqueta en el cos de la sol·licitud. Aquesta informació no és visible a la barra d'adreces del navegador, cosa que la fa ideal per a dades sensibles.

Al servidor, un llenguatge com PHP accedeix a aquestes dades a través de l'array superglobal $_POST, que conté els valors amb les claus corresponents als noms dels camps del formulari.

Exemple: un formulari de contacte

A continuació, tenim un formulari HTML que envia dades per POST a un fitxer PHP, que les processa i les mostra.

Fitxer: contacte.php

<!DOCTYPE html>
<html lang="ca">
<head>
    <meta charset="UTF-8">
    <title>Formulari de Contacte</title>
</head>
<body>

    <h2>Contacta amb nosaltres</h2>
    <form action="processar_contacte.php" method="post">
        <label for="nom">Nom:</label><br>
        <input type="text" id="nom" name="nom" required><br><br>
        
        <label for="email">Correu electrònic:</label><br>
        <input type="email" id="email" name="email" required><br><br>
        
        <label for="missatge">Missatge:</label><br>
        <textarea id="missatge" name="missatge" rows="4" required></textarea><br><br>
        
        <input type="submit" value="Enviar Missatge">
    </form>

</body>
</html>

Fitxer: processar_contacte.php

<?php

// Primer, comprovem si la sol·licitud s'ha enviat pel mètode POST
// if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (isset($_POST['nom']) && !empty($_POST['nom']) &&
    isset($_POST['email']) && !empty($_POST['email']) &&
    isset($_POST['missatge']) && !empty($_POST['missatge'])) {
    
    // Accedim als valors de l'array superglobal $_POST.
    // L'ús de isset() és una bona pràctica per evitar errors si els camps estan buits.
    $nom = isset($_POST['nom']) ? htmlspecialchars($_POST['nom']) : "No s'ha especificat";
    $email = isset($_POST['email']) ? htmlspecialchars($_POST['email']) : "No s'ha especificat";
    $missatge = isset($_POST['missatge']) ? htmlspecialchars($_POST['missatge']) : "No s'ha especificat";
    
    // Mostrem les dades rebudes
    echo "<h1>Missatge rebut correctament!</h1>";
    echo "<p>Gràcies, **{$nom}**.</p>";
    echo "<p>El teu correu electrònic és: {$email}</p>";
    echo "<p>El teu missatge és:</p>";
    echo "<p><em>\"{$missatge}\"</em></p>";
    
    // Aquí podríem afegir lògica addicional, com guardar les dades
    // a una base de dades, o enviar un correu electrònic.
    
} else {
    // Si la pàgina s'ha accedit directament sense enviar el formulari
    echo "<p>Aquesta pàgina s'ha de carregar des d'un formulari.</p>";
}

htmlspecialchars(): Aquesta funció és un pas de seguretat crucial. Converteix caràcters especials com < i > en entitats HTML (&lt;, &gt;). Si un usuari maliciós introduís codi HTML o JavaScript al formulari, htmlspecialchars() evitaria que el navegador l'interpretés, prevenint atacs de Cross-Site Scripting (XSS).

Un únic arxiu?

<!DOCTYPE html>
<html lang="ca">
<head>
    <meta charset="UTF-8">
    <title>Formulari de Contacte</title>
</head>
<body>

    <h2>Contacta amb nosaltres</h2>

    <?php
    // Comprovem si la sol·licitud és de tipus POST per saber si s'ha enviat el formulari.
    if ($_SERVER["REQUEST_METHOD"] == "POST") {

        // Validem que els camps obligatoris existeixin i no estiguin buits.
        if (isset($_POST['nom']) && !empty($_POST['nom']) &&
            isset($_POST['email']) && !empty($_POST['email']) &&
            isset($_POST['missatge']) && !empty($_POST['missatge'])) {
            
            // Assignem les dades a variables i les sanititzem amb htmlspecialchars().
            $nom = htmlspecialchars($_POST['nom']);
            $email = htmlspecialchars($_POST['email']);
            $missatge = htmlspecialchars($_POST['missatge']);

            // Mostrem el missatge de confirmació amb les dades rebudes.
            echo "<div style='color: green; font-weight: bold;'>";
            echo "Missatge rebut correctament! Gràcies, {$nom}.";
            echo "</div>";
            echo "<p>El teu correu electrònic és: {$email}</p>";
            echo "<p>El teu missatge és:</p>";
            echo "<p><em>\"{$missatge}\"</em></p>";
            
            // Aquí afegiries la lògica per guardar les dades, enviar un correu, etc.

        } else {
            // Missatge d'error si algun camp obligatori no s'ha omplert.
            echo "<div style='color: red; font-weight: bold;'>";
            echo "Error: Si us plau, omple tots els camps del formulari.";
            echo "</div>";
        }

    }
    ?>

    <form action="" method="post">
        <label for="nom">Nom:</label><br>
        <input type="text" id="nom" name="nom" required><br><br>
        
        <label for="email">Correu electrònic:</label><br>
        <input type="email" id="email" name="email" required><br><br>
        
        <label for="missatge">Missatge:</label><br>
        <textarea id="missatge" name="missatge" rows="4" required></textarea><br><br>
        
        <input type="submit" value="Enviar Missatge">
    </form>

</body>
</html>

Paràmetres en HTTP

Objecte SERVER

L'objecte $_SERVER a PHP és un array global que conté informació sobre l'entorn del servidor i l'execució del script. Les seves dades varien en funció de si el script s'executa des d'un servidor web o des de la línia de comandes. S'utilitza per obtenir informació com ara l'adreça IP del client, el nom del servidor, la ruta del script, i els headers HTTP de la petició.

Funcions principals i elements

Aquest array associatiu es crea automàticament per PHP i conté una gran varietat de dades útils. . La seva utilitat rau en la capacitat de proporcionar informació contextual per a la lògica de l'aplicació. A continuació, es detallen alguns dels seus elements més comuns i les seves funcions:

Element Funció Exemple de valor
$_SERVER['REQUEST_METHOD'] Indica el mètode de la petició HTTP utilitzat per accedir a la pàgina (per exemple, GET, POST, PUT). GET
$_SERVER['PHP_SELF'] Retorna el nom del fitxer del script que s'està executant, relatiu a la carpeta arrel del document. /carpeta/fitxer.php
$_SERVER['HTTP_HOST'] Conté el nom de domini del servidor al qual s'ha enviat la petició. www.exemple.cat
$_SERVER['SERVER_NAME'] Retorna el nom del servidor host. En un entorn de hosting compartit, pot ser diferent d'HTTP_HOST. www.exemple.cat
$_SERVER['SERVER_ADDR'] Proporciona l'adreça IP del servidor on s'executa el script. 192.168.1.100
$_SERVER['REMOTE_ADDR'] Retorna l'adreça IP del client que ha realitzat la petició a la pàgina. 123.45.67.89
$_SERVER['DOCUMENT_ROOT'] Indica la ruta absoluta del directori arrel del document del servidor. /var/www/html
$_SERVER['QUERY_STRING'] Conté la part de la URL que ve després del signe d'interrogació (?). id=123&nom=joan
$_SERVER['HTTP_USER_AGENT'] Proporciona informació sobre el navegador web i el sistema operatiu del client. Mozilla/5.0 (Windows NT 10.0; ...)
$_SERVER['SCRIPT_FILENAME'] Retorna el nom absolut de la ruta del script actual que s'està executant. /var/www/html/carpeta/fitxer.php

Elements que no es recomana emprar per seguretat

Tot i la seva utilitat, l'ús d'alguns elements de $_SERVER pot ser perillós si no es manipulen correctament, ja que es poden falsificar fàcilment. L'ús inadequat d'aquestes variables pot portar a vulnerabilitats com ara atacs de cross-site scripting (XSS). És fonamental validar i sanititzar sempre qualsevol dada obtinguda a través d'aquestes variables. .

Aquests són els elements que s'han d'usar amb precaució:

Per mitigar aquests riscos, s'han de sanititzar i validar sempre les dades rebudes, utilitzant funcions com htmlspecialchars() per evitar l'execució de codi HTML/JavaScript i filtres de validació (filter_var()) quan sigui possible.

Altres elements de capçalera

Element/Code Description
$_SERVER['PHP_SELF'] Returns the filename of the currently executing script
$_SERVER['GATEWAY_INTERFACE'] Returns the version of the Common Gateway Interface (CGI) the server is using
$_SERVER['SERVER_ADDR'] Returns the IP address of the host server
$_SERVER['SERVER_NAME'] Returns the name of the host server (such as www.w3schools.com)
$_SERVER['SERVER_SOFTWARE'] Returns the server identification string (such as Apache/2.2.24)
$_SERVER['SERVER_PROTOCOL'] Returns the name and revision of the information protocol (such as HTTP/1.1)
$_SERVER['REQUEST_METHOD'] Returns the request method used to access the page (such as POST)
$_SERVER['REQUEST_TIME'] Returns the timestamp of the start of the request (such as 1377687496)
$_SERVER['QUERY_STRING'] Returns the query string if the page is accessed via a query string
$_SERVER['HTTP_ACCEPT'] Returns the Accept header from the current request
$_SERVER['HTTP_ACCEPT_CHARSET'] Returns the Accept_Charset header from the current request (such as utf-8,ISO-8859-1)
$_SERVER['HTTP_HOST'] Returns the Host header from the current request
$_SERVER['HTTP_REFERER'] Returns the complete URL of the current page (not reliable because not all user-agents support it)
$_SERVER['HTTPS'] Is the script queried through a secure HTTP protocol
$_SERVER['REMOTE_ADDR'] Returns the IP address from where the user is viewing the current page
$_SERVER['REMOTE_HOST'] Returns the Host name from where the user is viewing the current page
$_SERVER['REMOTE_PORT'] Returns the port being used on the user's machine to communicate with the web server
$_SERVER['SCRIPT_FILENAME'] Returns the absolute pathname of the currently executing script
$_SERVER['SERVER_ADMIN'] Returns the value given to the SERVER_ADMIN directive in the web server configuration file (if your script runs on a virtual host, it will be the value defined for that virtual host) (such as someone@w3schools.com)
$_SERVER['SERVER_PORT'] Returns the port on the server machine being used by the web server for communication (such as 80)
$_SERVER['SERVER_SIGNATURE'] Returns the server version and virtual host name which are added to server-generated pages
$_SERVER['PATH_TRANSLATED'] Returns the file system based path to the current script
$_SERVER['SCRIPT_NAME'] Returns the path of the current script
$_SERVER['SCRIPT_URI'] Returns the URI of the current page

Quines variables tinc?

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>Server variable</title>
   </head>
   <body>
      <h1>VARIABLE $_SERVER</h1>
      
      <?php
         foreach ($_SERVER as $key => $value) {
            echo "<strong>$key</strong>: " . $value . "<br/>";
         }   
      ?>

   </body>
</html>

Paràmetres en HTTP

HTTP Header

Com funciona?

Un redireccionament HTTP és una instrucció que un servidor web envia a un navegador per indicar-li que la pàgina sol·licitada s'ha mogut a una nova URL. En lloc de carregar la pàgina actual, el navegador l'abandona i navega automàticament a la nova adreça.

El procés de redireccionament es basa en els codis d'estat HTTP. Quan un navegador sol·licita una URL, el servidor respon amb un codi d'estat. Els codis d'estat més comuns per a redireccionaments són:

En rebre un d'aquests codis, el navegador llegeix la capçalera Location: que acompanya la resposta, la qual conté la nova URL de destinació.

Casos d'ús

Els redireccionaments són fonamentals en la gestió de llocs web per diversos motius:

Tipus de redireccionaments

A més de la redirecció HTTP clàssica, hi ha altres mètodes:

Com fer un redirect amb PHP

Per fer un redireccionament, simplement has de cridar la funció header() amb la capçalera Location.

Cal uitilitzar aquesta funció  abans de qualsevol sortida de text, HTML o espai en blanc, ja que les capçaleres HTTP han de ser les primeres dades enviades.

<?php
header('Location: https://www.google.cat');
exit; // És important afegir 'exit' o 'die' per aturar l'execució del script

Cal afegir exit o die, ja que si no ho afegim, el script continuarà executant-se al servidor i podria enviar més contingut HTML, cosa que podria causar més errors o problemes de seguretat. Aquestes funcions asseguren que el script s'atura immediatament despres de la redirecció.

Avantatges i inconvenients

Avantatges

Inconvenients

Paràmetres en HTTP

Securització inputs

Sens dubte. Les Funcions de Filtre de PHP representen un conjunt d'eines essencial per a qualsevol desenvolupador, ja que són la manera més segura i recomanada de gestionar les dades d'entrada d'usuari i validar variables. El seu objectiu principal és separar les dades brutes de la lògica de l'aplicació, garantint que només es processin dades netes i amb el format esperat.

Funcions de Filtre (Visió Detallada)

Les funcions es divideixen en dos grups: les que treballen amb variables externes (com $_GET o $_POST) i les que treballen amb variables locals.

Funció Descripció Detallada Ús Típic
filter_input() Obté una variable d'entrada externa específica (de les superglobals $_GET, $_POST, etc.) i l'aplica un filtre de validació o sanejament en una sola operació. La forma més segura d'obtenir dades de formularis (p. ex., obtenir i validar una adreça de correu electrònic d'un camp POST).
filter_input_array() Obté múltiples variables d'entrada externes i permet aplicar diferents filtres a cadascuna mitjançant un array de definició. Processar la totalitat d'un formulari amb diversos camps i requisits de filtre diferents.
filter_var() Aplica un filtre de validació o sanejament a qualsevol variable local de l'script (no d'entrada externa). Validar dades obtingudes d'una base de dades, arxiu de configuració, o variables definides dins de la lògica.
filter_var_array() Filtra múltiples variables locals utilitzant un array de definició. Validar un array de dades de configuració abans d'utilitzar-les.
filter_has_var() Comprova si una variable d'entrada d'un tipus concret existeix ($_POST['email']). Determinar si s'ha enviat un formulari o si un camp concret està present.
filter_list() Retorna un array amb tots els noms de filtre disponibles. Diagnòstic i depuració (per veure quins filtres suporta la teva instal·lació de PHP).
filter_id() Retorna l'ID sencer d'un nom de filtre donat. Ús intern o per generar mapes de filtres.

Tipus de filtres (Validació vs. Sanejament)

Els filtres es divideixen en dos grans grups, que actuen de manera fonamentalment diferent:

Filtres de validació (FILTER_VALIDATE_...)

Aquests filtres només comproven si la dada compleix un format o regla específica.

Filtres de sanejament (FILTER_SANITIZE_...)

Aquests filtres netegen la dada, eliminant caràcters no desitjats o codificant-los per fer-los segurs.

Exemples pràctics (Validació i Sanejament)

Exemple 1: Obtenir i validar una adreça de mail (POST)

Aquest és l'ús més segur per obtenir dades d'entrada d'un formulari:

PHP

<?php
// Suposem que $_POST['email'] conté l'entrada de l'usuari

// Utilitzem filter_input()
$email_brut = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL); 
// Saneja: neteja el string, eliminant caràcters que no hauria de tenir un email.

// Validem el format (és vital fer-ho DESPRÉS del sanejament)
if ($email_brut !== false) {
    $email_validat = filter_var($email_brut, FILTER_VALIDATE_EMAIL); 
    
    if ($email_validat) {
        echo "Adreça de correu electrònic vàlida i segura: " . $email_validat;
    } else {
        echo "Error: El format de l'adreça no és correcte.";
    }
} else {
    echo "Error: El camp de correu electrònic és necessari.";
}

Exemple 2: Validar un nombre enter amb rang i flags

Validem que una variable local (o d'entrada) sigui un enter i que estigui dins d'un rang concret.

PHP

<?php
$edat_entrada = "35";

$opcions = [
    'options' => [
        'min_range' => 18,
        'max_range' => 99
    ]
];

// Validació de l'enter amb un filtre de rang
$edat_validada = filter_var(
    $edat_entrada, 
    FILTER_VALIDATE_INT, 
    $opcions
);

if ($edat_validada === false) {
    echo "L'edat ha de ser un enter entre 18 i 99.";
} else {
    echo "Edat processada: " . $edat_validada;
}

Exemple 3: Filtrar múltiples entrades (filter_input_array)

Utilització de filter_input_array() per processar un formulari sencer amb diferents regles.

PHP

<?php
// Definim les regles de filtratge
$definicions = [
    'nom' => [
        'filter' => FILTER_SANITIZE_STRING, // Neteja la cadena (elimina tags)
        'flags'  => FILTER_FLAG_NO_ENCODE_QUOTES // No codifica cometes
    ],
    'quantitat' => [
        'filter' => FILTER_VALIDATE_FLOAT, // Valida com a número flotant
        'options' => ['default' => 0.0] // Si falla, estableix 0.0
    ],
    'web' => FILTER_VALIDATE_URL // Validació simple d'URL
];

// Suposant que tenim dades a $_POST, les filtrem totes
$resultats_filtrats = filter_input_array(INPUT_POST, $definicions);

if ($resultats_filtrats['web'] === false) {
    echo "La URL no és vàlida.";
} else {
    echo "Nom netejat: " . $resultats_filtrats['nom'];
}

Referències PHP.net

Per a una referència exhaustiva de tots els filtres, opcions i constants, consulta la secció oficial de la documentació:

Utilitzar aquestes funcions és l'estàndard modern en PHP per garantir la seguretat contra vulnerabilitats comunes com Injecció SQL (juntament amb prepared statements) i Cross-Site Scripting (XSS).

Mai s'ha de confiar en les dades d'entrada sense una validació i un sanejament adequats.

Sessions

Sessions

Les cookies

Les cookies en PHP són una eina fonamental per gestionar l'estat en el protocol HTTP (que és sense estat). Una cookie és un petit fragment de dades (un parell clau-valor) que un servidor envia al navegador web de l'usuari. El navegador l'emmagatzema i la retorna al servidor amb cada petició posterior, permetent que el servidor "recordi" l'usuari o les seves preferències.

Funcionament de les Cookies en PHP

El procés de creació i ús d'una cookie amb PHP es basa en la comunicació mitjançant capçaleres HTTP:

  1. Creació (Servidor a Client): Quan un script PHP vol crear o modificar una cookie, utilitza la funció setcookie(). Aquesta funció no escriu immediatament la cookie al navegador, sinó que afegeix una capçalera HTTP anomenada Set-Cookie a la resposta del servidor.

    • Restricció Crítica: La capçalera Set-Cookie (i per tant la funció setcookie()) ha de ser enviada abans que qualsevol sortida (output) de l'script (HTML, espais en blanc, etc.). Si PHP ja ha començat a enviar el cos de la pàgina, no pot enviar capçaleres addicionals, i la funció fallarà, provocant un error de tipus "Headers already sent".

  2. Emmagatzematge (Client): El navegador web de l'usuari rep la capçalera Set-Cookie i desa el parell clau-valor de manera local.

  3. Transmissió (Client a Servidor): En cada petició posterior que l'usuari faci al domini corresponent, el navegador inclou automàticament la cookie en la capçalera HTTP de la petició, anomenada simplement Cookie.

  4. Lectura (Servidor amb PHP): PHP llegeix la capçalera Cookie rebuda i omple automàticament la variable superglobal $_COOKIE. El script pot accedir a les dades de la cookie com si fos un array associatiu ($_COOKIE['nom_cookie']).


Exemple d'Ús amb PHP

Per manipular les cookies utilitzem principalment dues eines en PHP: la funció setcookie() per crear-les i la variable $_COOKIE per llegir-les.

- Establir una Cookie

La sintaxi bàsica de setcookie() és:

PHP

// Ha d'estar abans de <html> o echo!

// Cookie de sessió (expira al tancar el navegador)
setcookie("usuari", "JordiCatalà"); 

// Cookie persistent (expira en 30 dies)
$expiracio = time() + (86400 * 30); // 86400 segons = 1 dia
setcookie("preferencia_idioma", "ca", $expiracio, "/"); 
// Els paràmetres addicionals (path, secure, httponly) són opcionals i clau per la seguretat.

- Llegir i Eliminar una Cookie

PHP

<?php
// Llegir una cookie
if (isset($_COOKIE['preferencia_idioma'])) {
    $idioma_seleccionat = $_COOKIE['preferencia_idioma'];
    echo "L'usuari prefereix l'idioma: " . $idioma_seleccionat;
} else {
    echo "No s'ha trobat cap preferència d'idioma.";
}

// Eliminar una cookie
// Per eliminar-la, es crida setcookie() amb una data d'expiració en el passat.
setcookie("usuari", "", time() - 3600); // El valor i la data d'expiració es mouen cap enrere

Avantatges de les Cookies

Avantatge Descripció Detallada
Persistència d'Estat Permeten mantenir la informació d'una petició a l'altra, simulant una "memòria" en HTTP.
Empremta Lleugera Són petits fitxers de text que no requereixen recursos del servidor per emmagatzemar la dada.
Identificació d'Usuari Són essencials per a funcions de "Recorda'm" (autologin) i per a la implementació de sessions (la cookie de sessió només conté l'identificador de la sessió).
Personalització Permeten desar preferències d'usuari (idioma, tema, tipus de lletra) sense haver de passar per una base de dades.

Inconvenients de les Cookies

Inconvenient Descripció Detallada
Límit de Mida La majoria de navegadors limiten la mida a 4 KB per cookie i a unes 20-50 cookies per domini. No són aptes per emmagatzemar grans quantitats de dades.
Riscos de Seguretat Si s'emmagatzema informació sensible (com una contrasenya) sense xifrar, pot ser compromesa fàcilment, ja que es transmeten en cada petició. Això es mitiga usant els atributs Secure i HttpOnly.
Control del Client Les cookies s'emmagatzemen al costat del client, cosa que significa que l'usuari pot esborrar-les, modificar-les o directament deshabilitar-les al seu navegador.
Regulació (GDPR/LSSI) A causa de la seva funció de rastreig, les cookies (especialment les de tercers) estan subjectes a estrictes normatives de privacitat i requereixen el consentiment explícit de l'usuari abans de ser establertes.
Retard de Latència Com que es reenvien amb cada petició HTTP (fins i tot per a imatges o fitxers estàtics), poden afegir un petit overhead de latència, especialment si són moltes i grans.

La funció setcookie()

La funció setcookie() de PHP és l'eina primària per crear i gestionar cookies. S'encarrega d'enviar la capçalera HTTP Set-Cookie des del servidor al navegador de l'usuari, que és l'encarregat d'emmagatzemar la dada.

Per protocol, setcookie() ha de ser cridada abans que qualsevol output (sortida) es generi a l'script (com ara HTML, echo, print, o fins i tot espais en blanc abans de l'etiqueta <?php).

- Paràmetres de setcookie()

La funció accepta fins a set paràmetres (o vuit a PHP 7.3+ si s'utilitza l'array d'opcions):

Posició Nom del Paràmetre Requerit Descripció
1 name El nom de la cookie. Aquest nom s'utilitzarà per accedir a la dada a través de $_COOKIE['name'].
2 value No El valor de la cookie. La dada que es vol emmagatzemar (ex: un ID d'usuari). Aquest valor es codifica automàticament a URL.
3 expire No El temps d'expiració de la cookie com a timestamp UNIX. Si s'estableix a 0 (per defecte), la cookie expirarà quan l'usuari tanqui el navegador (és a dir, serà una cookie de sessió).
4 path No El camí del servidor on la cookie estarà disponible. Utilitzar "/" la fa accessible a tot el domini. El valor per defecte és el directori actual on es crida setcookie().
5 domain No El domini pel qual la cookie està disponible (ex: "exemple.cat"). Per fer-la accessible també als subdominis (ex: blog.exemple.cat), s'ha d'anteposar un punt (ex: ".exemple.cat").
6 secure No Booleà. Si es posa a true, la cookie només s'enviarà a través de connexions HTTPS segures. És una bona pràctica de seguretat.
7 httponly No Booleà. Si es posa a true, la cookie serà inaccessible per llenguatges de scripting del costat del client (com JavaScript). Ajuda a mitigar atacs de Cross-Site Scripting (XSS).

Aquesta cookie només existirà mentre el navegador estigui obert.

PHP

<?php
// Usuari ha iniciat sessió. 
// La cookie expira quan es tanca el navegador (expire = 0 per defecte).
setcookie("session_id", "abc12345def67890", 0, "/");

echo "Cookie de sessió establerta.";
// L'usuari veurà la cookie la propera vegada que carregui una pàgina.

PHP
<?php
// Temps d'expiració: ara + (segons en un dia * 7 dies)
$expiracio_7_dies = time() + (86400 * 7); 
$path_total = "/"; 
$domini = "exemple.cat"; // La cookie és vàlida per a exemple.cat

setcookie(
    "tema_preferit", // name
    "foscur",        // value
    $expiracio_7_dies, // expire
    $path_total,     // path
    $domini,         // domain
    true,            // secure (Només HTTPS)
    true             // httponly (No accessible per JS)
);

echo "Cookie persistent establerta per 7 dies.";

Exemple 3: Eliminar una Cookie

Per eliminar una cookie, s'ha de cridar setcookie() amb el mateix nom, el mateix path i el mateix domain, i establir el temps d'expiració a una data passada.

PHP

<?php
// Només cal establir l'expiració en el passat i igualar el path i el domini si es van utilitzar
setcookie("tema_preferit", "", time() - 3600, "/", "exemple.cat");

echo "Cookie 'tema_preferit' eliminada.";

// La cookie desapareixerà del navegador de l'usuari després d'aquesta petició.

- Ús de l'Array d'Opcions (PHP 7.3+)

A partir de PHP 7.3, es pot utilitzar una sintaxi més llegible passant un array d'opcions com a tercer paràmetre, en lloc de passar tots els valors individuals. Això permet incloure opcions avançades com l'atribut SameSite (crític per la seguretat web moderna).

Clau de l'Array Equival a Paràmetre
'expires' expire (timestamp)
'path' path
'domain' domain
'secure' secure (booleà)
'httponly' httponly (booleà)
'samesite' Nou. Pot ser 'Strict', 'Lax' o 'None'.
PHP

<?php
$opcions = [
    'expires'  => time() + 3600, // Expira en 1 hora
    'path'     => '/',
    'domain'   => '.aplicacio.com',
    'secure'   => true, 
    'httponly' => true,
    'samesite' => 'Lax' // Millora la seguretat contra CSRF
];

// setcookie(name, value, array $options)
setcookie('token_remember', 'abcdef123456', $opcions);

echo "Cookie amb opcions de seguretat modernes establerta.";

- El paràmetre samesite (PHP 7.3+)

El paràmetre SameSite és un atribut de seguretat fonamental per a les cookies que va ser introduït per mitigar un tipus de vulnerabilitat web molt comú: els atacs de Falsificació de Peticions en Llocs Creuats (Cross-Site Request Forgery o CSRF).

Aquest paràmetre controla si una cookie ha de ser enviada automàticament pel navegador quan la petició s'origina des d'un lloc web diferent al que va establir la cookie.

Funcionament i Tipus de Valors

L'atribut SameSite es configura en la capçalera Set-Cookie enviada pel servidor i accepta tres valors principals: Lax, Strict i None.

1. SameSite=Lax (Recomanat per Defecte)

Aquest és el mode d'equilibri, i el valor recomanat per la majoria d'aplicacions:

2. SameSite=Strict (Màxima Seguretat)

Aquest mode ofereix la màxima protecció contra atacs CSRF.

3. SameSite=None (Sense Protecció)

Aquest valor inhabilita completament la protecció i permet l'enviament de la cookie en totes les peticions de lloc creuat.


Exemple d'Implementació amb PHP

A partir de PHP 7.3, l'atribut SameSite es configura millor mitjançant l'array d'opcions a la funció setcookie():

PHP

Importància en la Seguretat (CSRF)

Sense l'atribut SameSite, un atacant podria fer que un usuari iniciat en una aplicació (per exemple, un banc) fes clic en un enllaç o carregués una imatge en un lloc web maliciós. Aquest lloc web maliciós podria enviar una petició amagada al banc (per exemple, de transferència de fons).

Com que el navegador de la víctima automàticament adjuntaria la cookie de sessió del banc a aquesta petició (perquè els navegadors antigament feien això per defecte), el banc la processaria com una acció legítima.

L'atribut SameSite impedeix aquest comportament en la majoria de casos, ja que instruccions com Lax o Strict fan que la cookie no s'adjunti a la petició iniciada des del lloc maliciós, neutralitzant l'atac.

Sessions

Introducció

Les sessions de PHP són una manera de guardar informació d'un usuari durant la seva interacció amb un lloc web, a través de múltiples pàgines. Aquesta informació s'emmagatzema al servidor, no al navegador de l'usuari, fent-la més segura. El mecanisme es basa en un identificador únic (ID de sessió) que vincula el navegador de l'usuari amb el fitxer de sessió corresponent al servidor.

Com funciona?

Avantatges i inconvenients

Avantatges

Inconvenients

Les sessions de servidor depenen que el navegador accepti cookies

Sessions

Una sessió PHP

Les sessions de PHP són un mecanisme per emmagatzemar informació de l'usuari a través de múltiples pàgines web. A diferència de les cookies, que s'emmagatzemen al navegador de l'usuari, les dades de la sessió es guarden al servidor. La clau per vincular les dades de la sessió al navegador de l'usuari és un identificador de sessió únic que s'envia entre el client i el servidor.

Com funcionen les sessions

  1. Inici de la sessió: Quan una pàgina web crida la funció session_start(), PHP genera un identificador de sessió (un string de caràcters aleatoris) per a l'usuari si encara no en té cap. Aquest identificador és l'enllaç entre el navegador i el fitxer de sessió al servidor.
  2. Enviament de l'identificador: L'identificador de sessió s'envia al navegador de l'usuari, generalment a través d'una cookie anomenada PHPSESSID.
  3. Emmagatzematge de dades: Les dades es guarden en un array global anomenat $_SESSION. Qualsevol dada que es vulgui conservar entre pàgines s'emmagatzema en aquest array associatiu (per exemple, $_SESSION['nom'] = 'Joan').
  4. Recuperació de dades: En cada pàgina posterior, si s'utilitza de nou session_start(), PHP llegeix l'identificador de sessió de la cookie, troba el fitxer de sessió corresponent al servidor i carrega les dades a l'array $_SESSION, fent-les accessibles al script.

Pàgina 1 (sessio1.php)

<?php
// Inicia la sessió
session_start();

// Emmagatzema dades a la sessió
$_SESSION['nom'] = 'Anna';
$_SESSION['id_usuari'] = 123;

echo "Dades de la sessió guardades. <a href='sessio2.php'>Anar a la pàgina 2</a>";

Pàgina 2 (sessio2.php)

<?php
// Cal iniciar la sessió per accedir a les dades
session_start();

// Recupera les dades de la sessió
if (isset($_SESSION['nom'])) {
    echo "Hola, " . $_SESSION['nom'] . "!<br>";
    echo "El teu ID d'usuari és: " . $_SESSION['id_usuari'];
} else {
    echo "No hi ha dades de sessió disponibles.";
}

El principal avantatge d'utilitzar variables de sessió, és que aquestes s'emmagatzemen en el servidor i no en el client, això redueix el risc de manipulació per part de l'usuari, encara que no tenim límit en la mida perque s'emmagatzemen en disc, cal tenir en compte que quan s'executa el script aquestes variables es troben en memòria per cada usuari que es troba en execució.

Vida util de les sessions?

La vida útil de les variables de sessió al servidor comença amb la funció session_start() i acaba quan la sessió es destrueix o caduca.

  1. Creació: La sessió s'inicia amb session_start(). En aquest moment, es crea un fitxer de sessió temporal al servidor per a l'usuari, i un identificador únic de sessió s'associa amb ell.

  2. Activitat: Mentre l'usuari navega pel lloc web, l'identificador de sessió es manté actiu, i les variables guardades a $_SESSION persisteixen en les peticions successives.

  3. Finalització: La sessió pot finalitzar de dues maneres:

    • Caducitat per temps (Time-out): Si l'usuari no realitza cap petició al servidor durant un temps determinat, la sessió expira automàticament. Aquest temps es defineix en el fitxer de configuració de PHP (php.ini) amb la directiva session.gc_maxlifetime. El valor per defecte sol ser de 1440 segons (24 minuts). El recollidor d'escombraries de la sessió (session garbage collector) és l'encarregat d'eliminar periòdicament aquests fitxers de sessió caducats.

    • Destrucció explícita: Un script PHP pot tancar la sessió manualment amb la funció session_destroy(). Aquesta acció esborra el fitxer de sessió del servidor, eliminant totes les dades que hi havia guardades. Això s'utilitza habitualment quan un usuari tanca la sessió (log out).

Factors que afecten la vida útil

Eliminar una variable de sessió

unset(): La forma més comuna és usar la funció unset() per treure una clau específica de l'array $_SESSION.

<?php
session_start();
// Guarda una variable
$_SESSION['nom_usuari'] = 'Joan';

// Elimina només una variable
unset($_SESSION['nom_usuari']);

// La variable 'nom_usuari' ha estat eliminada
print_r($_SESSION);

Eliminar sessió del server

session_unset(): Aquesta funció elimina totes les variables registrades en l'array $_SESSION. És una opció útil per netejar totes les dades de la sessió alhora, però no tanca la sessió en si mateixa.

<?php
session_start();
// Guarda algunes variables
$_SESSION['nom'] = 'Anna';
$_SESSION['carret'] = ['pommes', 'peres'];

// Elimina totes les variables de la sessió
session_unset();

// L'array $_SESSION ara està buit
print_r($_SESSION);

Eliminar sessió sencera

Si es vol tancar la sessió completament, cal fer dos passos:

  1. Eliminar les variables de l'array $_SESSION.

  2. Destruir la sessió al servidor i la cookie al navegador.

Aquest procés és típic d'un tancament de sessió d'usuari (logout).

<?php
session_start();

// Pas 1: Destrueix totes les variables de la sessió
session_unset();

// Pas 2: Destrueix la sessió al servidor
session_destroy();

// Opcional: Elimina la cookie de sessió del navegador
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}

echo "Sessió tancada correctament.";

 

 

Sessions

Multiples sessions, mateix server

La funció session_name() a PHP s'utilitza per obtenir o establir el nom de la cookie de sessió. El nom per defecte és PHPSESSID. Canviar-lo pot tenir avantatges i inconvenients, i és útil en casos d'ús específics.

Avantatges i inconvenients

Avantatges

Inconvenients

Casos d'ús

 

Blog + Shop = únic server

Codi blog

<?php
// fitxer: /blog/index.php

// Defineix un nom de sessió per al blog
session_name('blog_session');

// Inicia la sessió
session_start();

// Emmagatzema una variable de sessió per al blog
$_SESSION['usuari'] = 'Joan_blog';

echo "Sessió del blog iniciada com a: " . $_SESSION['usuari'] . ".<br>";
echo '<a href="/shop/index.php">Visitar la botiga</a>';

Codi botiga online

<?php
// fitxer: /shop/index.php

// Defineix un nom de sessió per a la botiga
session_name('shop_session');

// Inicia la sessió
session_start();

// Emmagatzema una variable de sessió per a la botiga
$_SESSION['carret'] = ['producte1', 'producte2'];

echo "Sessió de la botiga iniciada amb productes al carret.<br>";
echo "Contingut del carret: " . implode(', ', $_SESSION['carret']) . ".<br>";
echo '<a href="/blog/index.php">Tornar al blog</a>';

Si no s'hagués utilitzat session_name(), ambdós scripts crearien una cookie amb el nom per defecte PHPSESSID. Això podria provocar que la informació d'una aplicació (per exemple, l'usuari del blog) es perdés quan s'iniciés la sessió de l'altra, ja que la segona sessió sobreescriuria la primera. Utilitzar session_name() garanteix que cada aplicació mantingui les seves pròpies dades de sessió de manera independent.

Les dates

Les dates

Les dates

El maneig de dates i hores en PHP ha evolucionat molt, passant de les funcions bàsiques a una orientació a objectes molt més robusta i fiable. Entendre aquest sistema és crucial per a qualsevol aplicació, especialment per a la correcta gestió de fusos horaris.

El funcionament intern de les dates en PHP

PHP gestiona el temps i les dates basant-se en el concepte de Timestamp Unix (Marca de temps Unix), tot i que la majoria de les funcions modernes treballen internament amb objectes.

El timestamp Unix

Un timestamp Unix és un valor sencer que representa el nombre de segons transcorreguts des de l'Època Unix (la mitjanit UTC de l'1 de gener de 1970).

El fus Horari (Timezone)

El fus horari és la configuració més crítica. PHP necessita saber en quin fus horari ha d'interpretar i mostrar les dates, ja que un mateix timestamp pot representar una hora diferent segons la ubicació.

 

Configuració (PHP.INI)

Dos paràmetres al fitxer php.ini (o configurats dinàmicament al codi) afecten directament el maneig de dates:

date.timezone

Aquest és el paràmetre obligatori i més important. Estableix el fus horari per defecte que PHP utilitzarà per a totes les operacions de data i hora.

date.default_latitude / date.default_longitude

Aquests paràmetres, juntament amb date.sunrise_color i date.sunset_color, s'utilitzen per a funcions de càlcul d'efemèrides com ara date_sunrise() i date_sunset(). No afecten el format de data ni l'hora.

 

Funcions disponibles (Procedural)

PHP ofereix un conjunt de funcions antigues però encara molt utilitzades, que converteixen entre timestamps i cadenes de text (strings):

Lectura de temps

Formatació de Dates

 

Conversió de cadena a Timestamp

 

https://www.php.net/manual/es/function.strtotime.php

Exemples. Formats Date
 <?php
$diaAvui=date("d");
echo "formato: date(\"d\")->   ".$diaAvui."<br/>";
$diaAvui=date("D");
echo "formato: date(\"D\")->   ".$diaAvui."<br/>";
$diaAvui=date("j");
echo "formato: date(\"j\")->   ".$diaAvui."<br/>";
$diaAvui=date("l");
echo "formato: date(\"l\")->   ".$diaAvui."<br/>";
$diaAvui=date("N");
echo "formato: date(\"N\")->   ".$diaAvui."<br/>";
$diaAvui=date("S");
echo "formato: date(\"S\")->   ".$diaAvui."<br/>";
$diaAvui=date("d").date("S");
echo "formato: date(\"d\").date(\"S\")->   ".$diaAvui."<br/>";
$dia=date("d-m-Y");
echo "formato: ".$dia."<br/>";
$dia=date("d-m-Y",strtotime("15-12-2025"));
echo "formato: ".$dia."<br/>";
$dia=date("N",strtotime("8-11-2025"));
echo "formato: ".$dia."<br/>";
<?php
echo "Avui es: " . date ("j M Y G:i:s") . "<br/>";
echo date ("YmdGis") . "<br/>"; //202509281534
echo "Dia setmana: " . date ("w") . "<br/>";
echo "Dia setmana: " . date ("w", strtotime("09/11/2025") ). "<br/>";

echo "Mes actual: " . date("n") . "<br/>";
$mes=date("n")+1;
echo "Mes actual: " . $mes . "<br/>";

$darrerDiaMes = date("t")."-".date("n")."-".date("Y");
echo "Dia setmana darrer dia mes: " . date("w",strtotime($darrerDiaMes));

 

Exemples. Date avui

 

 <?php
$diaAvui=date("N");
switch ($diaAvui) {
    case 1:
        $diaSemana="Lunes";
        break;
    case 2:
        $diaSemana="Martes";
        break;
    case 3:
        $diaSemana="Miercoles";
        break;
    case 4:
        $diaSemana="Jueves";
        break;
    case 5:
        $diaSemana="Viernes";
        break;
    case 6:
        $diaSemana="Sabado";
        break;
    case 7:
        $diaSemana="Domingo";
        break;
}
$mesAvui=date("n");
switch ($mesAvui) {
    case 1:
        $Mes="Enero";
        break;
    case 2:
        $Mes="Febrero";
        break;
    case 3:
        $Mes="Marzo";
        break;
    case 4:
        $Mes="Abril";
        break;
    case 5:
        $Mes="Mayo";
        break;
    case 6:
        $Mes="Junio";
        break;
    case 7:
        $Mes="Julio";
        break;
    case 8:
        $Mes="Agosto";
        break;
    case 9:
        $Mes="Septiembre";
        break;
    case 10:
        $Mes="Octubre";
        break;
    case 11:
        $Mes="Noviembre";
        break;
    case 12:
        $Mes="Diciembre";
        break;
}

echo $diaSemana.", ".date("j")." de ".$Mes." de ".date("Y");
Exemples. Operacions Date
 <?php
$fecha_actual = date("d-m-Y");
//sumo 1 día
echo 'Ahora:            '. date('d-m-Y') ."<br/>";            
echo 'Sumo 31 dia:       '.date("d-m-Y",strtotime($fecha_actual."+ 31 days"))."<br/><br/>"; 
//resto 1 día
echo 'Ahora:            '. date('d-m-Y') ."<br/>";            
echo 'Resto 31 dia:       '.date("d-m-Y",strtotime($fecha_actual."- 31 days"))."<br/><br/>"; 

//sumo 1 mes
echo 'Ahora:            '. date('d-m-Y') ."<br/>";            
echo 'Sumo 1 mes:       '.date("d-m-Y",strtotime($fecha_actual."+ 1 month"))."<br/><br/>"; 
//resto 1 mes
echo 'Ahora:            '. date('d-m-Y') ."<br/>";            
echo 'Resto 1 mes:       '.date("d-m-Y",strtotime($fecha_actual."- 1 month"))."<br/><br/>"; 

//sumo 1 año
echo 'Ahora:            '. date('d-m-Y') ."<br/>";            
echo 'Sumo 1 año:       '.date("d-m-Y",strtotime($fecha_actual."+ 1 year"))."<br/><br/>"; 
//resto 1 año
echo 'Ahora:            '. date('d-m-Y') ."<br/>";            
echo 'Resto 1 año:       '.date("d-m-Y",strtotime($fecha_actual."- 1 year"))."<br/><br/>"; 

//sumo 1 semana
echo 'Ahora:            '. date('d-m-Y') ."<br/>";
echo 'Semana Siguiente: '. date("d-m-Y",strtotime($fecha_actual."+ 1 week"))."<br/><br/>"; 
//resto 1 semana
echo 'Ahora:            '. date('d-m-Y') ."<br/>";
echo 'Semana Anterior: '. date("d-m-Y",strtotime($fecha_actual."- 1 week"))."<br/><br/>"; 

$semanaSiguiente = time() + (7 * 24 * 60 * 60); // 7 días; 24 horas; 60 minutos; 60 segundos
echo 'Ahora:            '. date('d-m-Y') ."<br/>";
echo 'Semana Siguiente: '. date('d-m-Y', $semanaSiguiente) ."<br/><br/>";

$semanaSiguiente = time() - (7 * 24 * 60 * 60); // 7 días; 24 horas; 60 minutos; 60 segundos
echo 'Ahora:            '. date('d-m-Y') ."<br/>";
echo 'Semana Anterior: '. date('d-m-Y', $semanaSiguiente) ."<br/><br/>";

strtotime( STRING ). 
Retorna un object timestamp a partir d'una data expresada en la cadena de caracters
  - Si el separador es / llavors la data esta expressada MES/DIA/ANY
  - Si el separador es - llavors la data està expressada DIA/MES/ANY

La funció strtotime() de PHP té un comportament diferent i potencialment confús quan s'utilitza la barra inclinada (/) com a separador entre els components numèrics de la data (mes, dia, any), en comparació amb el guió (-).

Aquesta diferència es basa en la manera com PHP, i en última instància, la biblioteca C subjacent, intenta inferir quin format de data s'està utilitzant.

El Comportament de strtotime() segons el Separador

La clau de la interpretació de strtotime() rau en la distinció entre el format americà (M/D/Y) i el format europeu (D/M/Y).

El Guió (-): Format ISO 8601 (Any-Mes-Dia)

Quan utilitzes el guió, strtotime() assumeix el format més estricte i universal: Any-Mes-Dia (YMD).

Entrada (Gió) Format Interpretar Explicació
"2025-03-01" YMD S'interpreta com l'1 de març de 2025.
"03-01-2025" YMD S'interpreta com el 3 de gener de 2025.

Conclusió amb -: El guió indueix el format internacional (ISO 8601), que prioritza l'any al principi (o l'any al final si es presenta només amb 3 components, assumint MDY).

La Barra Inclinada (/): Format Americà (Mes/Dia/Any) US

Quan utilitzes la barra inclinada (/), strtotime() prioritza el format de data curt utilitzat comunament als Estats Units: Mes/Dia/Any (M/D/Y).

Entrada (Barra) Format Interpretar Explicació
"03/01/2025" M/D/Y S'interpreta com l'1 de març de 2025.
"01/03/2025" M/D/Y S'interpreta com el 3 de gener de 2025.
"31/01/2025" Error Si el primer número supera 12 (més d'un mes), l'anàlisi falla, ja que s'espera un mes.

Conclusió amb /: La barra inclinada obliga a utilitzar la lògica Mes/Dia/Any (M/D/Y), independentment de les preferències regionals del servidor.

L'Ambivalència i el Risc d'Errors

El problema sorgeix quan un desenvolupador en una regió on s'utilitza el format Dia/Mes/Any (D/M/Y) assumeix que la barra inclinada mantindrà aquest ordre.

Desenvolupador Espera PHP Llegeix (M/D/Y) Resultat (Error)
Europeu 12 de maig de 2025 (12/05/2025) 5 de desembre de 2025 Data Incorrecta
Europeu 5 de desembre de 2025 (05/12/2025) 12 de maig de 2025 Data Incorrecta

Això es coneix com a "ambigüitat de format de data" i pot provocar errors subtils i difícils de detectar en la lògica de l'aplicació.

La solució recomanada: DateTime amb Format Explícit

Per evitar qualsevol ambigüitat, la pràctica recomanada és evitar totalment l'ús de strtotime() per analitzar dates d'entrada de l'usuari amb format D/M/Y o M/D/Y. En el seu lloc, s'ha d'utilitzar el mètode DateTime::createFromFormat(), ja que obliga a PHP a utilitzar el format de data que tu especifiques amb exactitud.

PHP
<?php
// Entrada de l'usuari (format català/europeu esperat: DD/MM/YYYY)
$data_entrada = "01/03/2025"; 

// 1. Ús ambigü (i erroni en context europeu):
// $timestamp_error = strtotime($data_entrada); 
// S'interpreta com Març 1 (M/D) en lloc de l'1 de Març (D/M).

// 2. Ús Correcte (Orientat a Objectes):
// Indica explícitament a PHP que la cadena és Dia/Mes/Any
$data_objecte = DateTime::createFromFormat('d/m/Y', $data_entrada);

if ($data_objecte) {
    // La data és l'1 de març de 2025
    echo "Data analitzada correctament: " . $data_objecte->format('Y-m-d'); 
} else {
    echo "Error: El format de data no és vàlid.";
}

Amb createFromFormat(), elimines qualsevol conjectura de PHP sobre si estàs utilitzant un guió, una barra inclinada o un punt, ja que tu defineixes la màscara d'anàlisi exacta.

Objectes per dates (Enfocament OO)

L'enfocament Orientat a Objectes (OOP) és l'estàndard modern en PHP, ja que resol problemes complexos de càlculs de dates i gestió de fusos horaris amb molta més fiabilitat.

DateTime (o DateTimeImmutable)

Representa una data i hora concretes, sempre associada a un fus horari:

Mètode Clau Descripció Exemple
Constructor Crea un nou objecte data. new DateTime() (ara) o new DateTime('2025-10-20').
format(string $format) Formata l'objecte data en una cadena (similar a la funció date()). $data->format('Y-m-d')
setTimezone(DateTimeZone $timezone) Canvia el fus horari de l'objecte sense alterar el punt en el temps. $data->setTimezone(new DateTimeZone('America/New_York'))
createFromFormat() Analitza una data d'una cadena amb un format conegut de forma segura. DateTime::createFromFormat('d/m/Y', '26/09/2025')

 

DateTimeZone

Un objecte que encapsula un fus horari concret.

DateInterval

Representa un període de temps (e.g., 2 anys, 3 mesos i 5 dies).

DatePeriod

Representa una col·lecció de dates i hores dins d'un període, iterant segons un DateInterval.

DateTime per càlculs (Immutabilitat)

La major fortalesa de l'OOP és el maneig de càlculs amb els mètodes add() i sub() (i diff() per calcular la diferència entre dues dates).

Per evitar modificar l'objecte original (un risc en programació), és molt recomanable utilitzar DateTimeImmutable, que sempre retorna una nova instància amb el canvi aplicat:

PHP
<?php
$ara = new DateTimeImmutable('now'); // Data original inalterable

// Sumem un període de temps (un mes i 5 dies)
$interval = new DateInterval('P1M5D');
$futur = $ara->add($interval); // Crea un nou objecte

echo "Ara: " . $ara->format('Y-m-d') . "\n";
echo "Futur: " . $futur->format('Y-m-d') . "\n";

 

 

 

 

 

 

 

Les dates

Exemple Calendari. Procedural

<html>
   <head>
      <title>Calendari <?php echo date("M") . "-" . date("Y"); ?></title>
   </head>
   <body>
      <h3> Calendari <?php echo date("M") . "-" . date("Y"); ?></h3>
      <table border="1" cellspacing="0" cellpadding="0">

         <tr>
            <td>Dl</td><td>Dm</td><td>Dc</td><td>Dj</td><td>Dv</td><td>Ds</td><td>Dg</td>
         </tr>
         <?php
            $dia=1;
            $nDiesMes= date("t");
            $iWDIni= date("w",strtotime( "1-".date("n")."-".date("Y") ));       //Dia setmana primer dia
            $iWDFi= date("w",strtotime($nDiesMes."-".date("n")."-".date("Y"))); //Dia setmana darrer dia mes

            echo "<tr>";
            for ($i=1 ; $i<$iWDIni ; $i++)   {
               echo "<td>&nbsp;--</td>";
            }
   
            //pintar dies del mes
            while ($dia <= $nDiesMes)
            {
               //si es dilluns llavors echo "<tr>"
               
               echo "<td>$dia</td>";
               
               //si es diumenge llavors echo "</tr>"
               $dia++;
            }
            

         ?>
      </table>
   </body>
</html>

Les dates

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

<?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

  1. Fiabilitat amb DateTimeImmutable: En lloc d'utilitzar múltiples crides a date() i la funció ambigua strtotime(), ara tens un objecte $dataMesActual que representa el mes, i un objecte $dataIteracio que es modifica utilitzant el mètode ->modify() o ->add() juntament amb DateInterval.

  2. 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.

  3. Iteració Sencilla: El bucle while avanç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.

  4. Consistència: Es calcula la $dataFiGraella per 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.

Les dates

Exemple Calendari. OOP + classe calendari

Un calendari, aplicant l'Orientació a Objectes (OOP) a PHP, utilitzant la classe DateTimeImmutable per a una manipulació de dates més fiable i encapsulant la lògica de generació del calendari en una classe Calendari. Aquesta solució separa la lògica (Calendari.php) de la presentació (index.php) i utilitza iteradors per generar les cel·les sense lògica complexa d'indexació.

Implementació Orientada a Objectes (Calendari.php)

Crearem la classe Calendari que s'encarregarà de tots els càlculs de dates i de generar el HTML del calendari.

PHP

<?php

class Calendari
{
    /** @var DateTimeImmutable Data del mes que es vol mostrar */
    private DateTimeImmutable $dataMes;

    /** @var DateTimeImmutable Data del primer dia a iterar (el primer dilluns visible) */
    private DateTimeImmutable $dataIniciIteracio;

    /** @var DateTimeImmutable Data de l'últim dia a iterar (l'últim diumenge visible) */
    private DateTimeImmutable $dataFiIteracio;

    /**
     * Constructor
     * @param DateTimeImmutable|null $dataMes Si és null, s'utilitza la data actual.
     */
    public function __construct(?DateTimeImmutable $dataMes = null)
    {
        // Posicionem la data al primer dia del mes seleccionat (o el mes actual)
        $any = $dataMes?->format('Y') ?? date('Y');
        $mes = $dataMes?->format('m') ?? date('m');

        // Utilitzem createFromFormat per garantir el primer dia
        $this->dataMes = DateTimeImmutable::createFromFormat('Y-m-d', "$any-$mes-01");

        $this->calcularDatesIteracio();
    }

    /**
     * Calcula la data d'inici (primer dilluns) i fi (últim diumenge)
     * de la graella, ajustant-se exactament al mes.
     */
    private function calcularDatesIteracio(): void
    {
        $primerDiaMes = $this->dataMes;
        $darrerDiaMes = $this->dataMes->modify('last day of this month');

        // 1. Càlcul de la data d'inici de la iteració (el primer dilluns visible)
        $diaSetmanaPrimerDia = (int)$primerDiaMes->format('N'); // 1 (Dl) a 7 (Dg)
        $diesARestar = $diaSetmanaPrimerDia - 1; 
        $this->dataIniciIteracio = $primerDiaMes->modify("-$diesARestar days");

        
        // 2. Càlcul de la data de finalització de la iteració (l'últim diumenge visible)
        
        // Busquem el dia de la setmana del darrer dia del mes
        $diaSetmanaDarrerDia = (int)$darrerDiaMes->format('N'); // 1 (Dl) a 7 (Dg)
        
        // Necessitem avançar fins al diumenge (dia 7)
        // Si el mes acaba un diumenge (7), sumem 0 dies.
        // Si el mes acaba un dissabte (6), sumem 1 dia.
        $diesASumar = 7 - $diaSetmanaDarrerDia;
        
        // L'últim dia real de la graella és el diumenge de l'última setmana
        $this->dataFiIteracio = $darrerDiaMes->modify("+$diesASumar days");
    }

    /**
     * Retorna el títol del calendari (Mes i Any)
     */
    public function getTitol(): string
    {
        // Exemple de formatació: Setembre - 2025
        return $this->dataMes->format('F') . ' - ' . $this->dataMes->format('Y');
    }

    /**
     * Mètode principal per generar el HTML del calendari
     */
    public function generaTaulaHTML(): string
    {
        $html = '<table class="calendari-taula" border="1" cellspacing="0" cellpadding="0">';
        
        // Capçalera de dies de la setmana
        $html .= '<tr>';
        $diesSetmana = ['Dl', 'Dm', 'Dc', 'Dj', 'Dv', 'Ds', 'Dg'];
        foreach ($diesSetmana as $dia) {
            $html .= "<th>$dia</th>";
        }
        $html .= '</tr>';

        // Cos del calendari
        $dataActual = $this->dataIniciIteracio;
        $avui = new DateTimeImmutable('today');
        $intervalDia = new DateInterval('P1D');

        while ($dataActual < $this->dataFiIteracio) {
            
            // Nova fila (<tr>) cada dilluns (N=1)
            if ($dataActual->format('N') == 1) {
                $html .= '<tr>';
            }

            // Determinació d'estils
            $esDelMesActual = $dataActual->format('m') === $this->dataMes->format('m');
            $esAvui = $dataActual->format('Y-m-d') === $avui->format('Y-m-d');
            
            $classe = $esAvui ? 'avui' : ($esDelMesActual ? 'mes-actual' : 'altre-mes');

            $html .= "<td class='$classe'>";
            $html .= $dataActual->format('j'); 
            $html .= '</td>';

            // Tancament de fila (</tr>) cada diumenge (N=7)
            if ($dataActual->format('N') == 7) {
                $html .= '</tr>';
            }

            // Avançar al dia següent amb l'interval
            $dataActual = $dataActual->add($intervalDia);
        }

        $html .= '</table>';
        return $html;
    }
}

Ús de la Classe (index.php)

El fitxer principal es simplifica molt, ja que tota la lògica es troba a la classe Calendari.

PHP

<?php
// index.php

require_once 'Calendari.php';

// Opcional: Establir el fus horari per consistència
date_default_timezone_set('Europe/Madrid');

// Per a provar un mes amb menys setmanes (Octubre 2025 comença Dimecres)
// $calendari = new Calendari(new DateTimeImmutable('2025-10-01')); 

// Crear l'objecte Calendari per al mes actual (Setembre 2025)
$calendari = new Calendari(); 

$titol = $calendari->getTitol();
$taula_html = $calendari->generaTaulaHTML();
?>

<!DOCTYPE html>
<html lang="ca">
<head>
    <meta charset="UTF-8">
    <title>Calendari Ajustat: <?php echo $titol; ?></title>
    <style>
        .calendari-taula {
            width: 100%;
            max-width: 500px;
            border-collapse: collapse;
            text-align: center;
        }
        .calendari-taula th, .calendari-taula td {
            padding: 8px;
            border: 1px solid #ccc;
        }
        .calendari-taula .avui {
            background-color: #ffe0b2;
            font-weight: bold;
        }
        .calendari-taula .altre-mes {
            color: #aaa;
            background-color: #f7f7f7;
        }
    </style>
</head>
<body>
    <h3> Calendari Ajustat: <?php echo $titol; ?></h3>
    
    <?php echo $taula_html; ?>

</body>
</html>

Avantatges de l'Orientació a Objectes

  1. Fiabilitat de Dates: L'ús de DateTimeImmutable (en lloc de constants com date("n") o date("Y") i funcions com strtotime()) elimina l'ambigüitat en els càlculs i evita errors per manipulació del mateix objecte (immutabilitat).

  2. Encapsulament: Tota la lògica de càlculs (com saber el primer dilluns, els dies a restar, etc.) està encapsulada dins la classe Calendari, fent que el codi sigui molt més net i fàcil de mantenir.

  3. Flexibilitat: El constructor ara pot acceptar qualsevol data, permetent generar calendaris per a qualsevol mes sense haver de modificar la lògica interna del codi.

  4. Separació de Responsabilitats: El fitxer index.php només s'encarrega de crear l'objecte i mostrar el seu resultat (generaTaulaHTML()), separant la Lògica (la classe) de la Presentació (el HTML).