Skip to content

iruuuuu/mvcBlog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📚 Guía Completa de Estudio: PHP y Patrón MVC

📌 Nota: Esta guía está diseñada para ayudarte a entender el código del proyecto MVC que has desarrollado. Léela con calma y practica cada concepto.

1. Fundamentos de PHP

1.1 ¿Qué es PHP?

PHP (Hypertext Preprocessor) es un lenguaje de programación del lado del servidor diseñado específicamente para el desarrollo web. Se ejecuta en el servidor y genera HTML que se envía al navegador del cliente.

1.2 Sintaxis Básica

Variables

En PHP, las variables comienzan con el símbolo $:

<?php
$nombre = "Juan";           // String (cadena de texto)
$edad = 25;                 // Integer (número entero)
$precio = 19.99;            // Float (número decimal)
$activo = true;             // Boolean (verdadero/falso)
$colores = ["rojo", "azul"]; // Array (arreglo)
?>

Concatenación de Strings

<?php
$nombre = "Juan";
$apellido = "Pérez";

// Usando el operador punto (.)
$nombreCompleto = $nombre . " " . $apellido;

// Usando comillas dobles (interpola variables)
$saludo = "Hola, $nombre $apellido";

// Usando comillas simples (NO interpola)
$texto = 'Hola, $nombre'; // Imprime: Hola, $nombre
?>

Estructuras de Control

<?php
// IF - ELSE
if ($edad >= 18) {
    echo "Eres mayor de edad";
} else {
    echo "Eres menor de edad";
}

// SWITCH
switch ($dia) {
    case "lunes":
        echo "Inicio de semana";
        break;
    case "viernes":
        echo "Fin de semana cerca";
        break;
    default:
        echo "Día normal";
}

// BUCLE FOR
for ($i = 0; $i < 5; $i++) {
    echo "Número: $i";
}

// BUCLE FOREACH (para arrays)
$frutas = ["manzana", "pera", "uva"];
foreach ($frutas as $fruta) {
    echo $fruta;
}
?>

Funciones

<?php
// Definir una función
function saludar($nombre) {
    return "Hola, " . $nombre;
}

// Llamar a la función
$mensaje = saludar("Juan");
echo $mensaje; // Imprime: Hola, Juan

// Función con valor por defecto
function calcularPrecio($precio, $descuento = 0) {
    return $precio - ($precio * $descuento / 100);
}

echo calcularPrecio(100);      // 100
echo calcularPrecio(100, 10);  // 90
?>

2. Programación Orientada a Objetos (POO) en PHP

2.1 ¿Qué es la POO?

La Programación Orientada a Objetos es un paradigma que organiza el código en "objetos" que contienen datos (propiedades) y comportamientos (métodos). Es como crear plantillas (clases) para crear cosas (objetos).

2.2 Clases y Objetos

<?php
// Definir una clase (plantilla)
class Coche {
    // Propiedades (características)
    public $marca;
    public $color;
    private $velocidad = 0;
    
    // Constructor (se ejecuta al crear el objeto)
    public function __construct($marca, $color) {
        $this->marca = $marca;
        $this->color = $color;
    }
    
    // Métodos (acciones)
    public function acelerar($cantidad) {
        $this->velocidad += $cantidad;
        return "Acelerando a " . $this->velocidad . " km/h";
    }
    
    public function getVelocidad() {
        return $this->velocidad;
    }
}

// Crear objetos (instancias de la clase)
$miCoche = new Coche("Toyota", "rojo");
echo $miCoche->marca;           // Toyota
echo $miCoche->acelerar(50);    // Acelerando a 50 km/h
?>

2.3 Modificadores de Acceso

Modificador Descripción Acceso desde


public Accesible desde cualquier lugar Clase, subclases, fuera de la clase private Solo accesible dentro de la clase Solo dentro de la clase protected Accesible en la clase y subclases Clase y subclases

2.4 $this y self

<?php
class Ejemplo {
    private $nombre = "Juan";
    private static $contador = 0;
    
    public function mostrarNombre() {
        // $this se refiere al objeto actual
        return $this->nombre;
    }
    
    public static function incrementar() {
        // self se refiere a la clase (para propiedades estáticas)
        self::$contador++;
    }
}
?>

3. El Patrón MVC (Modelo-Vista-Controlador)

3.1 ¿Qué es MVC?

MVC es un patrón de arquitectura de software que separa la aplicación en tres componentes principales:

  • Modelo (Model): Maneja los datos y la lógica de negocio
  • Vista (View): Presenta la información al usuario (HTML)
  • Controlador (Controller): Gestiona las peticiones y coordina Modelo y Vista

💡 Analogía: Imagina un restaurante:

  • Modelo: La cocina (prepara la comida/datos)
  • Vista: El plato servido (presentación)
  • Controlador: El camarero (toma pedidos y coordina) :::

