🐘 PHP Desde Cero - Guía Completa

Aprende PHP desde los fundamentos hasta conceptos avanzados

"PHP powers 77% of all websites whose server-side programming language we know."
Explorar Temas

📖 Temas del Curso

Haz clic en cualquier tema para ver el contenido detallado

📌 Introducción a PHP

¿Qué es PHP? PHP (Hypertext Preprocessor) es un lenguaje de scripting de código abierto ampliamente utilizado para el desarrollo web del lado del servidor. Fue creado por Rasmus Lerdorf en 1994 y ha evolucionado hasta convertirse en uno de los lenguajes más populares para crear sitios web dinámicos.

Características principales:

  • Código abierto: Gratuito y con una gran comunidad
  • Multiplataforma: Funciona en Windows, Linux, macOS
  • Fácil aprendizaje: Sintaxis sencilla similar a C y Perl
  • Base de datos: Soporte nativo para MySQL, PostgreSQL, SQLite

Estadísticas de uso:

Métrica Valor
Sitios web que usan PHP 77.4%
Version más usada PHP 8.x
Lanzamiento inicial 1995
💡 Dato curioso: PHP originalmente significaba "Personal Home Page" y era una colección de scripts CGI escritos en Perl.
← Volver a temas

🔧 Instalación y Configuración

En Windows con XAMPP:

  1. Descarga XAMPP desde apachefriends.org
  2. Ejecuta el instalador y selecciona los componentes
  3. Instala en C:\xampp (recomendado)
  4. Inicia el panel de control y arranca Apache y MySQL
  5. Accede a http://localhost para verificar

En Linux (Ubuntu/Debian):

# Actualizar repositorios
sudo apt update

# Instalar PHP y extensiones
sudo apt install php libapache2-mod-php php-mysql php-cli php-curl php-gd php-mbstring

# Verificar instalación
php --version

# Reiniciar Apache
sudo systemctl restart apache2

En macOS con Homebrew:

# Instalar Homebrew (si no lo tienes)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Instalar PHP
brew install php

# Verificar instalación
php --version

Configuración de php.ini:

; Habilitar display_errors (solo desarrollo)
display_errors = On

; Zona horaria
date.timezone = "America/New_York"

; Límite de memoria
memory_limit = 256M

; Tamaño máximo de subida
upload_max_filesize = 20M
post_max_size = 20M
← Volver a temas

📚 Sintaxis Básica

Estructura de un archivo PHP:

<?php
// Tu código PHP va aquí
echo "Hola Mundo!";
?>

Comentarios:

<?php
// Comentario de una línea

# También comentario de una línea

/*
    Comentario
    de múltiples
    líneas
*/
?>

Salida de datos:

<?php
echo "Hola Mundo";           // Imprime texto
print "Hola";                // Similar a echo
print_r($array);             // Imprime arrays
var_dump($variable);         // Muestra tipo y valor
?>

Diferencias entre echo y print:

Característica echo print
Velocidad Más rápido Un poco más lento
Retorno Void 1 (true)
Parámetros Múltiples Uno solo
💡 Tip: Siempre cierra tus archivos PHP con ?> solo si vas a mezclar HTML. Para archivos puramente PHP, omite el cierre para evitar espacios en blanco accidentales.
← Volver a temas

📦 Variables y Tipos de Datos

Declaración de variables:

<?php
$nombre = "Juan";           // String
$edad = 30;                 // Integer
$altura = 1.75;             // Float
$activo = true;             // Boolean
$nulo = null;               // Null

// Variables variables
$nombre_var = "ciudad";
$$nombre_var = "Madrid";    // $ciudad = "Madrid"
?>

Tipos de datos escalares:

<?php
// Boolean
$verdadero = true;
$falso = false;

// Integer
$entero = 42;
$negativo = -10;
$hex = 0x1A;        // 26 en decimal
$bin = 0b1010;      // 10 en decimal

// Float
$decimal = 3.14;
$cientifico = 1.2e3;  // 1200

// String
$texto = 'Hola';
$nombre = "Juan";
$heredoc = <<<EOT
Texto multilínea
con variables $nombre
EOT;
?>

Tipos de datos compuestos:

<?php
// Array indexado
$frutas = ["manzana", "banana", "naranja"];

// Array asociativo
$persona = [
    "nombre" => "Juan",
    "edad" => 30,
    "ciudad" => "Madrid"
];

