Unterstützt PHP 7 Typhinweise für Klasseneigenschaften?
Ich meine, nicht nur für Setter / Getter, sondern für die Immobilie selbst.
Etwas wie:
class Foo {
/**
*
* @var Bar
*/
public $bar : Bar;
}
$fooInstance = new Foo();
$fooInstance->bar = new NotBar(); //Error
php
attributes
php-7
type-hinting
variable-types
CarlosCarucce
quelle
quelle
Antworten:
PHP 7.4 unterstützt typisierte Eigenschaften wie folgt :
class Person { public string $name; public DateTimeImmutable $dateOfBirth; }
PHP 7.3 und frühere Versionen unterstützen dies nicht, es gibt jedoch einige Alternativen.
Sie können eine private Eigenschaft erstellen, auf die nur über Getter und Setter mit Typdeklarationen zugegriffen werden kann:
class Person { private $name; public function getName(): string { return $this->name; } public function setName(string $newName) { $this->name = $newName; } }
Sie können auch eine öffentliche Eigenschaft erstellen und einen Dokumentblock verwenden, um Typinformationen für Personen bereitzustellen, die den Code lesen und eine IDE verwenden. Dies bietet jedoch keine Laufzeit-Typprüfung:
class Person { /** * @var string */ public $name; }
In der Tat können Sie Getter und Setter und einen Docblock kombinieren.
Wenn Sie mehr Abenteuer sind, können Sie ein gefälschtes Grundstück mit dem machen
__get
,__set
,__isset
und__unset
magischen Methoden , und überprüfen Sie die Arten selbst. Ich bin mir nicht sicher, ob ich es empfehlen würde.quelle
array_push($this->foo, $bar)
odersort($this->foobar)
zu sagen .(new Person())->dateOfBirth = '2001-01-01';
... Vorausgesetztdeclare(strict_types=0);
, das ist. Wird es denDateTimeImmutable
Konstruktor werfen oder benutzen ? Und wenn dies der Fall ist, welche Art von Fehler wird ausgelöst, wenn die Zeichenfolge ein ungültiges Datum ist?TypeError
?7.4+:
Gute Nachrichten, dass es in den neuen Versionen implementiert wird, wie @Andrea betonte. Ich werde diese Lösung nur hier belassen, falls jemand sie vor 7.4 verwenden möchte
7,3 oder weniger
Aufgrund der Benachrichtigungen, die ich immer noch von diesem Thread erhalte, glaube ich, dass viele Leute da draußen das gleiche Problem hatten / haben wie ich. Meine Lösung für diesen Fall bestand darin, Setter +
__set
magische Methode in einem Merkmal zu kombinieren , um dieses Verhalten zu simulieren. Hier ist es: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; } } }
Und hier ist die Demonstration:
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
Erläuterung
Definieren Sie zunächst
bar
als Privateigentum, damit PHP__set
automatisch umgewandelt wird .__set
prüft, ob im aktuellen Objekt (method_exists($this, $setter)
) ein Setter deklariert ist . Andernfalls wird der Wert nur wie gewohnt eingestellt.Deklarieren Sie eine Setter-Methode (setBar), die ein typbezogenes Argument (
setBar(Bar $bar)
) empfängt .Solange PHP erkennt, dass etwas, das keine
Bar
Instanz ist, an den Setter übergeben wird, löst es automatisch einen schwerwiegenden Fehler aus: Nicht erfasster Typ Fehler: Argument 1, das an Foo :: setBar () übergeben wird, muss eine Instanz von Bar sein, Instanz von NotBar angegebenquelle
Bearbeiten für PHP 7.4:
Seit PHP 7.4 können Sie Attribute ( Dokumentation / Wiki ) eingeben, was bedeutet, dass Sie Folgendes tun können:
class Foo { protected ?Bar $bar; public int $id; ... }
Laut Wiki sind alle akzeptablen Werte:
PHP <7,4
Es ist eigentlich nicht möglich und Sie haben nur 4 Möglichkeiten, es tatsächlich zu simulieren:
Ich habe sie alle hier kombiniert
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; } }
Beachten Sie, dass Sie die Rückgabe tatsächlich als? Bar seit PHP 7.1 (nullbar) eingeben können, da sie null sein könnte (in PHP7.0 nicht verfügbar).
Sie können die Rückgabe auch als ungültig seit php7.1 eingeben
quelle
Sie können Setter verwenden
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);
Ausgabe:
TypeError: Argument 1 passed to Foo::setBar() must be an instance of Bar, instance of Foo given, called in ...
quelle