3.2 Flujo de una Petición MVC

1. Usuario hace clic en un enlace: index.php?c=post&action=create
2. index.php recibe la petición
3. index.php carga el controlador correspondiente (postController)
4. El controlador llama al método correspondiente (create)
5. El controlador puede usar el Modelo para obtener/guardar datos
6. El controlador carga la Vista con los datos
7. La Vista genera el HTML
8. El HTML se envía al navegador del usuario

3.3 Estructura de Carpetas del Proyecto

mvc/
├── controllers/          # Controladores (lógica de la aplicación)
│   ├── mainController.php
│   ├── userController.php
│   ├── postController.php
│   └── commentController.php
├── models/              # Modelos (datos y lógica de negocio)
│   ├── User.php
│   ├── UserRepositori.php
│   ├── Post.php
│   ├── PostRepository.php
│   ├── Comment.php
│   └── CommentRepository.php
├── views/               # Vistas (presentación HTML)
│   ├── blogView.phtml
│   ├── loginView.phtml
│   ├── registerView.phtml
│   └── createPostView.phtml
├── scripts/             # Scripts SQL
│   ├── create_database.sql
│   └── add_roles.sql
├── db.php              # Conexión a la base de datos
└── index.php           # Punto de entrada de la aplicación

4. Análisis del Código del Proyecto

4.1 index.php - El Punto de Entrada

<?php
session_start();  // Inicia la sesión para manejar usuarios logueados

// Obtiene el controlador de la URL (por defecto 'main')
$controller = $_GET['c'] ?? 'main';

// Carga el archivo del controlador
require_once "controllers/{$controller}Controller.php";

// Crea el nombre de la clase del controlador
$controllerClass = $controller . 'Controller';

// Crea una instancia del controlador
$controllerObj = new $controllerClass();

// Obtiene la acción de la URL (por defecto 'index')
$action = $_GET['action'] ?? 'index';

// Llama al método del controlador
$controllerObj->$action();
?>

📌 Ejemplo: Si visitas index.php?c=post&action=create:

  1. $controller = "post"
  2. Se carga "controllers/postController.php"
  3. $controllerClass = "postController"
  4. Se crea un objeto de postController
  5. $action = "create"
  6. Se llama al método create() del controlador

4.2 db.php - Conexión a la Base de Datos

<?php
class Database {
    private static $instance = null;
    private $connection;
    
    // Constructor privado (patrón Singleton)
    private function __construct() {
        $host = 'localhost';
        $dbname = 'blog';
        $username = 'root';
        $password = '';
        
        // PDO: PHP Data Objects (forma segura de conectar a BD)
        $this->connection = new PDO(
            "mysql:host=$host;dbname=$dbname;charset=utf8",
            $username,
            $password
        );
        
        // Configurar PDO para lanzar excepciones en errores
        $this->connection->setAttribute(
            PDO::ATTR_ERRMODE, 
            PDO::ERRMODE_EXCEPTION
        );
    }
    
    // Obtener la única instancia (Singleton)
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function getConnection() {
        return $this->connection;
    }
}
?>

💡 Patrón Singleton: Garantiza que solo exista UNA conexión a la base de datos en toda la aplicación. Es como tener una sola llave para

4.3 Modelos - Clases de Entidad

Las clases de entidad representan objetos del mundo real (User, Post, Comment):

<?php
class User {
    private $id;
    private $username;
    private $password;
    private $role;
    
    // Constructor
    public function __construct($id, $username, $password, $role = 'user') {
        $this->id = $id;
        $this->username = $username;
        $this->password = $password;
        $this->role = $role;
    }
    
    // Getters (obtener valores)
    public function getId() {
        return $this->id;
    }
    
    public function getUsername() {
        return $this->username;
    }
    
    public function getRole() {
        return $this->role;
    }
    
    // Método para verificar si es administrador
    public function isAdmin() {
        return $this->role === 'admin';
    }
}
?>

4.4 Repositorios - Acceso a Datos

Los repositorios manejan todas las operaciones de base de datos:

<?php
class UserRepositori {
    private $db;
    
    public function __construct() {
        // Obtener la conexión a la base de datos
        $this->db = Database::getInstance()->getConnection();
    }
    
    // Buscar usuario por nombre
    public function findByUsername($username) {
        // Preparar consulta SQL (previene inyección SQL)
        $stmt = $this->db->prepare(
            "SELECT * FROM user WHERE username = :username"
        );
        
        // Ejecutar con parámetros
        $stmt->execute(['username' => $username]);
        
        // Obtener resultado
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if ($row) {
            // Crear objeto User con los datos
            return new User(
                $row['id'],
                $row['username'],
                $row['password'],
                $row['role']
            );
        }
        
        return null;
    }
    
