Programación · n.º 13 entre los lenguajes más usados

Aprende PHP desde cero

El lenguaje de servidor detrás de WordPress y de buena parte de la web.

  • 10 lecciones
  • 10 ejercicios interactivos
  • 20 conceptos clave
  • 17,7 % lo usa*

Qué es PHP y para qué sirve

PHP se ejecuta en el servidor: genera la página HTML antes de enviarla al navegador. Con él están hechos WordPress, Wikipedia (MediaWiki) y frameworks como Laravel y Symfony. Las versiones modernas (PHP 8) tienen tipos, clases y un rendimiento muy distinto al del PHP de hace años.

  • Webs dinámicas y tiendas online
  • WordPress y otros gestores de contenidos
  • APIs y paneles de administración

Para empezar: Instala PHP desde php.net (o con un paquete como XAMPP) y lanza el servidor de pruebas con php -S localhost:8000.

Nivel 1 Básico

Lección 1 · Básico

Tu primer script

El código PHP va entre <?php y ?>, y puede mezclarse con HTML: el servidor ejecuta el PHP y envía al navegador solo el resultado. echo escribe texto en la página.

PHP trae un servidor web de pruebas: en la carpeta del proyecto, php -S localhost:8000 y abre esa dirección en el navegador.

Ejemplo práctico
<!-- index.php -->
<!DOCTYPE html>
<html lang="es">
<body>
  <h1><?php echo "¡Hola, mundo!"; ?></h1>
  <p>Hoy es <?= date("d/m/Y") ?></p>
</body>
</html>

Ejercicio

¿Dónde se ejecuta el código PHP?

Ver la solución

Respuesta: En el servidor, antes de enviar la página. El servidor ejecuta el PHP y el navegador solo recibe el HTML resultante.

Lección 2 · Básico

Variables y texto

Las variables empiezan por $ y no se declaran con tipo. Los textos se unen con el punto ..

Entre comillas dobles, las variables se sustituyen por su valor; entre comillas simples, no.

Ejemplo práctico
<?php
$nombre = "Ana";
$edad = 30;
$edad++;

echo "Hola, $nombre. Tienes $edad años.\n";
echo 'Hola, $nombre' . "\n";        // Hola, $nombre
echo "Total: " . (3 * 19.99) . " €\n";

Ejercicio

Completa el operador que une dos textos.

echo "Hola, "  $nombre;
Ver la solución

Respuesta: .. En PHP el punto . concatena cadenas; el + es solo para sumar números.

Lección 3 · Básico

Condiciones y bucles

if, elseif y else deciden qué se ejecuta. Compara con ===, que también comprueba el tipo, para evitar sorpresas con las conversiones automáticas.

foreach recorre un array, for usa un contador y while repite mientras se cumpla una condición.

Ejemplo práctico
<?php
$nota = 7;

if ($nota >= 9) {
    echo "Sobresaliente\n";
} elseif ($nota >= 5) {
    echo "Aprobado\n";
} else {
    echo "Suspenso\n";
}

for ($i = 1; $i <= 3; $i++) {
    echo "Vuelta $i\n";
}

Ejercicio

¿Qué comparación comprueba valor y tipo a la vez?

Ver la solución

Respuesta: ===. === exige el mismo valor y el mismo tipo; == convierte los tipos antes de comparar.

Lección 4 · Básico

Arrays

Un array puede ser una lista (["pan", "leche"]) o asociativo, con claves de texto (["teclado" => 10]). count() dice cuántos elementos tiene.

foreach recorre los valores, o las claves y los valores a la vez con $clave => $valor.

Ejemplo práctico
<?php
$compra = ["pan", "leche"];
$compra[] = "huevos";              // añade al final
echo count($compra) . "\n";        // 3

$stock = ["teclado" => 10, "raton" => 0];
foreach ($stock as $producto => $unidades) {
    echo "$producto: $unidades\n";
}

Ejercicio

¿Qué hace $compra[] = "huevos";?

Ver la solución

Respuesta: Añade «huevos» al final. Con corchetes vacíos, PHP añade el valor en la siguiente posición libre.

Nivel 2 Intermedio

Lección 5 · Intermedio

Funciones con tipos

Las funciones se declaran con function. Desde PHP 7 puedes indicar el tipo de los parámetros y del valor devuelto, y con declare(strict_types=1); PHP los respeta sin convertir.

Los parámetros pueden tener valor por defecto y se pueden pasar por nombre (PHP 8).

Ejemplo práctico
<?php
declare(strict_types=1);

function precioFinal(float $precio, float $iva = 21): float
{
    return round($precio * (1 + $iva / 100), 2);
}

echo precioFinal(100) . "\n";            // 121
echo precioFinal(precio: 100, iva: 10);  // 110

Ejercicio

¿Qué hace declare(strict_types=1);?

Ver la solución

Respuesta: Hace que PHP no convierta los tipos de los argumentos. Con tipos estrictos, pasar un texto donde se espera float da un error en lugar de convertirlo.

Lección 6 · Intermedio

Formularios y seguridad

Los datos de un formulario enviado con method="post" llegan en el array $_POST. Nunca confíes en ellos: valídalos antes de usarlos.

Para mostrar en la página algo que escribió el usuario, pásalo por htmlspecialchars(). Así un <script> se muestra como texto y no se ejecuta (se evita el ataque XSS).