// Array multidimensional
$matriz = [
    [1, 2, 3],
    [4, 5, 6]
];
?>

Constantes:

<?php
// Usando define()
define("PI", 3.1416);
define("NOMBRE_SITIO", "Mi Web");

// Usando const (más rápido)
const VERSION = "1.0.0";

// Constantes predefinidas
echo PHP_VERSION;
echo PHP_OS;
?>
← Volver a temas

🔷 Funciones y Scope

Declaración de funciones:

<?php
// Función básica
function saludar() {
    echo "Hola!";
}

// Función con parámetros
function saludarPersona($nombre) {
    echo "Hola $nombre!";
}

// Función con valor por defecto
function saludar($nombre = "Invitado") {
    echo "Hola $nombre!";
}

// Función con retorno
function sumar($a, $b) {
    return $a + $b;
}

// Tipado de parámetros y retorno (PHP 7+)
function multiplicar(int $a, int $b): int {
    return $a * $b;
}
?>

Arrow functions (PHP 7.4+):

<?php
// Sintaxis tradicional
$cuadrado = function($x) {
    return $x ** 2;
};

// Arrow function
$cuadrado = fn($x) => $x ** 2;

// Con tipos
$multiplicar = fn(int $a, int $b): int => $a * $b;
?>

Scope de variables:

<?php
$global = "Soy global";

function test() {
    // $global no es accesible aquí
    global $global;  // Importar variable global
    echo $global;
    
    // Alternativa con $GLOBALS
    echo $GLOBALS['global'];
}

// Variable estática
function contador() {
    static $count = 0;
    $count++;
    echo $count;
}

contador();  // 1
contador();  // 2
?>

Funciones variádicas:

<?php
// Usando ... (PHP 5.6+)
function sumar(...$numeros) {
    return array_sum($numeros);
}

echo sumar(1, 2, 3, 4);  // 10

// Desestructuración
function operar($operacion, ...$valores) {
    // $valores es un array
}
?>
← Volver a temas

📊 Arrays y Funciones de Array

Creación y acceso:

<?php
// Array indexado
$frutas = ["manzana", "banana", "naranja"];
echo $frutas[0];  // manzana

// Array asociativo
$persona = [
    "nombre" => "Juan",
    "edad" => 30
];
echo $persona["nombre"];  // Juan

// Agregar elementos
$frutas[] = "pera";
array_push($frutas, "uva");

// Eliminar elementos
unset($frutas[0]);
array_pop($frutas);  // Último
array_shift($frutas); // Primero
?>

Funciones útiles de array:

<?php
$nums = [1, 2, 3, 4, 5];

// Información
count($nums);           // 5
in_array(3, $nums);     // true
array_key_exists(0, $nums); // true

// Búsqueda
array_search(3, $nums); // 2
array_find($nums, fn($n) => $n > 3); // PHP 8.3+

// Transformación
array_map(fn($n) => $n * 2, $nums);
array_filter($nums, fn($n) => $n > 2);
array_reduce($nums, fn($c, $n) => $c + $n, 0);

// Ordenamiento
sort($nums);           // Ascendente
rsort($nums);          // Descendente
asort($persona);       // Por valor
ksort($persona);       // Por clave
?>

Iteración de arrays:

<?php
$frutas = ["manzana", "banana", "naranja"];

// foreach tradicional
foreach ($frutas as $fruta) {
    echo $fruta;
}

// foreach con clave
foreach ($frutas as $indice => $fruta) {
    echo "$indice: $fruta";
}

// while con each (obsoleto en PHP 7.2+)
reset($frutas);
while ($par = each($frutas)) {
    echo $par['value'];
}

// Usando Iterator
$iterador = new ArrayIterator($frutas);
?>
💡 Tip: Para arrays grandes, considera usar yield para crear generadores y ahorrar memoria.
← Volver a temas

📝 Formularios y Sesiones

Manejo de formularios:

<?php
// Método POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $nombre = $_POST['nombre'] ?? '';
    $email = $_POST['email'] ?? '';
    
    // Sanitización
    $nombre = htmlspecialchars(trim($nombre));
    $email = filter_var($email, FILTER_SANITIZE_EMAIL);
    
    // Validación
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $error = "Email inválido";
    }
}
?>

<form method="POST" action="">
    <input type="text" name="nombre" required>
    <input type="email" name="email" required>
    <button type="submit">Enviar</button>