    // Crear nuevo usuario
    public function create($username, $password, $role = 'user') {
        $stmt = $this->db->prepare(
            "INSERT INTO user (username, password, role) 
             VALUES (:username, :password, :role)"
        );
        
        return $stmt->execute([
            'username' => $username,
            'password' => password_hash($password, PASSWORD_DEFAULT),
            'role' => $role
        ]);
    }
}
?>

⚠️ Seguridad: Siempre usa prepare() y execute() con parámetros nombrados para prevenir inyección SQL. NUNCA concatenes variables directamente en SQL.

4.5 Controladores - Lógica de la Aplicación

<?php
class userController {
    private $userRepo;
    
    public function __construct() {
        $this->userRepo = new UserRepositori();
    }
    
    // Mostrar formulario de login
    public function login() {
        require_once 'views/loginView.phtml';
    }
    
    // Procesar login
    public function authenticate() {
        // Obtener datos del formulario
        $username = $_POST['username'] ?? '';
        $password = $_POST['password'] ?? '';
        
        // Buscar usuario en la base de datos
        $user = $this->userRepo->findByUsername($username);
        
        // Verificar si existe y la contraseña es correcta
        if ($user && password_verify($password, $user->getPassword())) {
            // Guardar datos en sesión
            $_SESSION['user_id'] = $user->getId();
            $_SESSION['username'] = $user->getUsername();
            $_SESSION['role'] = $user->getRole();
            
            // Redirigir al blog
            header('Location: index.php?c=main');
            exit;
        } else {
            // Login fallido
            $error = "Usuario o contraseña incorrectos";
            require_once 'views/loginView.phtml';
        }
    }
}
?>

4.6 Vistas - Presentación HTML

<!DOCTYPE html>
<html>
<head>
    <title>Login</title>
</head>
<body>
    <h1>Iniciar Sesión</h1>
    
    <?php if (isset($error)): ?>
        <p style="color: red;"><?= $error ?></p>
    <?php endif; ?>
    
    <form method="POST" action="index.php?c=user&action=authenticate">
        <label>Usuario:</label>
        <input type="text" name="username" required>
        
        <label>Contraseña:</label>
        <input type="password" name="password" required>
        
        <button type="submit">Entrar</button>
    </form>
</body>
</html>

5. Conceptos Importantes

5.1 Sesiones en PHP

Las sesiones permiten mantener información del usuario entre diferentes páginas:

<?php
// Iniciar sesión (siempre al principio)
session_start();

// Guardar datos en sesión
$_SESSION['user_id'] = 1;
$_SESSION['username'] = 'juan';

// Leer datos de sesión
$userId = $_SESSION['user_id'];

// Verificar si existe un dato
if (isset($_SESSION['user_id'])) {
    echo "Usuario logueado";
}

// Destruir sesión (logout)
session_destroy();
?>

5.2 Superglobales de PHP

Variable Descripción Ejemplo


$_GET Datos de la URL index.php?id=5 → $_GET['id'] $_POST Datos de formularios <input name="email"> → $_POST['email'] $_SESSION Datos de sesión $_SESSION['user_id'] $_SERVER Info del servidor $_SERVER['REQUEST_METHOD'] $_FILES Archivos subidos $_FILES['imagen']

5.3 PDO - PHP Data Objects

PDO es la forma moderna y segura de trabajar con bases de datos en PHP:

<?php
// Conectar
$pdo = new PDO("mysql:host=localhost;dbname=blog", "root", "");

// Consulta preparada (SEGURA)
$stmt = $pdo->prepare("SELECT * FROM user WHERE id = :id");
$stmt->execute(['id' => $userId]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

// Insertar datos
$stmt = $pdo->prepare("INSERT INTO post (title, content) VALUES (:title, :content)");
$stmt->execute([
    'title' => $title,
    'content' => $content
]);

// Obtener ID del último registro insertado
$lastId = $pdo->lastInsertId();
?>

5.4 Sistema de Roles

El sistema de roles controla qué puede hacer cada usuario:

<?php
// Verificar si el usuario está logueado
function isLoggedIn() {
    return isset($_SESSION['user_id']);
}

// Verificar si es administrador
function isAdmin() {
    return isset($_SESSION['role']) && $_SESSION['role'] === 'admin';
}

// Verificar si puede eliminar un post
function canDeletePost($postAuthorId) {
    // Admin puede eliminar cualquier post
    if (isAdmin()) {
        return true;
    }
    
    // Usuario puede eliminar solo sus propios posts
    return isset($_SESSION['user_id']) && 
           $_SESSION['user_id'] == $postAuthorId;
}

// Uso en el controlador
if (!canDeletePost($post->getUserId())) {
    die("No tienes permiso para eliminar este post");
}
?>

6. Seguridad en PHP

6.1 Prevención de Inyección SQL

❌ MAL (vulnerable):

$sql = "SELECT * FROM user WHERE username = '$username'";
$result = $pdo->query($sql);

✅ BIEN (seguro):

$stmt = $pdo->prepare("SELECT * FROM user WHERE username = :username");
$stmt->execute(['username' => $username]);

6.2 Hashing de Contraseñas

<?php
// Al registrar: hashear la contraseña
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);