Ejemplo práctico
<?php
$nombre = trim($_POST["nombre"] ?? "");

if ($nombre === "") {
    echo "Escribe tu nombre";
} else {
    echo "Hola, " . htmlspecialchars($nombre, ENT_QUOTES, "UTF-8");
}
?>
<form method="post">
  <label for="nombre">Nombre</label>
  <input id="nombre" name="nombre">
  <button>Enviar</button>
</form>

Ejercicio

Completa la función que evita que el texto del usuario se interprete como HTML.

echo ($comentario);
Ver la solución

Respuesta: htmlspecialchars. htmlspecialchars convierte <, >, & y las comillas en entidades HTML inofensivas.

Conceptos clave

Lección 7 · Intermedio

Clases y objetos

Una clase agrupa datos (propiedades) y funciones (métodos). Con la promoción de propiedades del constructor (PHP 8) declaras y asignas las propiedades en una sola línea.

$this es el propio objeto, y la flecha -> accede a sus propiedades y métodos.

Ejemplo práctico
<?php
class Cuenta
{
    public function __construct(
        public readonly string $titular,
        private float $saldo = 0,
    ) {}

    public function ingresar(float $cantidad): void
    {
        $this->saldo += $cantidad;
    }

    public function saldo(): float
    {
        return $this->saldo;
    }
}

$c = new Cuenta("Ana");
$c->ingresar(50);
echo $c->titular . ": " . $c->saldo();   // Ana: 50

Ejercicio

¿Con qué operador llamas a un método de un objeto en PHP?

Ver la solución

Respuesta: ->. $objeto->metodo() llama a un método de ese objeto; :: es para lo estático.

Nivel 3 Avanzado

Lección 8 · Avanzado

Bases de datos con PDO

PDO es la forma estándar de conectar PHP con MySQL, PostgreSQL o SQLite. Usa siempre consultas preparadas: escribes huecos y pasas los valores aparte.

Así evitas la inyección SQL, porque los datos del usuario nunca se mezclan con el código de la consulta.

Ejemplo práctico
<?php
$pdo = new PDO("sqlite:tienda.db", options: [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

$consulta = $pdo->prepare("SELECT nombre, precio FROM productos WHERE precio < :max");
$consulta->execute(["max" => 20]);

foreach ($consulta as $fila) {
    echo $fila["nombre"] . ": " . $fila["precio"] . "\n";
}

Ejercicio

¿Por qué usar prepare() y execute() en lugar de pegar el valor en la consulta?

Ver la solución

Respuesta: Para evitar la inyección SQL. Los valores van separados de la consulta, así que no pueden cambiar lo que hace.

Lección 9 · Avanzado

Composer y la carga automática

Composer es el gestor de paquetes de PHP: composer require paquete descarga una biblioteca en la carpeta vendor y la apunta en composer.json.

Incluyendo vendor/autoload.php, las clases se cargan solas cuando las usas, sin escribir un require por archivo.

Ejemplo práctico
# En la terminal
composer init
composer require monolog/monolog

<?php
require __DIR__ . "/vendor/autoload.php";

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger("tienda");
$log->pushHandler(new StreamHandler(__DIR__ . "/app.log"));
$log->info("Pedido recibido", ["id" => 42]);

Ejercicio

Completa el archivo que activa la carga automática de las bibliotecas.

require __DIR__ . "/vendor/.php";
Ver la solución

Respuesta: autoload. vendor/autoload.php, generado por Composer, carga cada clase la primera vez que se usa.

Lección 10 · Avanzado

Errores y excepciones

Cuando algo no puede continuar, lanza una excepción con throw y captúrala donde sepas qué hacer, con try y catch. finally se ejecuta siempre.

En producción no muestres los errores en la página (pueden revelar datos internos): regístralos en un archivo.

Ejemplo práctico
<?php
function dividir(float $a, float $b): float
{
    if ($b == 0) {
        throw new InvalidArgumentException("No se puede dividir entre cero");
    }
    return $a / $b;
}

try {
    echo dividir(10, 0);
} catch (InvalidArgumentException $e) {
    echo "Error: " . $e->getMessage();
} finally {
    echo "\nCálculo terminado";
}

Ejercicio

Completa la palabra que lanza una excepción.

 new RuntimeException("Falta el archivo");
Ver la solución

Respuesta: throw. throw lanza la excepción, que sube hasta el catch más cercano.

¿Has terminado? Sigue practicando

Repasa los conceptos en el diccionario, practica con estas herramientas o prueba otro lenguaje: las ideas que has aprendido (variables, condiciones, funciones, objetos…) te servirán en cualquiera.

  • Texto y programación

    Base64, URL y JSON

    Codifica y decodifica Base64 y URL, y valida o formatea JSON con la línea del error.

  • Seguridad y privacidad

    Analizar un enlace sospechoso

    Revisa un enlace sin abrirlo y descubre si imita a un banco o a otra web conocida.

  • Texto y programación

    Selector de colores y contraste

    Convierte colores entre HEX, RGB y HSL, toma colores de una imagen y comprueba el contraste WCAG.

Fuentes consultadas

* Porcentaje de personas que dijeron haber usado PHP en la Stack Overflow Developer Survey 2026: Technology (pregunta sobre lenguajes de programación, de scripts y de marcado; todas las respuestas). El progreso de las lecciones se guarda solo en este navegador.