</form>

Sesiones:

<?php
// Iniciar sesión (debe ser lo primero)
session_start();

// Guardar datos en sesión
$_SESSION['usuario'] = 'juan';
$_SESSION['id'] = 123;

// Leer datos
$usuario = $_SESSION['usuario'] ?? null;

// Eliminar un dato
unset($_SESSION['usuario']);

// Destruir sesión completa
session_destroy();

// Regenerar ID (seguridad)
session_regenerate_id(true);
?>

Cookies:

<?php
// Establecer cookie (1 hora)
setcookie('usuario', 'juan', time() + 3600, '/');

// Cookie segura (HTTPS only)
setcookie('token', 'abc123', [
    'expires' => time() + 3600,
    'path' => '/',
    'domain' => 'tudominio.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Strict'
]);

// Leer cookie
$usuario = $_COOKIE['usuario'] ?? null;

// Eliminar cookie
setcookie('usuario', '', time() - 3600, '/');
?>

Seguridad en formularios:

<?php
// Token CSRF
session_start();
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

// En el formulario
echo '<input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '">';

// Validar al recibir
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
    die('Token CSRF inválido');
}
?>
← Volver a temas

🗄️ PDO y Bases de Datos

Conexión con PDO:

<?php
$dsn = 'mysql:host=localhost;dbname=mibd;charset=utf8mb4';
$usuario = 'root';
$password = '';

$options = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES => false,
];

try {
    $pdo = new PDO($dsn, $usuario, $password, $options);
} catch (PDOException $e) {
    throw new PDOException($e->getMessage(), (int)$e->getCode());
}
?>

Consultas preparadas (CRUD):

<?php
// CREATE
$stmt = $pdo->prepare("INSERT INTO usuarios (nombre, email) VALUES (:nombre, :email)");
$stmt->execute(['nombre' => 'Juan', 'email' => 'juan@email.com']);
$id = $pdo->lastInsertId();

// READ
$stmt = $pdo->prepare("SELECT * FROM usuarios WHERE id = :id");
$stmt->execute(['id' => 1]);
$usuario = $stmt->fetch();

// READ múltiple
$stmt = $pdo->query("SELECT * FROM usuarios");
$usuarios = $stmt->fetchAll();

// UPDATE
$stmt = $pdo->prepare("UPDATE usuarios SET email = :email WHERE id = :id");
$stmt->execute(['email' => 'nuevo@email.com', 'id' => 1]);

// DELETE
$stmt = $pdo->prepare("DELETE FROM usuarios WHERE id = :id");
$stmt->execute(['id' => 1]);
?>

Transacciones:

<?php
try {
    $pdo->beginTransaction();
    
    $stmt = $pdo->prepare("INSERT INTO pedidos (usuario_id, total) VALUES (:uid, :total)");
    $stmt->execute(['uid' => 1, 'total' => 100]);
    
    $stmt = $pdo->prepare("UPDATE usuarios SET saldo = saldo - :total WHERE id = :uid");
    $stmt->execute(['total' => 100, 'uid' => 1]);
    
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Error: " . $e->getMessage();
}
?>
⚠️ Importante: Siempre usa consultas preparadas para prevenir inyección SQL. Nunca concatenes variables directamente en las consultas.
← Volver a temas

🏗️ Programación Orientada a Objetos

Clases y objetos:

<?php
class Persona {
    // Propiedades
    private string $nombre;
    private int $edad;
    
    // Constructor
    public function __construct(string $nombre, int $edad) {
        $this->nombre = $nombre;
        $this->edad = $edad;
    }
    
    // Métodos
    public function saludar(): string {
        return "Hola, soy {$this->nombre}";
    }
    
    // Getters y Setters
    public function getNombre(): string {
        return $this->nombre;
    }
    
    public function setNombre(string $nombre): void {
        $this->nombre = $nombre;
    }
}

// Uso
$juan = new Persona("Juan", 30);
echo $juan->saludar();
?>

Herencia:

<?php
class Empleado extends Persona {
    private float $salario;
    
    public function __construct(string $nombre, int $edad, float $salario) {
        parent::__construct($nombre, $edad);
        $this->salario = $salario;
    }
    
    public function trabajar(): string {
        return "{$this->getNombre()} está trabajando";
    }
}
?>

Interfaces y clases abstractas:

<?php
interface Hablador {
    public function hablar(): string;
}