// Al hacer login: verificar la contraseña
if (password_verify($passwordIngresada, $hashedPasswordBD)) {
    echo "Contraseña correcta";
}
?>

6.3 Validación de Datos

<?php
// Validar que no esté vacío
if (empty($_POST['username'])) {
    die("El username es requerido");
}

// Validar longitud
if (strlen($_POST['username']) < 3) {
    die("El username debe tener al menos 3 caracteres");
}

// Sanitizar HTML (prevenir XSS)
$username = htmlspecialchars($_POST['username']);

// Validar email
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
    die("Email inválido");
}
?>

7. Cómo Leer y Entender Código PHP

7.1 Estrategia de Lectura

  1. Empieza por index.php: Es el punto de entrada, entiende cómo se enrutan las peticiones
  2. Sigue el flujo: URL → Controlador → Modelo → Vista
  3. Lee los nombres: Los nombres de clases, métodos y variables deben ser descriptivos
  4. Busca patrones: Los repositorios siempre tienen métodos similares (find, create, update, delete)
  5. Entiende las relaciones: ¿Qué clases usan otras clases?

7.2 Preguntas para Entender Código

  • ¿Qué hace este método? (lee el nombre y los comentarios)
  • ¿Qué datos recibe? (parámetros)
  • ¿Qué datos devuelve? (return)
  • ¿Qué otras clases/métodos usa?
  • ¿Hay validaciones o comprobaciones?
  • ¿Hay manejo de errores?

7.3 Ejemplo de Análisis de Código

<?php
public function create() {
    // 1. ¿Qué hace? Crea un nuevo post
    
    // 2. Verifica si el usuario está logueado
    if (!isset($_SESSION['user_id'])) {
        header('Location: index.php?c=user&action=login');
        exit;
    }
    
    // 3. Si es GET, muestra el formulario
    if ($_SERVER['REQUEST_METHOD'] === 'GET') {
        require_once 'views/createPostView.phtml';
        return;
    }
    
    // 4. Si es POST, procesa el formulario
    $title = $_POST['title'] ?? '';
    $content = $_POST['content'] ?? '';
    $userId = $_SESSION['user_id'];
    
    // 5. Valida los datos
    if (empty($title) || empty($content)) {
        $error = "Todos los campos son requeridos";
        require_once 'views/createPostView.phtml';
        return;
    }
    
    // 6. Guarda en la base de datos
    $this->postRepo->create($title, $content, $userId);
    
    // 7. Redirige al blog
    header('Location: index.php?c=main');
    exit;
}
?>

8. Ejercicios Prácticos

Ejercicio 1: Agregar un campo "email" a los usuarios

  1. Modifica la tabla user en SQL para agregar el campo email
  2. Actualiza la clase User para incluir la propiedad email
  3. Modifica UserRepositori para guardar y recuperar el email
  4. Actualiza el formulario de registro para pedir el email

Ejercicio 2: Agregar edición de posts

  1. Crea un método edit() en postController
  2. Crea un método update() en PostRepository
  3. Crea una vista editPostView.phtml
  4. Agrega un botón "Editar" en blogView.phtml
  5. Verifica que solo el autor o admin puedan editar

Ejercicio 3: Agregar paginación al blog

  1. Modifica getAllPosts() para aceptar límite y offset
  2. Usa LIMIT y OFFSET en la consulta SQL
  3. Agrega botones "Anterior" y "Siguiente" en la vista

9. Recursos Adicionales

Documentación Oficial

Conceptos para Seguir Aprendiendo

  • Composer (gestor de dependencias)
  • Namespaces en PHP
  • Autoloading de clases
  • Manejo de excepciones (try-catch)
  • APIs REST con PHP
  • Frameworks PHP (Laravel, Symfony)

10. Glosario de Términos

Término Definición


MVC Patrón de diseño que separa datos, lógica y presentación PDO Interfaz para acceder a bases de datos de forma segura OOP Programación Orientada a Objetos CRUD Create, Read, Update, Delete (operaciones básicas de BD) Sesión Mecanismo para mantener datos del usuario entre páginas Hash Transformación irreversible de datos (ej: contraseñas) Inyección SQL Ataque que inserta código SQL malicioso XSS Cross-Site Scripting, ataque que inyecta JavaScript Repository Patrón que encapsula el acceso a datos Singleton Patrón que garantiza una única instancia de una clase

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published