una tips para new extraer escapar dentro comillas caracteres cadena atributos array php attributes php-7 type-hinting variable-types

tips - ¿Escriba sugerencias para propiedades en PHP 7?



new php (4)

¿PHP 7 admite sugerencias de tipo para propiedades de clase?

Quiero decir, no solo para los setters / getters sino también para la propiedad en sí.

Algo como:

class Foo { /** * * @var Bar */ public $bar : Bar; } $fooInstance = new Foo(); $fooInstance->bar = new NotBar(); //Error


En realidad no es posible y solo tiene 4 formas de simularlo:

  • Valores predeterminados
  • Decoradores en bloques de comentarios
  • Valores predeterminados en constructor
  • Getters y setters

Los combiné todos aquí

class Foo { /** * @var Bar */ protected $bar = null; /** * Foo constructor * @param Bar $bar **/ public function __construct(Bar $bar = null){ $this->bar = $bar; } /** * @return Bar */ public function getBar() : ?Bar{ return $this->bar; } /** * @param Bar $bar */ public function setBar(Bar $bar) { $this->bar = $bar; } }

Tenga en cuenta que en realidad puede escribir el retorno como? Bar desde php 7.1 (anulable) porque podría ser nulo (no disponible en php7.0).

También puede escribir el retorno como nulo desde php7.1


PHP 7.4 admitirá propiedades escritas de esta manera:

class Person { public string $name; public DateTimeImmutable $dateOfBirth; }

PHP 7.3 y versiones anteriores no admiten esto, pero hay algunas alternativas.

Puede crear una propiedad privada a la que solo se pueda acceder mediante getters y setters que tengan declaraciones de tipo:

class Person { private $name; public function getName(): string { return $this->name; } public function setName(string $newName) { $this->name = $newName; } }

También puede hacer una propiedad pública y usar un docblock para proporcionar información de tipo a las personas que leen el código y usan un IDE, pero esto no proporciona verificación de tipo de tiempo de ejecución:

class Person { /** * @var string */ public $name; }

Y de hecho, puedes combinar getters y setters y un docblock.

Si eres más aventurero, puedes hacer una propiedad falsa con los __get __set __get , __set , __isset y __unset , y verificar los tipos tú mismo. Sin embargo, no estoy seguro de si lo recomendaría.


Puedes usar setter

class Bar { public $val; } class Foo { /** * * @var Bar */ private $bar; /** * @return Bar */ public function getBar() { return $this->bar; } /** * @param Bar $bar */ public function setBar(Bar $bar) { $this->bar = $bar; } } $fooInstance = new Foo(); // $fooInstance->bar = new NotBar(); //Error $fooInstance->setBar($fooInstance);

Salida:

TypeError: Argument 1 passed to Foo::setBar() must be an instance of Bar, instance of Foo given, called in ...


7.4+:

Buenas noticias de que se implementará en los nuevos lanzamientos, como señaló @Andrea. Dejaré esta solución aquí en caso de que alguien quiera usarla antes de 7.4

7.3 o menos

Según las notificaciones que aún recibo de este hilo, creo que muchas personas tenían / ​​están teniendo el mismo problema que yo. Mi solución para este caso fue combinar setters + __set magic method dentro de un rasgo para simular este comportamiento. Aquí está:

trait SettersTrait { /** * @param $name * @param $value */ public function __set($name, $value) { $setter = ''set''.$name; if (method_exists($this, $setter)) { $this->$setter($value); } else { $this->$name = $value; } } }

Y aquí está la demostración:

class Bar {} class NotBar {} class Foo { use SettersTrait; //It could be implemented within this class but I used it as a trait for more flexibility /** * * @var Bar */ private $bar; /** * @param Bar $bar */ protected function setBar(Bar $bar) { //(optional) Protected so it wont be called directly by external ''entities'' $this->bar = $bar; } } $foo = new Foo(); $foo->bar = new NotBar(); //Error //$foo->bar = new Bar(); //Success

Explicación

En primer lugar, defina bar como una propiedad privada para que PHP emita __set .

__set verificará si hay algún setter declarado en el objeto actual ( method_exists($this, $setter) ). De lo contrario, solo establecerá su valor como lo haría normalmente.

Declare un método setter (setBar) que recibe un argumento de tipo insinuado ( setBar(Bar $bar) ).

Siempre que PHP detecte que algo que no es una instancia de Bar se pasa al configurador, automáticamente activará un Error grave: Tipo de error no capturado: El argumento 1 pasado a Foo :: setBar () debe ser una instancia de Bar, instancia de NotBar dado