Constructor Property Promotion
Constructor Property Promotion permite declarar y asignar propiedades directamente en los parametros del constructor, eliminando codigo repetitivo.
Antes vs Despues
Antes de PHP 8, crear una clase requeria declarar propiedades, definir parametros y asignar valores por separado:
<?php
declare(strict_types=1);
class Producto
{
private string $nombre;
private float $precio;
private int $stock;
public function __construct(string $nombre, float $precio, int $stock)
{
$this->nombre = $nombre;
$this->precio = $precio;
$this->stock = $stock;
}
}
Con PHP 8, agregas el modificador de visibilidad directamente en los parametros:
<?php
declare(strict_types=1);
class Producto
{
public function __construct(
private string $nombre,
private float $precio,
private int $stock
) {}
}
$producto = new Producto('Laptop', 999.99, 10);
// Las propiedades estan disponibles automaticamente
PHP automaticamente declara las propiedades y les asigna los valores.
Visibilidad y valores por defecto
Puedes usar cualquier modificador (public, protected,
private) y asignar valores por defecto:
<?php
declare(strict_types=1);
class Articulo
{
public function __construct(
public string $titulo, // Accesible desde fuera
private string $contenido, // Solo accesible internamente
private string $autor = 'Anonimo',
private bool $publicado = false
) {}
public function getResumen(): string
{
$estado = $this->publicado ? 'Publicado' : 'Borrador';
return "{$this->titulo} por {$this->autor} - {$estado}";
}
}
$articulo = new Articulo('PHP 8', 'Contenido...');
echo $articulo->titulo; // PHP 8 (public)
echo $articulo->getResumen(); // PHP 8 por Anonimo - Borrador
Combinar con lógica adicional
Puedes mezclar propiedades promovidas con propiedades tradicionales y agregar validaciones en el cuerpo del constructor:
<?php
declare(strict_types=1);
class Usuario
{
private string $id;
public function __construct(
private string $nombre,
private string $email
) {
// Validacion
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException('Email invalido');
}
// Propiedad calculada
$this->id = uniqid('user_');
}
public function getId(): string
{
return $this->id;
}
}
$usuario = new Usuario('Ana', 'ana@example.com');
echo $usuario->getId(); // user_6574a3f2...
Ejemplo practico: DTO
Constructor Property Promotion es ideal para Data Transfer Objects, clases simples que transportan datos:
<?php
declare(strict_types=1);
class CrearPedidoDTO
{
public function __construct(
public string $cliente,
public array $productos,
public float $total,
public ?string $cupon = null
) {}
}
// Desde datos de formulario
$dto = new CrearPedidoDTO(
cliente: 'Juan Garcia',
productos: ['Laptop', 'Mouse'],
total: 1099.99
);
echo $dto->cliente; // Juan Garcia
echo $dto->total; // 1099.99
Ejercicios
Ejercicio 1: Refactorizar clase
Refactoriza esta clase para usar Constructor Property Promotion:
<?php
declare(strict_types=1);
class Libro
{
private string $titulo;
private string $autor;
private float $precio;
public function __construct(string $titulo, string $autor, float $precio)
{
$this->titulo = $titulo;
$this->autor = $autor;
$this->precio = $precio;
}
}
Ver solucion
<?php
declare(strict_types=1);
class Libro
{
public function __construct(
private string $titulo,
private string $autor,
private float $precio
) {}
}
Ejercicio 2: Crear clase Direccion
Crea una clase Direccion con: calle, numero, ciudad,
codigoPostal, y pais (por defecto 'Espana'). Incluye un metodo
formatear() que retorne la direccion completa.
Ver solucion
<?php
declare(strict_types=1);
class Direccion
{
public function __construct(
private string $calle,
private string $numero,
private string $ciudad,
private string $codigoPostal,
private string $pais = 'Espana'
) {}
public function formatear(): string
{
return "{$this->calle} {$this->numero}, "
. "{$this->codigoPostal} {$this->ciudad}, "
. "{$this->pais}";
}
}
$dir = new Direccion('Gran Via', '42', 'Madrid', '28001');
echo $dir->formatear();
// Gran Via 42, 28001 Madrid, Espana
Ejercicio 3: Validacion en constructor
Crea una clase Edad que valide que el valor este
entre 0 y 150. Si no es valido, lanza una excepcion.
Ver solucion
<?php
declare(strict_types=1);
class Edad
{
public function __construct(
private int $valor
) {
if ($valor < 0 || $valor > 150) {
throw new \InvalidArgumentException(
"Edad invalida: {$valor}"
);
}
}
public function getValor(): int
{
return $this->valor;
}
}
$edad = new Edad(25);
echo $edad->getValor(); // 25
¿Has encontrado un error o tienes una sugerencia?
Escribenos