abstract class Animal {
    abstract public function hacerSonido(): string;
}

class Perro extends Animal implements Hablador {
    public function hacerSonido(): string {
        return "Guau!";
    }
    
    public function hablar(): string {
        return "Soy un perro";
    }
}
?>

Traits:

<?php
trait Loggable {
    public function log(string $mensaje): void {
        echo "[LOG]: $mensaje";
    }
}

class Usuario {
    use Loggable;
}

$usuario = new Usuario();
$usuario->log("Usuario creado");
?>
← Volver a temas

🏛️ MVC Pattern

Estructura MVC:

/app
├── controllers/
│   └── UsuarioController.php
├── models/
│   └── Usuario.php
├── views/
│   └── usuarios/
│       └── index.php
└── core/
    ├── Database.php
    └── Controller.php

Modelo:

<?php
class Usuario {
    private $db;
    
    public function __construct() {
        $this->db = Database::getInstance();
    }
    
    public function getAll(): array {
        $this->db->query("SELECT * FROM usuarios");
        return $this->db->fetchAll();
    }
    
    public function getById(int $id): ?array {
        $this->db->query("SELECT * FROM usuarios WHERE id = :id");
        $this->db->bind(':id', $id);
        return $this->db->fetch();
    }
}
?>

Controlador:

<?php
class UsuarioController extends Controller {
    private $usuarioModel;
    
    public function __construct() {
        $this->usuarioModel = $this->model('Usuario');
    }
    
    public function index() {
        $usuarios = $this->usuarioModel->getAll();
        $this->view('usuarios/index', ['usuarios' => $usuarios]);
    }
    
    public function show(int $id) {
        $usuario = $this->usuarioModel->getById($id);
        $this->view('usuarios/show', ['usuario' => $usuario]);
    }
}
?>

Vista:

<!-- views/usuarios/index.php -->
<h1>Lista de Usuarios</h1>
<ul>
    <?php foreach ($usuarios as $usuario): ?>
        <li><?= htmlspecialchars($usuario['nombre']) ?></li>
    <?php endforeach; ?>
</ul>
💡 Beneficios de MVC: Separación de responsabilidades, código más mantenible, fácil testing, reutilización de componentes.
← Volver a temas

🌐 APIs REST

API REST básica:

<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');

$method = $_SERVER['REQUEST_METHOD'];
$endpoint = $_GET['endpoint'] ?? '';

switch ($method) {
    case 'GET':
        getUsers($endpoint);
        break;
    case 'POST':
        createUser();
        break;
    case 'PUT':
        updateUser($endpoint);
        break;
    case 'DELETE':
        deleteUser($endpoint);
        break;
    default:
        http_response_code(405);
        echo json_encode(['error' => 'Method not allowed']);
}

function getUsers($endpoint) {
    if ($endpoint) {
        // Obtener usuario específico
        $usuario = ['id' => $endpoint, 'nombre' => 'Juan'];
        echo json_encode($usuario);
    } else {
        // Listar todos
        $usuarios = [
            ['id' => 1, 'nombre' => 'Juan'],
            ['id' => 2, 'nombre' => 'Maria']
        ];
        echo json_encode($usuarios);
    }
}
?>

Autenticación con JWT:

<?php
use Firebase\JWT\JWT;

// Generar token
function generarToken($usuario) {
    $payload = [
        'iat' => time(),
        'exp' => time() + 3600,
        'data' => $usuario
    ];
    
    return JWT::encode($payload, 'TU_CLAVE_SECRETA', 'HS256');
}

// Verificar token
function verificarToken($token) {
    try {
        return JWT::decode($token, 'TU_CLAVE_SECRETA', ['HS256']);
    } catch (Exception $e) {
        return null;
    }
}

// Middleware de autenticación
function authMiddleware() {
    $headers = getallheaders();
    $authHeader = $headers['Authorization'] ?? '';
    
    if (preg_match('/Bearer\s+(.*)/', $authHeader, $matches)) {
        $token = $matches[1];
        $payload = verificarToken($token);
        
        if ($payload) {
            return $payload->data;
        }
    }
    
    http_response_code(401);
    exit(json_encode(['error' => 'Unauthorized']));
}
?>

Respuestas HTTP:

<?php
// 200 OK
http_response_code(200);
echo json_encode(['success' => true, 'data' => $data]);

// 201 Created
http_response_code(201);
echo json_encode(['success' => true, 'message' => 'Recurso creado']);

