Re: [RFC] PHP Attributes

From: Date: Mon, 25 Apr 2016 07:51:20 +0000
Subject: Re: [RFC] PHP Attributes
References: 1 2 3 4 5 6 7  Groups: php.internals 
Request: Send a blank email to internals+get-92709@lists.php.net to get a copy of this message
On 04/22/2016 06:56 PM, Larry Garfield wrote:
On 4/22/16 10:39 AM, guilhermeblanco@gmail.com wrote:
On Fri, Apr 22, 2016 at 3:07 AM, Dmitry Stogov <dmitry@zend.com> wrote:
3- Did you put any thought on inheritance? What I mentioned in comment #1 is even smaller than what you implemented in RFC. Assuming you keep the RFC approach, did you consider support overrides, inherit, etc? In my opinion, attributes don't have to be inherited. If you think differently - please explain your point.
Of source I can. A simple case would be to increate visibility of the inherited property. It was declared in a parent class as protected, but now you want public, and you still want to keep all parent defined Attributes. Another example is like we do in Doctrine. We support a callback system which we named as lifetime callbacks. Pre-persist is one of them, which is called every time a given Entity is about to be persisted into DB. When you're dealing with inheritance, you can potentially override the method content and you still want to trigger the same operation as if it was untouched. Example: use Doctrine\ORM; trait Timestampable {
     protected $created;
     protected $updated;
     <<ORM\PrePersist>>
     public function prePersist() {
         $this->created = $this->updated = new \DateTime("now");
     }
     <<ORM\PreUpdate>>
     public function preUpdate() {
         $this->updated = new \DateTime("now");
     }
} <<ORM\Entity>> class User {
     use Timestampable;
     public function prePersist() {
         // Add my custom logic
     }
} The implication is that through a simplistic approach, inheriting (or overriding) is not clear and I can't figure it out an easy way to achieve that. Now if we go towards calling a function or class constructor like I mentioned before, then we could easily build structures like __Inherit, __Override, etc.
Here's another example from a Doctrine-using project I built a while back. (Not the exact code, but the same concept; I've adapted it to PHP 7 types as well): interface Ownable { public function getOwner() : string; public function setOwner(string $u); public function isUnowned() : bool; } trait OwnableTrait { /** @ORM\String **/ private $owner = ''; public getOwner() : string {
    return $this->owner;
} public setOwner(string $u) {
    $this->owner = $owner;
} public function isUnowned() : bool {
    return $this->owner == '';
} } /** @ORM\Entity */ class Product implements Ownable { use OwnableTrait; // ... } class Widget extends Product {
    // ...
} For annotations to work for this use case, reflecting on the properties of Widget would need to include $owner, and it would need to include the ORM\String annotation. (True regardless of whether annotations are array or object based.) In your example you don't override the property, so you'll able to see attributes of your property.
<?php trait T {
    <<test>>
    protected $x;
} class Foo {
    use T;
} $r = new ReflectionClass("Foo"); $prop = $r->getProperty("x"); var_dump($prop->getAttributes()); ?> $ sapi/cli/php attr7.php array(1) { ["test"]=> bool(true) } Works fine. Thanks. Dmitry.

« previous php.internals (#92709) next »