PHPackages                             miguelex/php-template - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. miguelex/php-template

ActiveProject[Testing &amp; Quality](/categories/testing)

miguelex/php-template
=====================

PHP 8.2 MVC template with PHPStan, Pest, Gulp/Vite and AI agent support

v1.0.4(1mo ago)20MITPHPPHP ^8.2CI passing

Since May 4Pushed 1mo agoCompare

[ Source](https://github.com/miguelex/php-template)[ Packagist](https://packagist.org/packages/miguelex/php-template)[ RSS](/packages/miguelex-php-template/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (9)Versions (6)Used By (0)

php-template
============

[](#php-template)

Plantilla base para proyectos PHP 8.2 con arquitectura MVC, tooling moderno y soporte para desarrollo con agentes IA.

[![CI](https://github.com/miguelex/php-template/actions/workflows/ci.yml/badge.svg)](https://github.com/miguelex/php-template/actions)[![PHP](https://camo.githubusercontent.com/3f99b197569aa2dcfbefff17ecc68d74098e7f929d8b52dc40f3a898f740eae1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d3737374242343f6c6f676f3d706870)](https://php.net)[![License: MIT](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](LICENSE)

> 🇬🇧 [English README](README.en.md)

---

¿Qué incluye?
-------------

[](#qué-incluye)

### 🏗 Arquitectura MVC

[](#-arquitectura-mvc)

- **Router** — registro de rutas GET/POST/PUT/PATCH/DELETE, soporte `_method` override, middleware global, manejo de 404/500
- **ActiveRecord** — ORM ligero sobre PDO con prepared statements, `find`, `where`, `save`, `delete`, validación, alertas
- **EmailService** — envío SMTP vía PHPMailer con templates HTML base
- **Html helper** — escape seguro, CSRF, alertas en vista, dump de debug

### ✅ Calidad de código PHP

[](#-calidad-de-código-php)

- **PHPStan** nivel 6 — análisis estático
- **PHP\_CodeSniffer** — PSR-12
- **PHP-CS-Fixer** — autocorrección de estilo
- **PHPUnit 11** + **Pest 3** — tests unitarios, integración y feature

### ⚡ Frontend (modo `fullstack`)

[](#-frontend-modo-fullstack)

Dos opciones de bundler, elige la que prefieras:

**Gulp****Vite**Ideal paraJS vanilla, proyectos sin módulosProyectos con imports/exports, HMRSCSS → CSS✅✅Imágenes WebP + optimización✅✅ (plugin)BrowserSync / HMRBrowserSyncHMR nativoConfiguración`gulpfile.js``vite.config.js`Linting y tests front:

- **ESLint** + **Stylelint**
- **Vitest** — tests unitarios JS
- **Playwright** — tests E2E

### 🤖 Preparado para agentes IA

[](#-preparado-para-agentes-ia)

Ficheros `.agent/` leídos automáticamente por Claude Code, Cursor y similares:

- `AGENTS.md` — permisos, restricciones, comandos disponibles
- `CONVENTIONS.md` — PSR-12, BEM, Conventional Commits
- `PROJECT.md` — contexto de negocio (rellenar por proyecto)
- `TASKS.md` — backlog de tareas

### 🔄 CI/CD

[](#-cicd)

GitHub Actions con dos jobs paralelos: PHP QA (PHPStan + PHPCS + PHPUnit + Pest) y Front QA (ESLint + Stylelint + Vitest + Playwright).

---

Requisitos
----------

[](#requisitos)

HerramientaVersión mínimaNotasPHP8.2`php --version`Composer2.x`composer --version`Node.js20 LTSSolo modo `fullstack`npm10+Solo modo `fullstack`Gitcualquiera### Windows

[](#windows)

- Instalar PHP desde [windows.php.net](https://windows.php.net/download/) o via **Laragon** / **XAMPP**
- Instalar Node.js desde [nodejs.org](https://nodejs.org)
- Añadir PHP y Composer al PATH
- El script `dev.sh` requiere WSL o Git Bash; alternativamente usar `npm run dev` directamente

### WSL (Windows Subsystem for Linux)

[](#wsl-windows-subsystem-for-linux)

```
# PHP 8.2
sudo apt update && sudo apt install php8.2 php8.2-mbstring php8.2-xml php8.2-curl

# Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

# Node.js via nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install 20 && nvm use 20
```

### macOS

[](#macos)

```
brew install php composer node@20
```

### Linux (Ubuntu/Debian)

[](#linux-ubuntudebian)

```
sudo apt install php8.2 php8.2-mbstring php8.2-xml php8.2-curl
composer # desde getcomposer.org
nvm install 20
```

---

Crear un nuevo proyecto
-----------------------

[](#crear-un-nuevo-proyecto)

### Opción A — Clonar y usar el script `init-project.sh`

[](#opción-a--clonar-y-usar-el-script-init-projectsh)

```
git clone https://github.com/miguelex/php-template.git
cd php-template
./init-project.sh
```

El script es interactivo y pregunta:

1. **Nombre del proyecto** (se usará como nombre de directorio y en composer/package.json)
2. **Modo**: `backend-only` o `fullstack`

También acepta argumentos directos:

```
./init-project.sh mi-api      backend   # API PHP sin front
./init-project.sh mi-web      full      # Web completa con assets
```

El script genera `./mi-proyecto/` con:

- Git inicializado (commit inicial limpio, sin historia de la plantilla)
- Ficheros personalizados con el nombre del proyecto
- Modo `backend` elimina automáticamente gulpfile, vite.config, tests/front, etc.

### Opción B — Fork en GitHub

[](#opción-b--fork-en-github)

1. Hacer fork del repositorio
2. Clonar tu fork: `git clone https://github.com/TU_USER/php-template.git mi-proyecto`
3. Eliminar la historia: `rm -rf .git && git init && git add . && git commit -m "chore: init"`
4. Ajustar manualmente `composer.json` y `package.json`

---

Instalación (tras crear el proyecto)
------------------------------------

[](#instalación-tras-crear-el-proyecto)

```
cd mi-proyecto

# Dependencias PHP (copia .env.example a .env automáticamente)
composer install

# Dependencias Node (solo fullstack)
npm install

# Instalar navegadores para Playwright (solo fullstack)
npx playwright install chromium
```

Editar `.env` con los valores reales del proyecto:

```
APP_NAME="Mi Proyecto"
APP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost:8000

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=mi_base_de_datos
DB_USERNAME=root
DB_PASSWORD=
```

---

Desarrollo
----------

[](#desarrollo)

### Arrancar el entorno

[](#arrancar-el-entorno)

**Opción 1 — `concurrently` (recomendado en Windows/WSL sin tmux)**

```
# Gulp + PHP server en una sola terminal
npm run dev

# Vite + PHP server en una sola terminal
npm run dev:vite

# Solo servidor PHP (backend-only)
npm run php
```

Cada proceso aparece con prefijo de color: `[PHP]` en azul, `[GULP]`/`[VITE]` en verde/amarillo.

**Opción 2 — `dev.sh` con tmux (Linux/macOS/WSL)**

```
./dev.sh                  # Gulp + PHP (paneles separados en tmux)
./dev.sh --bundler=vite   # Vite + PHP
./dev.sh --php-only       # Solo PHP (backend)
./dev.sh --tests          # Gulp + PHP + Vitest watch
```

Atajos tmux: `Ctrl+B → flechas` para moverse entre paneles · `Ctrl+B → D` para desconectar · `tmux attach -t dev` para reconectar.

**Opción 3 — Terminales manuales**

```
# Terminal 1
php -S localhost:8000 -t public

# Terminal 2 (fullstack Gulp)
npx gulp watch

# Terminal 2 (fullstack Vite)
npx vite
```

### Compilar assets

[](#compilar-assets)

```
# Desarrollo (sourcemaps, sin minificar)
npm run build          # Gulp
npm run build:vite     # Vite

# Producción (minificado, optimizado)
npm run build:prod          # Gulp
npm run build:vite:prod     # Vite
```

---

Comandos de calidad
-------------------

[](#comandos-de-calidad)

### PHP

[](#php)

```
composer qa           # Todo: lint + stan + tests (pasar antes de cada commit)
composer lint         # PHPCS — detecta problemas de estilo
composer lint:fix     # PHP-CS-Fixer — autocorrige el estilo
composer stan         # PHPStan — análisis estático nivel 6
composer test         # PHPUnit
composer test:pest    # Pest
composer test:cover   # PHPUnit + coverage HTML en storage/coverage/
```

### Front (fullstack)

[](#front-fullstack)

```
npm run test          # Vitest unit
npm run test:watch    # Vitest en modo watch
npm run test:e2e      # Playwright E2E (requiere servidor PHP activo)
npm run test:all      # Vitest + Playwright
npm run lint:js       # ESLint
npm run lint:css      # Stylelint
npm run lint:fix      # ESLint --fix
npm run format        # Prettier
```

---

Estructura del proyecto
-----------------------

[](#estructura-del-proyecto)

```
php-template/
├── .agent/                        ← Contexto para agentes IA
│   ├── AGENTS.md                  ← Instrucciones, permisos, comandos
│   ├── CONVENTIONS.md             ← Convenciones de código
│   ├── PROJECT.md                 ← Contexto de negocio (rellenar)
│   └── TASKS.md                   ← Backlog de tareas
│
├── .github/workflows/ci.yml       ← GitHub Actions (PHP QA + Front QA)
│
├── src/                           ← Código fuente PHP
│   ├── Core/
│   │   ├── App.php                ← Bootstrap (env, config, BD)
│   │   ├── Router.php             ← Router MVC
│   │   ├── ActiveRecord.php       ← ORM base con PDO
│   │   └── Database.php           ← Conexión PDO (singleton)
│   ├── Controllers/               ← HTTP handlers
│   ├── Models/                    ← Entidades (extienden ActiveRecord)
│   │   └── User.php               ← Modelo de ejemplo
│   ├── Services/
│   │   └── EmailService.php       ← SMTP con PHPMailer
│   ├── Helpers/
│   │   └── Html.php               ← Escape, CSRF, alertas, dump
│   └── Exceptions/
│       ├── RouteNotFoundException.php
│       └── DatabaseException.php
│
├── views/                         ← Vistas PHP
│   ├── layouts/default.php        ← Layout base
│   ├── templates/
│   │   ├── header.php
│   │   └── footer.php
│   ├── errors/
│   │   ├── 404.php
│   │   └── 500.php
│   └── home.php                   ← Vista de ejemplo
│
├── config/
│   └── routes.php                 ← Definición de rutas
│
├── public/                        ← Document root del servidor web
│   ├── index.php                  ← Entry point
│   └── assets/                    ← Generado por Gulp/Vite (no editar)
│
├── resources/                     ← Fuentes front (solo fullstack)
│   ├── scss/
│   │   ├── app.scss
│   │   ├── _variables.scss
│   │   ├── _mixins.scss
│   │   ├── _base.scss
│   │   └── components/
│   └── js/
│       ├── app.js
│       └── modules/
│
├── tests/
│   ├── TestCase.php               ← Base para PHPUnit/Pest
│   ├── Unit/                      ← Tests unitarios PHPUnit
│   ├── Integration/               ← Tests de integración
│   ├── Feature/                   ← Tests Pest
│   └── front/                     ← Solo fullstack
│       ├── unit/                  ← Vitest
│       └── e2e/                   ← Playwright
│
├── database/
│   ├── migrations/
│   └── seeders/
│
├── storage/
│   ├── logs/
│   └── cache/
│
├── composer.json
├── phpstan.neon                   ← Nivel 6
├── phpcs.xml                      ← PSR-12
├── .php-cs-fixer.php
├── phpunit.xml
├── pest.php
├── gulpfile.js                    ← Bundler opción A
├── vite.config.js                 ← Bundler opción B
├── package.json
├── vitest.config.js
├── playwright.config.js
├── eslint.config.js
├── .stylelintrc.json
├── .editorconfig
├── .gitignore
├── .env.example
├── dev.sh                         ← Lanzador tmux
└── init-project.sh                ← Script de inicialización

```

---

Decisiones de diseño
--------------------

[](#decisiones-de-diseño)

**¿Por qué sin framework como Laravel/Symfony?**Para proyectos donde el overhead de un framework completo no está justificado: módulos de negocio específicos, integraciones con sistemas legacy, o proyectos donde el control fino sobre cada capa es importante.

**¿Gulp o Vite?**Ambos están disponibles. Gulp es ideal si el JS es simple (unas funciones, jQuery): pipeline directo, sin módulos, sin bundling. Vite es mejor si empiezas a usar `import/export`, necesitas HMR instantáneo, o prevés que el front crezca.

**¿Por qué PHPStan nivel 6 y no 9?**El nivel 9 en un proyecto real con código legacy o integraciones externas genera decenas de falsos positivos. El 6 ofrece el 90% del valor sin el ruido. Se puede subir gradualmente.

**ActiveRecord vs Repository**Para proyectos pequeños/medianos ActiveRecord es más directo. Si el dominio crece, el patrón Repository es el paso siguiente: extraer la lógica de acceso a datos de los modelos a clases `UserRepository`, etc.

---

Contribuir
----------

[](#contribuir)

¡Las contribuciones son bienvenidas! Esto incluye mejoras al core MVC, nuevas features de tooling, correcciones, documentación o ejemplos adicionales.

### Antes de abrir un PR

[](#antes-de-abrir-un-pr)

1. Haz **fork** del repositorio y clona tu fork
2. Crea una rama descriptiva: ```
    git checkout -b feature/nombre-corto
    # o
    git checkout -b fix/descripcion-del-bug
    ```
3. Asegúrate de que **`composer qa` pasa en verde** antes de hacer push
4. Si añades código PHP, añade también sus tests
5. Sigue las convenciones de [Conventional Commits](https://www.conventionalcommits.org/): ```
    feat: añadir soporte para rutas con parámetros dinámicos
    fix: corregir resolución de URI con query string
    chore: actualizar dependencias Composer
    docs: mejorar sección de contribución en README
    test: añadir tests para ActiveRecord::whereMany

    ```

### Tipos de contribución bienvenidas

[](#tipos-de-contribución-bienvenidas)

- 🐛 **Bug fixes** — con test que reproduzca el fallo
- ✨ **Features** — discutir primero en un issue si es algo grande
- 📖 **Documentación** — mejoras al README, comentarios en código
- 🧪 **Tests** — más cobertura siempre es bienvenida
- 🌐 **Compatibilidad** — mejoras para Windows, macOS, distintas versiones de PHP

### Tipos de contribución que no encajan

[](#tipos-de-contribución-que-no-encajan)

- Añadir dependencias de frameworks completos (Laravel, Symfony, etc.)
- Cambios de estilo sin funcionalidad asociada
- Romper compatibilidad con PHP 8.2

### Flujo de un PR

[](#flujo-de-un-pr)

```
fork → rama → código + tests → composer qa verde → push → PR

```

En el PR describe:

- **Qué** hace el cambio
- **Por qué** es necesario
- **Cómo** probarlo

---

Licencia
--------

[](#licencia)

MIT — ver [LICENSE](LICENSE).

---

Agradecimientos
---------------

[](#agradecimientos)

Inspirado en el mini-framework de [codigoconjuan](https://codigoconjuan.com), modernizado con PHP 8.2, PDO, typed properties y tooling actual.

---

CLI — bin/console
-----------------

[](#cli--binconsole)

La plantilla incluye una herramienta de línea de comandos para las tareas más comunes:

```
# Migraciones
php bin/console migrate               # ejecutar pendientes
php bin/console migrate:status        # ver estado
php bin/console migrate:rollback      # deshacer última
php bin/console migrate:rollback 3    # deshacer últimas 3
php bin/console migrate:fresh         # rollback todo + migrate

# Generadores de código
php bin/console make:migration create_posts_table
php bin/console make:controller Post
php bin/console make:model Post
php bin/console make:repository Post

# Otros
php bin/console cache:clear
php bin/console help
```

O con Make:

```
make migrate
make migration NAME=create_posts_table
make controller NAME=Post
make model NAME=Post
```

---

Patrones disponibles: ActiveRecord vs Repository
------------------------------------------------

[](#patrones-disponibles-activerecord-vs-repository)

### ActiveRecord — para proyectos simples/medianos

[](#activerecord--para-proyectos-simplesmedianos)

```
// src/Models/Post.php
final class Post extends ActiveRecord {
    protected static string $table = 'posts';
    protected static array $columns = ['id', 'title', 'body'];
    public string $title = '';
    public string $body  = '';
}

// Uso directo
$post = Post::find(1);
$posts = Post::all();
$post->title = 'Nuevo título';
$post->save();
```

### Repository — para proyectos con dominio complejo

[](#repository--para-proyectos-con-dominio-complejo)

```
// src/Repositories/PostRepository.php
final class PostRepository extends BaseRepository {
    protected string $table = 'posts';

    public function findPublished(): array {
        return $this->findWhere(['published' => 1], 'created_at DESC');
    }

    protected function hydrate(array $row): Post { ... }
    protected function extract(object $entity): array { ... }
}

// Uso con inyección
$repo = new PostRepository(Database::connect());
$posts = $repo->paginate(page: 1, perPage: 10);
```

---

Makefile
--------

[](#makefile)

```
make help           # ver todos los comandos disponibles
make install        # composer install + npm install
make dev            # PHP + Gulp (concurrently)
make dev-vite       # PHP + Vite (concurrently)
make qa             # lint + stan + tests
make test-all       # PHP + JS + E2E
make migrate        # ejecutar migraciones
make cache-clear    # vaciar storage/cache/
```

En **Windows** sin WSL, instalar `make` con:

```
winget install GnuWin32.Make
# o
choco install make
```

---

Sistema de agentes IA — estructura completa
-------------------------------------------

[](#sistema-de-agentes-ia--estructura-completa)

```
.agent/
├── AGENTS.md        ← Punto de entrada: qué es el proyecto, permisos, comandos
├── WORKFLOW.md      ← Cómo actuar: planificar, verificar, aprender, elegancia
├── CONVENTIONS.md   ← Cómo escribir: PHP, JS, SCSS, Git, nomenclatura
├── PROJECT.md       ← Contexto de negocio (rellenar por proyecto)
└── TASKS.md         ← Backlog estratégico del proyecto

tasks/
├── todo.md          ← Tarea activa: plan + checkboxes + review section
└── lessons.md       ← Errores pasados + reglas para no repetirlos

```

Los agentes que leen `AGENTS.md` de forma nativa (Claude Code, Cursor en modo agente) cargan automáticamente todo el contexto. El fichero `WORKFLOW.md` garantiza que el agente planifica antes de actuar, hace cambios quirúrgicos, y aprende de los errores del proyecto.

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance93

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

5

Last Release

36d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/dfecdb31d15d47273599e5edf5088a8eab9abffe9d79a31e78013be357d6cc8b?d=identicon)[miguelex](/maintainers/miguelex)

---

Top Contributors

[![migueAsinco](https://avatars.githubusercontent.com/u/124771270?v=4)](https://github.com/migueAsinco "migueAsinco (7 commits)")

---

Tags

ai-agentgulpmvcpestphpphp8phpstanphpunittemplatevitephppestPHPStantemplatemvcvitegulp

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/miguelex-php-template/health.svg)

```
[![Health](https://phpackages.com/badges/miguelex-php-template/health.svg)](https://phpackages.com/packages/miguelex-php-template)
```

###  Alternatives

[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k51.0M7.4k](/packages/larastan-larastan)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
