Lo nuevo en PHP 7.4: Propiedades con tipo

¡Por fin! Ahora, con PHP 7.4, vamos a poder especificar de qué tipo es una propiedad en una clase. Era una de las cosas que más echaba yo en falta en PHP. Se acabó usar el incómodo y feo PHPDoc.

Hasta ahora teníamos que hacer esto para nuestro editor de código supiera el tipo de propiedad:

class Persona
{
    /**
     * @var string
     */
    public $nombre;
    /**
     * @var string
     */
    public $apellidos;
}

Pero eso ya se acabó. Ya podemos al fin especificar bien los tipos de propiedades:

class Persona
{
    public string $nombre;
    public string $apellidos;
}

Y se pueden usar sin ningún misterio:

class Persona
{
    public string $nombre;
    public string $apellidos;
}

$persona = new Persona;

$persona->nombre = 'Gorka';
$persona->apellidos = 'Urrutia';

echo "Se llama {$persona->nombre} {$persona->apellidos}\n";

Valores iniciales

Pero, ojo, si vas a usarlas hay una serie de condiciones que debes tener en cuenta. La primera es que debes dar valor inicial a una propiedad con tipo antes de usarla.

En el siguiente ejemplo vamos a tener un error por intentar usar «apellidos» sin haberle dado un valor:

class Persona
{
    public string $nombre;
    public string $apellidos;
}

$persona = new Persona;

$persona->nombre = 'Gorka';

echo "Se llama {$persona->nombre} {$persona->apellidos}\n";

Esto lo podemos arreglar así:

class Persona
{
    public string $nombre;
    public string $apellidos = 'Nadie';
}

$persona = new Persona;

$persona->nombre = 'Gorka';

echo "Se llama {$persona->nombre} {$persona->apellidos}\n";class Persona
{
    public string $nombre;
    public string $apellidos = 'Nadie';
}

$persona = new Persona;

$persona->nombre = 'Gorka';

echo "Se llama {$persona->nombre} {$persona->apellidos}\n";

Propiedades con valor null

Hasta ahora no había ningún problema en dar un valor «null» a una propiedad. Pero si usas propiedades con tipo ya no vas a poder.

Este ejemplo te va a dar un error diciendo que no se puede asignar el valor null a $edad:

class Persona
{
    public string $nombre;
    public string $apellidos;
    public int $edad = null;
}

¿Entonces qué hago? Tranquilidad, que para todo hay solución. En este caso basta con añadir el símbolo ‘?’ delante del tipo que vamos a usar:

class Persona
{
    public string $nombre;
    public string $apellidos;
    public ?int $edad = null;
}

Así que, recuerda, solo las propiedades «nullables» pueden contener el valor null.

Tipos permitidos en las propiedades

Para una propiedad podemos usar cualquier tipo «primitivo» (los que vienen definidos por PHP como int, float, string, etc.) salvo éstos:

  • void
  • callable

También podemos usar una clase como propiedad o incluso un interface:

class Edad
{
    public $edad = 0;

    public function meses()
    {
        return $this->edad * 12;
    }
}

interface TrabajoInterface {
    public function peligrosidad();
}

class Persona
{
    public string $nombre;
    public string $apellidos;
    public Edad $edad;
    public TrabajaInterface $trabajo;
}

Curiosamente sí se puede poner un trait como tipo de una propiedad, aunque teniendo en cuenta que un trait no se puede instanciar no veo por qué íbamos a hacer tal cosa:

trait MiTrait
{
}

class Persona
{
    public string $nombre;
    public string $apellidos;
    public MiTrait $trait;
}

Conversión de datos

Pero PHP sigue siendo majete y nos convierte los tipos de datos siempre que pueda. Así que si, por ejemplo, pasamos una cadena que se puede convertir en un número hará la conversión sin problemas:

class Persona
{
    public string $nombre;
    public string $apellidos;
    public int $edad;
}

$persona = new Persona;

$persona->edad = '30';

echo "Esta persona tiene {$persona->edad} años\n";

Nota: No, yo no tengo 30 años, ya me gustaría.

Pero no va a aceptar:

$persona->edad = 'treinta';

Ojo con strict_types

Lo que he comentado en el punto anterior es totalmente falso si usamos strict_types. Verás que al añadir esta primera línea tienes un error porque ya no te va aceptar ’30’ como un número:

declare(strict_types=1);

class Persona
{
    public string $nombre;
    public string $apellidos;
    public int $edad;
}

$persona = new Persona;

$persona->edad = '30';

echo "Esta persona tiene {$persona->edad} años\n";

Más información

Para más información lo mejor es ir a la fuente que, en este caso es el RFC correspondiente:

PHP RFC: Typed Properties 2.0

Me siento solo, dime algo...