// 400 Bad Request
http_response_code(400);
echo json_encode(['success' => false, 'error' => 'Datos inválidos']);

// 404 Not Found
http_response_code(404);
echo json_encode(['success' => false, 'error' => 'Recurso no encontrado']);

// 500 Internal Server Error
http_response_code(500);
echo json_encode(['success' => false, 'error' => 'Error interno']);
?>
← Volver a temas

🎯 Laravel / Symfony

Laravel - Instalación:

# Instalar Laravel Installer
composer global require laravel/installer

# Crear nuevo proyecto
laravel new mi-proyecto

# O con Composer
composer create-project laravel/laravel mi-proyecto

# Servidor de desarrollo
cd mi-proyecto
php artisan serve

Laravel - Estructura:

/app
├── Http/
│   ├── Controllers/
│   └── Middleware/
├── Models/
├── Providers/
└── ...
/database
├── migrations/
├── seeders/
└── factories/
/resources
├── views/
└── css/
/routes
└── web.php

Laravel - Rutas y Controladores:

// routes/web.php
Route::get('/', [HomeController::class, 'index']);
Route::resource('usuarios', UsuarioController::class);

// app/Http/Controllers/UsuarioController.php
class UsuarioController extends Controller {
    public function index() {
        $usuarios = Usuario::all();
        return view('usuarios.index', compact('usuarios'));
    }
    
    public function store(Request $request) {
        $validated = $request->validate([
            'nombre' => 'required|string|max:255',
            'email' => 'required|email|unique:usuarios'
        ]);
        
        Usuario::create($validated);
        return redirect()->route('usuarios.index');
    }
}

Symfony - Instalación:

# Instalar Symfony CLI
curl -sS https://get.symfony.com/cli/installer | bash

# Crear proyecto
symfony new mi-proyecto --webapp

# Servidor de desarrollo
symfony serve

Symfony - Controlador:

// src/Controller/UsuarioController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class UsuarioController extends AbstractController {
    #[Route('/usuarios', name: 'usuarios_index')]
    public function index(): Response {
        $usuarios = $this->getDoctrine()
            ->getRepository(Usuario::class)
            ->findAll();
            
        return $this->render('usuarios/index.html.twig', [
            'usuarios' => $usuarios
        ]);
    }
}
💡 Comparación: Laravel es más opinado y tiene más características out-of-the-box. Symfony es más modular y flexible, ideal para proyectos enterprise.
← Volver a temas

📚 Contenido del Curso

Módulo 1: Fundamentos

  • Introducción a PHP
  • Instalación y configuración
  • Sintaxis básica
  • Variables y tipos de datos
Ir a temas →

Módulo 2: Intermedio

  • Funciones y scope
  • Arrays y funciones de array
  • Formularios y sesiones
  • PDO y bases de datos
Ir a temas →

Módulo 3: Avanzado

  • Programación orientada a objetos
  • MVC pattern
  • APIs REST
  • Laravel / Symfony
Ir a temas →

📝 Ejemplos Rápidos

Variables y Tipos

<?php
$nombre = "Juan";
$edad = 30;
$altura = 1.75;
$esEstudiante = true;
$hobbies = ["leer", "codificar"];
$persona = ["nombre" => $nombre, "edad" => $edad];
?>

Funciones

<?php
function saludar($nombre) {
    return "Hola $nombre";
}

function sumar($a, $b = 0) {
    return $a + $b;
}

// Arrow functions (PHP 7.4+)
$cuadrado = fn($x) => $x ** 2;
?>

PDO y Base de Datos

<?php
$dsn = 'mysql:host=localhost;dbname=mibd';
$usuario = 'root';
$password = '';

try {
    $pdo = new PDO($dsn, $usuario, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $pdo->prepare("SELECT * FROM usuarios WHERE id = :id");
    $stmt->execute(['id' => 1]);
    $usuario = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}
?>

📖 Recursos Adicionales

Herramientas

  • XAMPP
  • Composer
  • PHPUnit

Comunidades

👨‍💻 Desarrollado por Isaac Esteban Haro Torres

Ingeniero en Sistemas · Full Stack · Automatización · Data

📧 Email: zackharo1@gmail.com

📱 WhatsApp: 098805517

💻 GitHub: github.com/ieharo1

🌐 Portafolio: ieharo1.github.io/portafolio-isaac.haro/