Estandares PSR
Los PSR (PHP Standard Recommendations) son estandares desarrollados por el PHP-FIG (Framework Interoperability Group) para que todo el codigo PHP siga las mismas convenciones. Seguir estos estandares hace tu codigo mas legible y compatible con las librerias del ecosistema PHP.
¿Qué es el PHP-FIG?
El PHP Framework Interoperability Group es un grupo formado por representantes de los principales frameworks y proyectos PHP (Laravel, Symfony, Drupal, etc.). Su objetivo es crear estandares comunes para que el codigo sea interoperable entre proyectos.
Los PSR mas importantes para el dia a dia son:
- PSR-1: Estándar básico de codificación
- PSR-4: Autoloading (ya lo vimos en la leccion de Composer)
- PSR-12: Guia de estilo extendida
PSR-1: Estandar basico
Define las reglas fundamentales que todo codigo PHP debe seguir:
Archivos
- Solo usar las etiquetas
<?phpo<?= - Codificacion UTF-8 sin BOM
- Un archivo debe declarar símbolos (clases, funciones) O ejecutar código, no ambos
<?php
// INCORRECTO: mezcla declaracion con ejecucion
declare(strict_types=1);
class Usuario
{
public function __construct(
public readonly string $nombre
) {}
}
// Esto no deberia estar aqui
$usuario = new Usuario('Ana');
echo $usuario->nombre;
<?php
// CORRECTO: archivo src/Usuario.php (solo declaracion)
declare(strict_types=1);
namespace App;
class Usuario
{
public function __construct(
public readonly string $nombre
) {}
}
<?php
// CORRECTO: archivo index.php (solo ejecucion)
declare(strict_types=1);
require_once 'vendor/autoload.php';
use App\Usuario;
$usuario = new Usuario('Ana');
echo $usuario->nombre;
Nombres
- Clases: PascalCase (
MiClase,ControladorUsuario) - Constantes de clase: MAYUSCULAS_CON_GUIONES (
MAX_INTENTOS) - Metodos: camelCase (
obtenerNombre,calcularTotal)
<?php
declare(strict_types=1);
namespace App\Servicios;
class GestorPedidos // PascalCase
{
public const MAX_ITEMS_POR_PEDIDO = 100; // MAYUSCULAS
public function crearPedido(array $items): Pedido // camelCase
{
// ...
}
public function calcularTotal(Pedido $pedido): float
{
// ...
}
}
PSR-12: Guia de estilo
PSR-12 extiende PSR-1 con reglas detalladas sobre formato y estilo:
Estructura de archivos
<?php
// 1. Etiqueta de apertura
// 2. declare (si lo hay)
declare(strict_types=1);
// 3. namespace
namespace App\Controladores;
// 4. imports (use) - uno por linea, ordenados
use App\Entidades\Usuario;
use App\Repositorios\UsuarioRepositorio;
use App\Servicios\EmailService;
// 5. Declaracion de clase
class UsuarioControlador
{
// Contenido...
}
Indentacion y lineas
- Usar 4 espacios (no tabs)
- Maximo 120 caracteres por linea (recomendado 80)
- Una linea en blanco al final del archivo
- No dejar espacios en blanco al final de las lineas
Llaves y espacios
<?php
declare(strict_types=1);
namespace App;
// Llave de apertura en nueva linea para clases
class Calculadora
{
// Llave de apertura en nueva linea para metodos
public function sumar(int $a, int $b): int
{
return $a + $b;
}
// Estructuras de control: llave en la misma linea
public function esPar(int $numero): bool
{
if ($numero % 2 === 0) {
return true;
} else {
return false;
}
}
// Ejemplo con switch
public function obtenerDia(int $numero): string
{
switch ($numero) {
case 1:
return 'Lunes';
case 2:
return 'Martes';
default:
return 'Desconocido';
}
}
}
Metodos y funciones
<?php
declare(strict_types=1);
namespace App;
class Servicio
{
// Sin espacio entre nombre de metodo y parentesis
// Espacio despues de cada coma en parametros
public function procesar(string $dato, int $limite): array
{
// ...
}
// Parametros en multiples lineas cuando son muchos
public function crearUsuario(
string $nombre,
string $email,
string $password,
?string $telefono = null
): Usuario {
// ...
}
// Visibilidad siempre explicita
private function metodoPrivado(): void
{
// ...
}
}
Orden de visibilidad
<?php
declare(strict_types=1);
namespace App;
// Orden de modificadores: abstract/final, visibilidad, static, readonly
abstract class ClaseBase
{
// Primero constantes
public const VERSION = '1.0';
private const LIMITE = 100;
// Luego propiedades
public readonly string $id;
protected static int $contador = 0;
private array $datos = [];
// Finalmente metodos
abstract public function procesar(): void;
final protected static function incrementar(): void
{
self::$contador++;
}
}
Herramientas automaticas
No tienes que verificar manualmente que tu codigo cumple PSR-12. Existen herramientas que lo hacen automaticamente:
PHP-CS-Fixer
# Instalar como dependencia de desarrollo
composer require --dev friendsofphp/php-cs-fixer
# Ejecutar para ver problemas
./vendor/bin/php-cs-fixer fix src --dry-run --diff
# Ejecutar para corregir automaticamente
./vendor/bin/php-cs-fixer fix src
Crea un archivo .php-cs-fixer.php en la raiz del proyecto:
<?php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests');
return (new PhpCsFixer\Config())
->setRules([
'@PSR12' => true,
'strict_param' => true,
'declare_strict_types' => true,
])
->setFinder($finder)
->setRiskyAllowed(true);
PHP_CodeSniffer
# Instalar
composer require --dev squizlabs/php_codesniffer
# Verificar codigo contra PSR-12
./vendor/bin/phpcs --standard=PSR12 src
# Corregir automaticamente lo posible
./vendor/bin/phpcbf --standard=PSR12 src
PSR-4: Recordatorio
Ya vimos PSR-4 en detalle en la leccion de Composer. Es el estandar para autoloading que mapea namespaces a directorios:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
App\Servicios\EmailService → src/Servicios/EmailService.php
Ejercicios
Ejercicio 1: Corregir codigo
El siguiente codigo tiene varios errores de estilo segun PSR-12. Identifica y corrige al menos 5 problemas:
<?php
namespace app\servicios;
use App\Usuario;
use App\Email;
class gestorUsuarios{
const max_usuarios=100;
function CrearUsuario($nombre,$email){
if($nombre==''){
return null;
}
else{
return new Usuario($nombre,$email);
}
}
}
Ver solucion
<?php
declare(strict_types=1); // 1. Faltaba declare
namespace App\Servicios; // 2. Namespace en PascalCase
use App\Email; // 3. Linea en blanco antes de use
use App\Usuario; // 4. Un use por linea, ordenados
class GestorUsuarios // 5. Clase en PascalCase, llave en nueva linea
{
public const MAX_USUARIOS = 100; // 6. Visibilidad, MAYUSCULAS
public function crearUsuario(string $nombre, string $email): ?Usuario // 7. Visibilidad, camelCase, tipos, espacios
{
if ($nombre === '') { // 8. Espacio despues de if, ===
return null;
}
return new Usuario($nombre, $email); // 9. Sin else innecesario
}
}
Problemas corregidos:
- Faltaba
declare(strict_types=1) - Namespace debe ser PascalCase:
App\Servicios - Linea en blanco entre namespace y use
- Use en lineas separadas y ordenados alfabeticamente
- Clase en PascalCase, llave de apertura en nueva linea
- Constante con visibilidad explicita y MAYUSCULAS
- Metodo con visibilidad, camelCase, type hints y espacios despues de comas
- Espacio entre
ify parentesis, comparacion estricta - Else innecesario eliminado (early return)
Ejercicio 2: Estructura de clase
Crea una clase Producto en el namespace App\Entidades
que cumpla PSR-12. Debe tener:
- Una constante
IVAcon valor 0.21 - Propiedades
nombre(string) yprecio(float) - Constructor con property promotion
- Metodo
calcularPrecioConIva
Ver solucion
<?php
declare(strict_types=1);
namespace App\Entidades;
class Producto
{
public const IVA = 0.21;
public function __construct(
public readonly string $nombre,
public readonly float $precio
) {}
public function calcularPrecioConIva(): float
{
return $this->precio * (1 + self::IVA);
}
}
Ejercicio 3: Configurar PHP-CS-Fixer
Escribe un archivo .php-cs-fixer.php que:
- Use las reglas de PSR-12
- Busque archivos en
srcytests - Exija
declare(strict_types=1)
Ver solucion
<?php
declare(strict_types=1);
$finder = PhpCsFixer\Finder::create()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests');
return (new PhpCsFixer\Config())
->setRules([
'@PSR12' => true,
'declare_strict_types' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'no_unused_imports' => true,
])
->setFinder($finder)
->setRiskyAllowed(true);
Has encontrado un error o tienes una sugerencia para mejorar esta leccion?
EscribenosTe está gustando el curso?
Tenemos cursos premium con proyectos reales y soporte personalizado.
Descubrir cursos premium