1. PHP bàsic
- Introducció
- Introducció
- Versions
- Sintaxi bàsica
- Els comentaris
- PHP Info
- Mostrar informació
- Variables
- Spread operator (Arrays)
- Estructures bàsiques
- Paràmetres en HTTP
- Sessions
- Les dates
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:
-
Una línia: // o #
-
Multilínia: /* ... */
Mostrar informació
-
echo → imprimir text o variables
-
print → imprimir i retornar 1
-
print_r() i var_dump() → útils per arrays i objectes
-
die() → mostra un missatge i atura l’script
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ó
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:
-
Millor suport per a la programació orientada a objectes, que en versions anteriors era extremadament rudimentari.
-
Millores de rendiment.
-
Millor suport per a MySQL amb extensió completament reescrita.
-
Millor suport a XML (XPath, DOM, etc.).
-
Suport natiu per a SQLite.
-
Suport integrat per a SOAP.
-
Iteradors de dades.
-
Gestió d’excepcions.
-
Millores amb la implementació amb Oracle.
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.
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_globals, safe_mode, allow_call_time_pass_reference, session_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
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.
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
*/
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:
-
La versió de PHP que s’està executant.
-
Les extensions carregades i les seves configuracions (com MySQLi, GD, cURL, etc.).
-
Els valors de les directives del php.ini (com
upload_max_filesize,memory_limit,display_errors, etc.). -
Informació del servidor web (per exemple, Apache o Nginx).
-
El sistema operatiu sobre el qual corre PHP.
-
Variables d’entorn i de servidor.
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).
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>
É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));
Variables
Les variables en PHP ens serveixen per emmagatzemar dades i que poden canviar durant l'execució del programa.
Característiques
- Sempre comencen amb el símbol del dòlar
$, seguit d'un nom que pot contenir lletres, números i guions baixos. - PHP és un llenguatge case-sensitive
- Variables no tipades. PHP assigna dinàmicament l'espai en funció del valor
// 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 de valor en qualsevol moment
// Les variables poden canviar en valor
// i fins i tot de tipus
$var = "Joan";
$var = 23;
- Si utilitzem cometes dobles en els string, podem inserir variables directament (interpolació)
$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
- Nomenclatura:
- Noms descriptius, en minuscules amb guions baixos per separar paraules
$nom_variable(snake case) - Noms descriptius,
$nomVariable, separant les paraules amb la primera lletra majuscula (camel case) - Noms descriptius,
$sNomVariable, la primera lletra indica el tipus de la variable i segueix el nom de la variable en camel case (Hungarian Case)
- Noms descriptius, en minuscules amb guions baixos per separar paraules
- Inicialitzar les variables abans d'utilitzar-les
- Evitar variables globals si no són necessàries, utilitzar funcions i arrays per encapsular dades
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>";
-
Snake case: llegible, molt utilitzat en PHP clàssic.
-
Camel case: modern, habitual en frameworks i codi orientat a objectes.
-
Hungarian case: mostra el tipus de dada, útil per depuració, menys usat avui dia.
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)
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:
-
En crides de funcions/mètodes (Argument Unpacking, introduït a PHP 5.6).
-
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
// 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
$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
// Ú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:
-
Condicionals: Permeten prendre decisions dins del codi segons si es compleix o no una condició.
-
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.
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;
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.
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:
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.
-
GET: S'utilitza per obtenir dades d'un recurs del servidor. És el mètode més comú per a la navegació i les cerques. Les dades s'envien a la URL i no modifiquen l'estat del servidor (operació idempotent).
-
POST: S'utilitza per enviar dades al servidor per crear o actualitzar un recurs. Les dades s'incorporen al cos de la sol·licitud, no a la URL, el que el fa més segur per a dades sensibles. No és idempotent.
-
PUT: S'utilitza per actualitzar un recurs existent o per crear-ne un de nou si no existeix, a una URL específica. És idempotent.
-
DELETE: S'utilitza per eliminar un recurs específic del servidor. També és idempotent.
-
HEAD: Similar a
GET, però només sol·licita les capçaleres de la resposta, no el cos. És útil per obtenir informació d'un recurs sense descarregar-lo completament, per exemple, per comprovar si un arxiu ha estat modificat. -
PATCH: S'utilitza per aplicar modificacions parcials a un recurs. A diferència de
PUT, que substitueix el recurs sencer,PATCHnomés modifica les parts especificades.
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 | Sí | 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 | Sí | Baixa | ✅ Sí |
| PATCH | Modificar parcialment un recurs | No | Alta | ❌ No |
| OPTIONS | Retorna els mètodes per un recurs | Sí | 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.
-
100 Continue: El servidor ha rebut les capçaleres de la sol·licitud i el client ha de continuar enviant el cos de la sol·licitud.
Categoria 2xx: Èxit
Indiquen que la sol·licitud s'ha processat correctament.
-
200 OK: La sol·licitud s'ha realitzat amb èxit. Aquest és el codi més comú. -
201 Created: La sol·licitud s'ha completat amb èxit i s'ha creat un nou recurs. (Comú ambPOST). -
204 No Content: La sol·licitud s'ha processat correctament, però no hi ha contingut per retornar al cos de la resposta. (Comú ambPUToDELETE).
Categoria 3xx: Redirecció
Indiquen que es necessita una acció addicional per completar la sol·licitud, generalment redirigint el navegador a una nova URL.
-
301 Moved Permanently: El recurs s'ha mogut permanentment a una nova URL. El client ha de fer la sol·licitud a la nova adreça. -
302 Found: El recurs es troba temporalment a una altra URL. El client ha de fer la sol·licitud allà, però ha de seguir utilitzant l'adreça original en el futur.
Categoria 4xx: Error del Client
Indiquen que hi ha hagut un error a causa d'una sol·licitud incorrecta per part del client.
-
400 Bad Request: El servidor no pot processar la sol·licitud perquè la sintaxi és incorrecta o malformada. -
401 Unauthorized: Es requereix autenticació per accedir al recurs. (L'usuari no ha iniciat sessió o no té permisos). -
403 Forbidden: El servidor ha entès la sol·licitud, però es nega a autoritzar-la. L'usuari no té permís per accedir al recurs, independentment de si s'ha autenticat. -
404 Not Found: El recurs sol·licitat no existeix al servidor. Aquest és un dels errors més familiars. -
405 Method Not Allowed: El mètode HTTP utilitzat (per exemple,POST) no està permès per al recurs sol·licitat.
Categoria 5xx: Error del Servidor
Indiquen que el servidor ha fallat en processar una sol·licitud vàlida.
-
500 Internal Server Error: S'ha produït un error inesperat al servidor que impedeix complir amb la sol·licitud. -
503 Service Unavailable: El servidor no pot gestionar la sol·licitud actualment, normalment a causa d'un manteniment o sobrecàrrega temporal.
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:
-
Són fàcils de compartir, ja que la URL es pot copiar i enganxar.
-
Permeten que les pàgines amb filtres o cerques siguin indexables pels motors de cerca.
-
S'utilitzen per a operacions idempotents, és a dir, sol·licituds que no canvien l'estat del servidor (com una cerca o la visualització d'un producte).
Inconvenients:
-
Limitació de grandària (al voltant de 2048 caràcters).
-
Les dades són públiques i visibles, per la qual cosa no s'han d'utilitzar mai per a informació sensible com contrasenyes o dades de targetes de crèdit.
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>
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:
-
Inicis de sessió: enviar contrasenyes i noms d'usuari.
-
Comentaris o missatges: crear contingut nou a un lloc web.
-
Processament de pagaments: enviar informació bancària.
A PHP, el servidor rep aquestes dades en una variable superglobal diferent: $_POST, que també és un array associatiu.
Avantatges:
-
Les dades són més segures i privades.
-
No hi ha limitació de grandària (o és molt més gran que la de GET), permetent enviar fitxers grans o molt de text.
-
S'utilitza per a operacions que modifiquen l'estat del servidor (crear un usuari, enviar una comanda).
Inconvenients:
-
No es poden compartir fàcilment (no hi ha una URL única per a la sol·licitud).
-
No són indexables pels motors de cerca.
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 (<, >). 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>
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ó:
-
$_SERVER['PHP_SELF']: Aquesta variable és especialment susceptible a atacs XSS. Un atacant podria injectar codi maliciós a la URL, que seria retornat per aquesta variable i executat en el navegador del client. Per exemple, si s'utilitza en un formulari d'acció (<form action="<?php echo $_SERVER['PHP_SELF']; ?>">), un atacant podria afegir codi com ara"><script>alert('XSS');</script>a la URL, tancant l'etiqueta HTML i injectant codi JavaScript. -
$_SERVER['HTTP_HOST']: Aquesta variable pot ser manipulada per un atacant a través dels headers de la petició. Si s'utilitza per construir URLs absolutes, es podria aconseguir que el lloc web generi enllaços cap a un domini controlat per l'atacant, facilitant atacs de phishing o cache poisoning. -
$_SERVER['REQUEST_URI']: Similar aPHP_SELF, pot contenir dades malicioses injectades a la URL pel client. S'ha de tractar amb molta precaució. -
$_SERVER['REMOTE_ADDR']: Encara que útil per obtenir l'IP del client, pot ser falsificada en peticions que passen per servidors proxy. Per obtenir la IP real del client en aquests casos, s'haurien de comprovar altres headers com araX-Forwarded-For, que també poden ser falsificats.
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>
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:
-
301 (Moved Permanently): Indica que la pàgina s'ha mogut permanentment a una nova ubicació. Aquest tipus de redireccionament és ideal per a SEO, ja que els motors de cerca entenen que la "autoritat" de l'URL original ha de transferir-se a la nova. -
302 (Found): Indica que la pàgina s'ha mogut temporalment. El navegador hauria de continuar utilitzant l'URL original en futures sol·licituds. És útil per a manteniment o testatge. -
307 (Temporary Redirect): Similar al 302, però manté el mètode de la petició original (per exemple, una peticióPOSTcontinua sentPOSTa la nova URL). -
308 (Permanent Redirect): Similar al 301, però també manté el mètode de la petició original.
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:
-
Canvis d'URL: Quan una pàgina canvia de nom o de ruta.
-
Consolidació de dominis: Per unificar el trànsit de diferents dominis cap a un de sol (p.ex., de
exemple.catawww.exemple.cat). -
Pàgines esborrades: Per enviar els visitants a una pàgina similar o a la pàgina d'inici quan una pàgina ja no existeix.
-
HTTPS: Per redirigir automàticament tot el trànsit d'HTTP a HTTPS per motius de seguretat.
-
Manteniment: Per redirigir els usuaris a una pàgina de "manteniment" mentre el lloc web està fora de línia temporalment.
Tipus de redireccionaments
A més de la redirecció HTTP clàssica, hi ha altres mètodes:
-
Redireccionament a nivell de servidor (
.htaccess): És el mètode més recomanat per a redireccions permanents. Es configura en un fitxer al servidor (.htaccessen servidors Apache) i és molt eficient. -
Redireccionament amb metaetiqueta (
<meta>): Es realitza afegint una etiqueta<meta http-equiv="refresh" ...>dins l'apartat<head>del HTML. Aquest mètode és menys recomanable per a SEO i pot ser més lent. -
Redireccionament amb JavaScript: Es fa amb
window.location.href = 'nova_url'. Aquest mètode no és visible per als robots de cerca i depèn de si l'usuari té JavaScript activat.
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
-
Eficiència: És un mètode ràpid i eficient, ja que la redirecció es gestiona completament pel navegador. El servidor només envia la instrucció i tanca la connexió.
-
Seguretat: Quan es fa correctament, evita que el codi sensible s'executi innecessàriament després d'una redirecció.
-
SEO: Permet utilitzar diferents tipus de codis d'estat HTTP, com ara
301 (Moved Permanently)o302 (Found), que tenen un impacte important en el SEO. Per defecte,header('Location: ...')envia un codi 302, que és una redirecció temporal. Per a una redirecció permanent, cal afegir explícitament el codi d'estat:header('Location: https://www.google.cat', true, 301);. .
Inconvenients
-
Problema de sortida de dades (Headers already sent): El principal inconvenient és que no es pot enviar la capçalera si ja s'ha generat alguna sortida. Si un script ja ha produït qualsevol text, espai en blanc, o etiqueta HTML, PHP generarà una advertència
Warning: Cannot modify header information - headers already sent by (...)i la redirecció fallarà. -
Dependència del navegador: La redirecció depèn completament de la capacitat del navegador per interpretar la capçalera HTTP
Location. Si per algun motiu el navegador no la processa, l'usuari no serà redirigit. Per això, a vegades es recomana una redirecció mitjançantmeta refreshcom a solució alternativa. -
Pèrdua de dades
$_POST: Per defecte, un redireccionament ambheader('Location: ...')converteix una peticióPOSTen una peticióGET, de manera que les dades enviades per un formulariPOSTes perden.
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.
-
Retorn:
-
La dada original, si la validació és exitosa (
true). -
false, si la dada no compleix el format (p. ex., un string no és una adreça de correu electrònic vàlida).
-
-
Objectiu: Assegurar que la dada és correcta.
Filtres de sanejament (FILTER_SANITIZE_...)
Aquests filtres netegen la dada, eliminant caràcters no desitjats o codificant-los per fer-los segurs.
-
Retorn:
-
La dada modificada i neta.
-
-
Objectiu: Fer que la dada sigui segura, especialment abans de mostrar-la a l'usuari (per prevenir atacs XSS) o abans de guardar-la a la base de dades.
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
// 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
$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
// 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ó:
-
Visió General de les Funcions de Filtre: https://www.php.net/manual/en/book.filter.php
-
Funció
filter_input(): https://www.php.net/manual/en/function.filter-input.php -
Llista Completa de Constants de Filtre: https://www.php.net/manual/en/filter.constants.php
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
Les cookies
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:
-
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 anomenadaSet-Cookiea 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".
-
-
Emmagatzematge (Client): El navegador web de l'usuari rep la capçalera
Set-Cookiei desa el parell clau-valor de manera local. -
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. -
Lectura (Servidor amb PHP): PHP llegeix la capçalera
Cookierebuda 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:
// 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
// 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()
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 |
Sí | 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). |
Exemple 1: Cookie de Sessió Bàsica
<?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.
Exemple 2: Cookie Persistent amb Configuració de Seguretat
<?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
// 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'. |
Exemple 4: Cookie amb SameSite
<?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:
-
Com funciona: La cookie NO s'envia quan la petició es fa des d'un lloc extern (tercer) mitjançant mètodes insegurs com
POST. -
Excepció: La cookie SÍ s'envia si la navegació des del lloc extern es fa a través d'un mètode segur (
GET), com en el cas d'un clic en un enllaç o la càrrega d'una imatge. -
Ús: És ideal per a cookies que mantenen la sessió (com les de PHP, si no s'utilitza
Strict), ja que permet que els usuaris puguin arribar al vostre lloc a través d'enllaços externs sense perdre la sessió immediatament, alhora que ofereix protecció contra CSRF bàsic.
2. SameSite=Strict (Màxima Seguretat)
Aquest mode ofereix la màxima protecció contra atacs CSRF.
-
Com funciona: La cookie MAI s'envia si la petició es fa des d'un context de lloc creuat (cross-site), independentment del mètode HTTP utilitzat.
-
Ús: S'ha d'utilitzar per a cookies que gestionen estats d'alta seguretat o accions molt sensibles (per exemple, les cookies que s'utilitzen per confirmar una operació financera o canvis de contrasenya).
-
Inconvenient: Si un usuari inicia sessió i després fa clic en un enllaç al vostre propi lloc web des d'un correu electrònic o una altra aplicació, la cookie de sessió no s'enviarà, i l'usuari semblarà que no ha iniciat sessió.
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.
-
Com funciona: La cookie S'envia sempre amb les peticions de lloc creuat.
-
Requeriment: Quan s'utilitza
SameSite=None, la cookie HA D'incloure obligatòriament l'atributSecure(és a dir, només es pot enviar a través de HTTPS). -
Ús: Només s'ha d'utilitzar quan la cookie és estrictament necessària per a la funcionalitat d'un tercer (per exemple, widgets incrustats, píxels de seguiment o serveis publicitaris).
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
// 1. Cookie amb SameSite=Strict (Alta seguretat)
setcookie('sessio_estricta', 'token123', [
'expires' => time() + 3600,
'path' => '/',
'httponly' => true,
'samesite' => 'Strict'
]);
// 2. Cookie amb SameSite=Lax (Valor recomanat per defecte)
setcookie('preferencia_usuari', 'mode_clar', [
'expires' => time() + (86400 * 30),
'path' => '/',
'httponly' => true,
'samesite' => 'Lax'
]);
// 3. Cookie amb SameSite=None (S'usa per a tercers, requereix 'Secure' = true)
setcookie('widget_tercers', 'data_widget', [
'expires' => time() + 86400,
'path' => '/',
'secure' => true, // OBLIGATORI amb SameSite=None
'samesite' => 'None'
]);
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).
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.
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?
-
Inici de la sessió: Quan una pàgina invoca la funció
session_start(), PHP verifica si ja existeix un ID de sessió. Si no, en crea un de nou. -
Identificador de sessió: Aquest ID únic s'envia al navegador de l'usuari mitjançant una cookie (anomenada per defecte
PHPSESSID). -
Emmagatzematge de dades: Les dades es guarden en un array global anomenat
$_SESSION. Qualsevol informació que vulguis conservar (com ara el nom d'usuari o el contingut d'un carret de compra) es pot desar en aquest array. -
Recuperació: En cada pàgina posterior, en cridar de nou
session_start(), PHP llegeix l'ID de sessió de la cookie, troba el fitxer de sessió al servidor i carrega les dades a l'array$_SESSION, fent-les accessibles al script.
Avantatges i inconvenients
Avantatges
-
Seguretat: Les dades es mantenen al servidor, per la qual cosa no poden ser manipulades directament per l'usuari.
-
Capacitat: No hi ha límit de mida per a la informació de la sessió, més enllà de l'espai de disc del servidor.
Inconvenients
-
Ús de recursos: Cada sessió activa utilitza recursos del servidor. Un gran nombre de sessions pot afectar el rendiment.
-
Dependència de
session_start(): Cal cridar aquesta funció a l'inici de cada pàgina on es vulguin utilitzar o accedir a les dades de la sessió. Ha de ser la primera línia de codi PHP abans de qualsevol sortida HTML. -
Cookies: Per defecte, depenen de les cookies del navegador per funcionar. Si l'usuari les té desactivades, les sessions no funcionaran correctament.
Les sessions de servidor depenen que el navegador accepti cookies
Una cookie és una petita porció de dades, que un lloc web envia al navegador d'un usuari i que s'emmagatzema al seu dispositiu.
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
- 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. - Enviament de l'identificador: L'identificador de sessió s'envia al navegador de l'usuari, generalment a través d'una cookie anomenada
PHPSESSID. - 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'). - 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.
-
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. -
Activitat: Mentre l'usuari navega pel lloc web, l'identificador de sessió es manté actiu, i les variables guardades a
$_SESSIONpersisteixen en les peticions successives. -
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 directivasession.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
-
session.gc_maxlifetime: Aquesta directiva dephp.inidetermina el temps màxim d'inactivitat d'una sessió abans que es consideri obsoleta. -
session.cookie_lifetime: Aquest paràmetre de configuració afecta la vida de la cookie de sessió al navegador de l'usuari. Si la cookie caduca, el navegador ja no enviarà l'identificador de sessió al servidor, trencant la connexió amb les dades de la sessió. -
Destrucció manual: L'ús de funcions com
session_unset()per alliberar totes les variables de la sessió osession_destroy()per eliminar-la completament finalitza la seva vida útil de manera controlada.
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:
-
Eliminar les variables de l'array
$_SESSION. -
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.";
-
session_unset(): Deixa l'array$_SESSIONbuit. Tot i quesession_destroy()farà el mateix, és una bona pràctica netejar l'array primer. -
session_destroy(): Aquesta és la funció clau. S'encarrega d'eliminar el fitxer de sessió del servidor, fent que les dades de la sessió siguin irrecuperables. -
setcookie(): La líniasetcookie()ens garanteix que la cookie de la sessió s'elimini del navegador de l'usuari. Això impedeix que el navegador enviï un ID de sessió antic en peticions futures
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
-
Seguretat: Canviar el nom per defecte de la cookie de sessió (
PHPSESSID) pot ser una mesura de seguretat bàsica. Fa que sigui més difícil per a un atacant, que no conegui el nom de la cookie, realitzar atacs com ara el segrest de sessions (session hijacking). Això és una pràctica de "seguretat per foscor" (security through obscurity), que tot i no ser una solució definitiva, pot dificultar atacs genèrics. -
Coexistència de sessions: Permet que coexisteixin múltiples aplicacions PHP al mateix domini sense conflictes. Si dues aplicacions tenen el mateix nom de cookie de sessió, les dades d'una podrien sobrescriure les de l'altra, causant errors. Utilitzar
session_name()permet assignar un nom únic per a cada aplicació.
Inconvenients
-
Compatibilitat: Si es canvia el nom de la sessió, cal assegurar-se que totes les pàgines de l'aplicació utilitzen el mateix nom abans de cridar
session_start(). Si no, es crearan múltiples sessions innecessàries, cadascuna amb un nom de cookie diferent. -
Complexitat: Pot afegir una capa de complexitat a l'aplicació, ja que el nom de la sessió ha de ser gestionat i recordat per tot el codi.
Casos d'ús
-
Múltiples aplicacions en un mateix domini: Si tens més d'una aplicació web en el mateix domini (per exemple, un bloc i una botiga en línia), canviar el nom de la sessió evita que les dades de sessió d'un lloc interfereixin amb les de l'altre. Per exemple, el bloc podria utilitzar
session_name('blog_sessid')i la botigasession_name('shop_sessid'). -
Millora de la seguretat: En entorns de producció, on la seguretat és prioritària, canviar el nom per defecte pot ser una petita barrera addicional contra atacs automatitzats. No obstant això, és important recordar que aquesta mesura ha de complementar, i no reemplaçar, altres mesures de seguretat més robustes, com la validació de dades i l'ús de tokens CSRF.
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
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).
-
Avantatge: És universal, independent del fus horari i ideal per a emmagatzemar dates a bases de dades o fer càlculs de temps (sumar o restar segons).
-
Funció Clau: La funció
time()retorna el timestamp Unix actual.
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.
-
Configuració Recomanada: S'ha d'establir a una cadena de fus horari vàlida (e.g.,
Europe/Madrid,America/New_York). -
Problema Comú: Si no es defineix, PHP genera un avís (
Warning) i utilitza un fus horari per defecte insegur, cosa que pot causar errors de càlcul d'una hora. -
Configuració Dinàmica: Es pot sobrescriure al codi amb
date_default_timezone_set('Europe/Madrid').
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
-
time(): Retorna el timestamp Unix actual. -
microtime(true): Retorna el timestamp Unix amb precisió de microsegons (com afloat).
Formatació de Dates
-
date(string $format, int $timestamp = time()): string:-
Converteix un timestamp Unix (o el temps actual per defecte) en una cadena de data/hora formatada.
-
El paràmetre
$formatutilitza caràcters especials (e.g.,Yper a l'any complet,mper al mes numèric,Hper a les hores). -
Exemple:
date('d/m/Y H:i:s')retorna"26/09/2025 11:24:54".
-
-
gmdate(): Igual quedate(), però sempre formatat en el fus horari GMT/UTC.
Conversió de cadena a Timestamp
-
strtotime(string $time, int $now = time()): int:-
La funció
strtotime()de PHP és una de les funcions més potents i flexibles, tot i ser de l'enfocament procedural antic. La seva funció principal és analitzar (o interpretar) una cadena de text en anglès (human-readable) que descriu una data o hora i convertir-la al Timestamp Unix corresponent (el nombre de segons des de l'1 de gener de 1970 00:00:00 UTC).És popular per la seva capacitat d'interpretar formats absoluts (com "2025-12-31") i formats relatius (com "next Monday" o "+2 weeks").
-
Exemples:
strtotime('tomorrow'),strtotime('+1 week'),strtotime('2025-01-01').
-
https://www.php.net/manual/es/function.strtotime.php
-
mktime(): Retorna el timestamp Unix d'una data específica, permetent passar any, mes, dia, hora, minut, i segon com a arguments separats.
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 (Y−M−D).
| Entrada (Gió) | Format Interpretar | Explicació |
"2025-03-01" |
Y−M−D | S'interpreta com l'1 de març de 2025. |
"03-01-2025" |
Y−M−D | 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 M−D−Y).
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
// 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.
-
Ús: Es fa servir com a argument en el constructor de
DateTimeo al mètodesetTimezone(). -
Exemple:
new DateTimeZone('Asia/Tokyo').
DateInterval
Representa un període de temps (e.g., 2 anys, 3 mesos i 5 dies).
-
Ús: S'utilitza en operacions de data/hora.
-
Exemple:
new DateInterval('P2Y3M5D')(P de Període, 2 Anys, 3 Mesos, 5 Dies).
DatePeriod
Representa una col·lecció de dates i hores dins d'un període, iterant segons un DateInterval.
-
Ús: Generar una llista de totes les hores laborables entre dues dates.
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
$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";
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> --</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>
Exemple Calendari. OOP
Calendari, utilitzant la potència dels objectes DateTimeImmutable i DateInterval. Aquesta aproximació manté el codi dins del bloc PHP principal, però utilitza l'OOP per a la manipulació de dates, la qual cosa el fa més segur i menys propens a errors de fus horari.
A continuació, tens el codi utilitzant només objectes de data.
<?php
// index.php
// ----------------------------------------------------
// 1. Configuració i Inicialització de Dades
// ----------------------------------------------------
// Configuració del fus horari (CRÍTIC per a la fiabilitat de dates)
date_default_timezone_set('Europe/Madrid');
// Data d'avui i objectes base (Immutables per seguretat)
$dataAvui = new DateTimeImmutable('today');
// Primer dia del mes que volem mostrar (Setembre 2025)
$dataMesActual = new DateTimeImmutable('first day of this month');
// Últim dia del mes
$darrerDiaMes = new DateTimeImmutable('last day of this month');
// ----------------------------------------------------
// 2. Càlcul de la Data d'Inici (Primer Dilluns Visible)
// ----------------------------------------------------
// Dia de la setmana del 1r dia del mes (N: 1=Dl, 7=Dg)
$diaSetmanaPrimerDia = (int)$dataMesActual->format('N');
// Dies a restar per arribar al Dilluns anterior (o el mateix Dilluns)
$diesARestar = $diaSetmanaPrimerDia - 1;
$dataIteracio = $dataMesActual->modify("-$diesARestar days");
// ----------------------------------------------------
// 3. Càlcul de la Data de Finalització (Últim Diumenge Visible)
// ----------------------------------------------------
// Dia de la setmana de l'últim dia del mes (N: 1=Dl, 7=Dg)
$diaSetmanaDarrerDia = (int)$darrerDiaMes->format('N');
// Dies a sumar per arribar al diumenge (dia 7)
// Si acaba en Diumenge (7), sumem 0 dies. Si acaba en Dissabte (6), sumem 1 dia.
$diesASumar = 7 - $diaSetmanaDarrerDia;
// Data de finalització de la graella (l'últim diumenge de la setmana del mes)
$dataFiGraella = $darrerDiaMes->modify("+$diesASumar days");
// Interval per avançar dia a dia dins del bucle
$intervalDia = new DateInterval('P1D');
?>
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<title>Calendari Ajustat: <?php echo $dataMesActual->format("F - Y"); ?></title>
<style>
.calendari-taula {
border-collapse: collapse;
width: 400px;
text-align: center;
}
.calendari-taula th, .calendari-taula td {
padding: 8px;
border: 1px solid #ccc;
}
.altre-mes {
color: #aaa;
background-color: #f7f7f7;
}
.avui {
background-color: #ffe0b2;
font-weight: bold;
}
</style>
</head>
<body>
<h3> Calendari Ajustat: <?php echo $dataMesActual->format("F - Y"); ?></h3>
<table class="calendari-taula" cellspacing="0" cellpadding="0">
<tr>
<th>Dl</th><th>Dm</th><th>Dc</th><th>Dj</th><th>Dv</th><th>Ds</th><th>Dg</th>
</tr>
<?php
// ----------------------------------------------------
// 4. Bucle d'Iteració
// ----------------------------------------------------
while ($dataIteracio < $dataFiGraella) {
// Comença una nova fila cada dilluns (N=1)
if ($dataIteracio->format('N') == 1) {
echo "<tr>";
}
// --------------------------------------
// Determinació d'Estils
// --------------------------------------
$classe = '';
// A) És el dia actual?
if ($dataIteracio->format('Y-m-d') === $dataAvui->format('Y-m-d')) {
$classe = 'avui';
}
// B) És del mes que estem mostrant?
elseif ($dataIteracio->format('m') !== $dataMesActual->format('m')) {
$classe = 'altre-mes';
}
// Pintar la cel·la (j: dia del mes sense zero inicial)
echo "<td class='$classe'>";
echo $dataIteracio->format('j');
echo "</td>";
// Tanca la fila cada diumenge (N=7)
if ($dataIteracio->format('N') == 7) {
echo "</tr>";
}
// Avançar al dia següent
$dataIteracio = $dataIteracio->add($intervalDia);
}
?>
</table>
</body>
</html>
Explicació OOP
-
Fiabilitat amb
DateTimeImmutable: En lloc d'utilitzar múltiples crides adate()i la funció ambiguastrtotime(), ara tens un objecte$dataMesActualque representa el mes, i un objecte$dataIteracioque es modifica utilitzant el mètode->modify()o->add()juntament ambDateInterval. -
Càlculs Clars: El càlcul del primer dilluns (
$dataIteracio = $dataMesActual->modify("-$diesARestar days")) és molt més explícit i fiable que les manipulacions de strings de l'exemple inicial. -
Iteració Sencilla: El bucle
whileavança dia a dia utilitzant$dataIteracio = $dataIteracio->add($intervalDia), aprofitant la lògica de dates de PHP per gestionar canvis de mes i anys automàticament. -
Consistència: Es calcula la
$dataFiGraellaper garantir que la taula del calendari sempre tingui sis setmanes completes (6 * 7 dies), evitant que la taula es redimensioni segons el dia de la setmana en què acabi el mes.
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
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
// 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
-
Fiabilitat de Dates: L'ús de
DateTimeImmutable(en lloc de constants comdate("n")odate("Y")i funcions comstrtotime()) elimina l'ambigüitat en els càlculs i evita errors per manipulació del mateix objecte (immutabilitat). -
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. -
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.
-
Separació de Responsabilitats: El fitxer
index.phpnomés s'encarrega de crear l'objecte i mostrar el seu resultat (generaTaulaHTML()), separant la Lògica (la classe) de la Presentació (el HTML).