PATRÓN REPOSITORY EN PHP: QUÉ ES Y CÓMO IMPLEMENTARLO
En este post se muestra un ejemplo del Patrón Repository en PHP.
Estructura de carpetas recomendada
src/
├── Domain/
│ └── User.php
├── Infrastructure/
│ └── Persistence/
│ ├── UserRepository.php
│ └── UserRepositoryInterface.php
└── index.php
Entidad (Domain)
// src/Domain/User.php
namespace App\Domain;
class User
{
public function __construct(
public readonly ?int $id,
public string $name,
public string $email
) {}
}
Interfaz del Repository
// src/Infrastructure/Persistence/UserRepositoryInterface.php
namespace App\Infrastructure\Persistence;
use App\Domain\User;
interface UserRepositoryInterface
{
public function findById(int $id): ?User;
public function findAll(): array;
public function save(User $user): void;
public function delete(int $id): bool;
}
Implementación con MySQL (PDO)
// src/Infrastructure/Persistence/UserRepository.php
namespace App\Infrastructure\Persistence;
use App\Domain\User;
use PDO;
use PDOException;
class UserRepository implements UserRepositoryInterface
{
private PDO $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function findById(int $id): ?User
{
$stmt = $this->db->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $id]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$data) {
return null;
}
return new User(
(int)$data['id'],
$data['name'],
$data['email']
);
}
public function findAll(): array
{
$stmt = $this->db->query("SELECT * FROM users");
$users = [];
while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
$users[] = new User(
(int)$data['id'],
$data['name'],
$data['email']
);
}
return $users;
}
public function save(User $user): void
{
if ($user->id === null) {
// Insertar nuevo usuario
$stmt = $this->db->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
$stmt->execute([
'name' => $user->name,
'email' => $user->email
]);
} else {
// Actualizar usuario existente
$stmt = $this->db->prepare("UPDATE users SET name = :name, email = :email WHERE id = :id");
$stmt->execute([
'id' => $user->id,
'name' => $user->name,
'email' => $user->email
]);
}
}
public function delete(int $id): bool
{
$stmt = $this->db->prepare("DELETE FROM users WHERE id = :id");
return $stmt->execute(['id' => $id]);
}
}
Uso (index.php)
// index.php
require_once __DIR__ . '/vendor/autoload.php'; //Si se usaComposer
use App\Domain\User;
use App\Infrastructure\Persistence\UserRepository;
use PDO;
// Configuración de la base de datos
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=mi_app;charset=utf8mb4',
'root', // usuario
'', // contraseña
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
} catch (PDOException $e) {
die("Error de conexión: " . $e->getMessage());
}
// Crear el Repository
$repository = new UserRepository($pdo);
// === Ejemplos de uso ===
// Crear usuario
$newUser = new User(null, "Carlos Ramírez", "carlos@example.com");
$repository->save($newUser);
echo "Usuario guardado correctamente!
";
// Buscar por ID
$user = $repository->findById(1);
if ($user) {
echo "Usuario encontrado: {$user->name} - {$user->email}
";
}
// Listar todos
echo "Todos los usuarios:";
foreach ($repository->findAll() as $u) {
echo "- {$u->name} ({$u->email})
";
}
Tabla en MySQL
CREATE DATABASE mi_app CHARACTER SET utf8mb4;
USE mi_app;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);