# [RFC] PHP Attributes

- Thread: https://externals.io/message/92609
- Original archive: https://news-web.php.net/php.internals/92609
- Started by Dmitry Stogov on 2016-04-21T21:13:15+00:00
- Messages: 122
- RFC: PHP Attributes (Declined) — https://externals.io/rfc/attributes.md
- Page 1 of 5: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/92609.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #92609 — Dmitry Stogov — 2016-04-21T21:13:15+00:00

URL: https://externals.io/message/92609#92609

Hi,


I would like to present an RFC proposing support for native annotation.

The naming, syntax and behavior are mostly influenced by HHVM Hack, but not exactly the same.

The most interesting difference is an ability to use arbitrary PHP expressions as attribute values.

These expressions are not evaluated, but stored as Abstract Syntax Trees, and later may be accessed (node by node) in PHP extensions, preprocessors and PHP scripts their selves. I think this ability may be useful for "Design By Contract", other formal verification systems, Aspect Oriented Programming, etc


https://wiki.php.net/rfc/attributes


Note that this approach is going to be native, in contrast to doc-comment approach that uses not well defined syntax, and even not parsed by PHP itself.


Additional ideas, endorsement and criticism are welcome.


Thanks. Dmitry.

---

## #92612 — Larry Garfield — 2016-04-21T21:52:05+00:00

URL: https://externals.io/message/92609#92612 · In reply to: #92609

> Hi,
>
>
> I would like to present an RFC proposing support for native annotation.
>
> The naming, syntax and behavior are mostly influenced by HHVM Hack, but not exactly the same.
>
> The most interesting difference is an ability to use arbitrary PHP expressions as attribute values.
>
> These expressions are not evaluated, but stored as Abstract Syntax Trees, and later may be accessed (node by node) in PHP extensions, preprocessors and PHP scripts their selves. I think this ability may be useful for "Design By Contract", other formal verification systems, Aspect Oriented Programming, etc
>
>
> https://wiki.php.net/rfc/attributes
>
>
> Note that this approach is going to be native, in contrast to doc-comment approach that uses not well defined syntax, and even not parsed by PHP itself.
>
>
> Additional ideas, endorsement and criticism are welcome.
>
>
> Thanks. Dmitry.

Thanks, Dmitry!  In concept I am in favor of syntax-native annotations, 
although I have some concerns with the specifics of the proposal.  
Thoughts in no particular order:

First, for the getAttributes() reflection method, please oh please don't 
return array-or-false.  That's horrible.  Just return an empty array if 
there aren't any, as that makes getAttributes() entirely type safe and 
saves all callers from a mandatory if-check.  (See 
http://www.garfieldtech.com/blog/empty-return-values for more information.)

The reflection section further indicates that the type of the result is 
variable, which means I cannot know in advance if I'm going to get back 
a scalar or an array.  If we go with this free-form approach, I'd 
honestly prefer to always get back an array, even for single value, so 
that I can always know the type I'm dealing with. (Since I cannot 
enforce a given attribute to be single-value.)

For the expression example:

<<test($a  +  $b   >  0)>>
function  foo($a,  $b)  {
}


It is not at all clear to me what scope the annotation's $a and $b exist 
in.  Are the they same $a and $b as in the function signature? If so, 
what happens if I reflect the function before ever calling it?  How can 
I evaluate test?  Or are they inherited from the global scope at the 
time of declaration?  (That scares me a great deal.)  I don't know what 
to make of that at all.

In the "Attribute syntax" section, the text says the tokens are the left 
and right double-angle character, as used for quotations in some 
European languages.  The rest of the text says it's two left/right 
carrot characters, as seen above the comma and period on US keyboards.  
I'm assuming the former is just a typo/auto-correct bug.

If I read correctly, the following two would be semantically identical:

<<One, Two>>
function foo() {}

<<One>>
<<Two>>
function foo() {}

Is there a reason you chose the name "attribute" rather than 
"annotations", which seems at least in PHP to be the more common term 
for this type of declaration?

It appears that the annotations themselves are entirely free-form. At 
the risk of expanding the typing debate, this concerns me as then all 
we're adding is a new way to parse undocumented, undefined anonymous 
structs.  How can I say what annotations mean what for my ORM, or 
routing system, or whatever?  We're back to, essentially, out-of-band 
documentation of big anonymous structs (aka associative arrays).

A more robust alternative would be something along the same lines that 
Doctrine uses: Make annotations actual classes.  To wit:


<<AThing>>
<<AnotherThing('stuff')>>
<<MoreThing(1, 2, 3)>>
function foo($a, $b) { }

Where AThing, AnotherThing, and MoreThing are defined classes, and 
subject to namespaces and use statements.  Then what gets returned from 
getAttributes() is an array consisting of an instance of AThing, an 
instance of AnotherThing, and an instance of MoreThing. In this example 
we'd just call their constructors with the listed values and let them do 
as they will.  Doctrine uses named properties in the annotation that 
maps to properties on the object, which is even more flexible and 
self-documenting although I don't know how feasible that is without 
opening up the named properties can of worms globally.

Either way, the advantage then is that I know what annotations are 
available, and the class itself serves as documentation for what it is, 
what it does, and what its options are.  It also helps address 
collisions if two different libraries both want to use the same keyword; 
we already have a class name resolution mechanism that works and 
everyone is familiar with.

One concern is that not all classes necessarily make sense as an 
annotation; perhaps only classes with a certain interface can be used.  
Actually (thinking aloud here), that would be a possible solution to the 
named property issue.  To wit:

<<AThing(a => 'a', b => 'b')>>
foo() {}

class AThing implements Attribute {
   public static function attributeCreate(array $params) {
     return new static($param['a'], $param['b']);
   }
}

$r  = new ReflectionFunction('foo');
$a = $r->getAttributes();

$a is now an array of one element, an instance of AThing, created with 
'a' and 'b'.  The specifics here are probably terrible, but the general 
idea of using classes to define annotations is, I think, a big step 
forward for documentation and avoiding multi-library collisions.

While I know some of the things Drupal 8 is using annotations for are 
arguably excessive (and I would agree with that argument in some cases), 
as is I fear the proposed system is too free-form and rudimentary for 
Drupal to switch to them.

-- 
--Larry Garfield

---

## #92613 — Benjamin Eberlei — 2016-04-21T22:08:25+00:00

URL: https://externals.io/message/92609#92613 · In reply to: #92612

On Thu, Apr 21, 2016 at 11:52 PM, Larry Garfield <larry@garfieldtech.com>
wrote:

> 
>
> > […]
>
> Thanks, Dmitry!  In concept I am in favor of syntax-native annotations,
> although I have some concerns with the specifics of the proposal.  Thoughts
> in no particular order:
>
> First, for the getAttributes() reflection method, please oh please don't
> return array-or-false.  That's horrible.  Just return an empty array if
> there aren't any, as that makes getAttributes() entirely type safe and
> saves all callers from a mandatory if-check.  (See
> http://www.garfieldtech.com/blog/empty-return-values for more
> information.)
>
> The reflection section further indicates that the type of the result is
> variable, which means I cannot know in advance if I'm going to get back a
> scalar or an array.  If we go with this free-form approach, I'd honestly
> prefer to always get back an array, even for single value, so that I can
> always know the type I'm dealing with. (Since I cannot enforce a given
> attribute to be single-value.)
>
> For the expression example:
>
> <<test($a  +  $b   >  0)>>
> function  foo($a,  $b)  {
> }
>
>
> It is not at all clear to me what scope the annotation's $a and $b exist
> in.  Are the they same $a and $b as in the function signature? If so, what
> happens if I reflect the function before ever calling it?  How can I
> evaluate test?  Or are they inherited from the global scope at the time of
> declaration?  (That scares me a great deal.)  I don't know what to make of
> that at all.
>

They don't exist in any scope. You get an AST of this expression, what you
do with it is entirely your choosing and you can set the scope/context
yourself.

>
> In the "Attribute syntax" section, the text says the tokens are the left
> and right double-angle character, as used for quotations in some European
> languages.  The rest of the text says it's two left/right carrot
> characters, as seen above the comma and period on US keyboards.  I'm
> assuming the former is just a typo/auto-correct bug.
>
> If I read correctly, the following two would be semantically identical:
>
> <<One, Two>>
> function foo() {}
>
> <<One>>
> <<Two>>
> function foo() {}
>
> Is there a reason you chose the name "attribute" rather than
> "annotations", which seems at least in PHP to be the more common term for
> this type of declaration?
>
> It appears that the annotations themselves are entirely free-form. At the
> risk of expanding the typing debate, this concerns me as then all we're
> adding is a new way to parse undocumented, undefined anonymous structs.
> How can I say what annotations mean what for my ORM, or routing system, or
> whatever?  We're back to, essentially, out-of-band documentation of big
> anonymous structs (aka associative arrays).
>
> A more robust alternative would be something along the same lines that
> Doctrine uses: Make annotations actual classes.  To wit:
>
>
> <<AThing>>
> <<AnotherThing('stuff')>>
> <<MoreThing(1, 2, 3)>>
> function foo($a, $b) { }


> Where AThing, AnotherThing, and MoreThing are defined classes, and subject
> to namespaces and use statements.  Then what gets returned from
> getAttributes() is an array consisting of an instance of AThing, an
> instance of AnotherThing, and an instance of MoreThing. In this example
> we'd just call their constructors with the listed values and let them do as
> they will.  Doctrine uses named properties in the annotation that maps to
> properties on the object, which is even more flexible and self-documenting
> although I don't know how feasible that is without opening up the named
> properties can of worms globally.
>

I like that its just arrays, PHP is not exclusively OOP, so making this an
OOP feature doesn't make sense to me.

A library like Doctrine can always add the meaning on top, for example
checking:

<<ORM\Entity>>
class User
{
}

Again resolving this against namespaces for example inside Doctrine
Annotations itself, like its done right now.


>
> Either way, the advantage then is that I know what annotations are
> available, and the class itself serves as documentation for what it is,
> what it does, and what its options are.  It also helps address collisions
> if two different libraries both want to use the same keyword; we already
> have a class name resolution mechanism that works and everyone is familiar
> with.


> One concern is that not all classes necessarily make sense as an
> annotation; perhaps only classes with a certain interface can be used.
> Actually (thinking aloud here), that would be a possible solution to the
> named property issue.  To wit:
>

This is why it should be just arrays, using classes suddenly tons of
special things can happen and must be thought of.


>
> <<AThing(a => 'a', b => 'b')>>
> foo() {}
>
> class AThing implements Attribute {
>   public static function attributeCreate(array $params) {
>     return new static($param['a'], $param['b']);
>   }
> }
>
> $r  = new ReflectionFunction('foo');
> $a = $r->getAttributes();
>
> $a is now an array of one element, an instance of AThing, created with 'a'
> and 'b'.  The specifics here are probably terrible, but the general idea of
> using classes to define annotations is, I think, a big step forward for
> documentation and avoiding multi-library collisions.
>
> While I know some of the things Drupal 8 is using annotations for are
> arguably excessive (and I would agree with that argument in some cases), as
> is I fear the proposed system is too free-form and rudimentary for Drupal
> to switch to them.


You can build any kind of structure on top of $refl->getAttributes() inside
your framework (Drupal in this case)

>
>
> --
> --Larry Garfield

---

## #92616 — Dmitry Stogov — 2016-04-21T22:42:21+00:00

URL: https://externals.io/message/92609#92616 · In reply to: #92612

> 
> > […]
>
> Thanks, Dmitry!  In concept I am in favor of syntax-native 
> annotations, although I have some concerns with the specifics of the 
> proposal.  Thoughts in no particular order:
>
> First, for the getAttributes() reflection method, please oh please 
> don't return array-or-false.  That's horrible.  Just return an empty 
> array if there aren't any, as that makes getAttributes() entirely type 
> safe and saves all callers from a mandatory if-check.  (See 
> http://www.garfieldtech.com/blog/empty-return-values for more 
> information.)
Makes sense. I may change this.
>
> The reflection section further indicates that the type of the result 
> is variable, which means I cannot know in advance if I'm going to get 
> back a scalar or an array.  If we go with this free-form approach, I'd 
> honestly prefer to always get back an array, even for single value, so 
> that I can always know the type I'm dealing with. (Since I cannot 
> enforce a given attribute to be single-value.)

I'm not sure yet. both decisions may make sense. If I expect just a 
single value, I'll have to check the number of elements (or just ignore 
values above the first).
>
> For the expression example:
>
> <<test($a  +  $b   >  0)>>
> function  foo($a,  $b)  {
> }
>
>
> It is not at all clear to me what scope the annotation's $a and $b 
> exist in.  Are the they same $a and $b as in the function signature? 
> If so, what happens if I reflect the function before ever calling it?
This is just an AST. It may contain any valid PHP expression syntax, but 
variable, functions and constants don't have to be valid.

> How can I evaluate test?
I hope this functionality will be provided by php-ast extension. 
Currently, it is not a problem to reconstruct PHP source from AST and 
then use regular eval().
In general, we may find a more efficient way.

> Or are they inherited from the global scope at the time of 
> declaration?  (That scares me a great deal.)  I don't know what to 
> make of that at all.
AST is going to be mainly used by extension and pre-processors (like AOT 
and DBC), but in general, they also may be used directly in scripts.

<<test($a  +  $b   >  0)>>
function  foo($a,  $b)  {
ast_eval(RefelectionFunction(__FUNCTION__)->getAttributes()["test"]);
}

> DB
> In the "Attribute syntax" section, the text says the tokens are the 
> left and right double-angle character, as used for quotations in some 
> European languages.  The rest of the text says it's two left/right 
> carrot characters, as seen above the comma and period on US 
> keyboards.  I'm assuming the former is just a typo/auto-correct bug.

yeah, computers think they are too smart :)
>
> If I read correctly, the following two would be semantically identical:
>
> <<One, Two>>
> function foo() {}
>
> <<One>>
> <<Two>>
> function foo() {}

right
>
> Is there a reason you chose the name "attribute" rather than 
> "annotations", which seems at least in PHP to be the more common term 
> for this type of declaration?

I took the name from HHVM. Personally, I don't care about naming at all.
>
>
> It appears that the annotations themselves are entirely free-form.
no. they are parsed according to PHP expression syntax rules. syntax 
mistakes in attributes are going to be caught at compile time.

> At the risk of expanding the typing debate, this concerns me as then 
> all we're adding is a new way to parse undocumented, undefined 
> anonymous structs.  How can I say what annotations mean what for my 
> ORM, or routing system, or whatever?  We're back to, essentially, 
> out-of-band documentation of big anonymous structs (aka associative 
> arrays).
>
> A more robust alternative would be something along the same lines that 
> Doctrine uses: Make annotations actual classes.  To wit:
>
>
> <<AThing>>
> <<AnotherThing('stuff')>>
> <<MoreThing(1, 2, 3)>>
> function foo($a, $b) { }
>
> Where AThing, AnotherThing, and MoreThing are defined classes, and 
> subject to namespaces and use statements.  Then what gets returned 
> from getAttributes() is an array consisting of an instance of AThing, 
> an instance of AnotherThing, and an instance of MoreThing. In this 
> example we'd just call their constructors with the listed values and 
> let them do as they will.  Doctrine uses named properties in the 
> annotation that maps to properties on the object, which is even more 
> flexible and self-documenting although I don't know how feasible that 
> is without opening up the named properties can of worms globally.
This is just a next level. Attributes are just a storage of meta-data. 
You may use them as you like :)

function getAttributesAsObjects($r) {
     $ret = array();
     $a = $r->getAttributes();
     foreach ($a as $name => $val) {
         $ret[] = new $name(...$val);
    }
    return $ret;
}
>
> Either way, the advantage then is that I know what annotations are 
> available, and the class itself serves as documentation for what it 
> is, what it does, and what its options are.  It also helps address 
> collisions if two different libraries both want to use the same 
> keyword; we already have a class name resolution mechanism that works 
> and everyone is familiar with.
>
> One concern is that not all classes necessarily make sense as an 
> annotation; perhaps only classes with a certain interface can be 
> used.  Actually (thinking aloud here), that would be a possible 
> solution to the named property issue.  To wit:
>
> <<AThing(a => 'a', b => 'b')>>
> foo() {}
>
> class AThing implements Attribute {
>   public static function attributeCreate(array $params) {
>     return new static($param['a'], $param['b']);
>   }
> }
>
> $r  = new ReflectionFunction('foo');
> $a = $r->getAttributes();
>
> $a is now an array of one element, an instance of AThing, created with 
> 'a' and 'b'.  The specifics here are probably terrible, but the 
> general idea of using classes to define annotations is, I think, a big 
> step forward for documentation and avoiding multi-library collisions.
>
> While I know some of the things Drupal 8 is using annotations for are 
> arguably excessive (and I would agree with that argument in some 
> cases), as is I fear the proposed system is too free-form and 
> rudimentary for Drupal to switch to them.
>
We can't use classes and object in storage directly, because they may be 
defined in different PHP script, may be changed between requests, etc.
but as I showed, it's very easy to construct corresponding objects on 
request.

Thanks for deep review and good suggestions.

Dmitry.

---

## #92617 — Dmitry Stogov — 2016-04-21T22:51:58+00:00

URL: https://externals.io/message/92609#92617

>
> On Thu, Apr 21, 2016 at 11:13 PM, Dmitry Stogov <dmitry@zend.com 
> <mailto:dmitry@zend.com>> wrote:
>
>     Hi,
>
>
>     I would like to present an RFC proposing support for native
>     annotation.
>
>     The naming, syntax and behavior are mostly influenced by HHVM
>     Hack, but not exactly the same.
>
>     The most interesting difference is an ability to use arbitrary PHP
>     expressions as attribute values.
>
>     These expressions are not evaluated, but stored as Abstract Syntax
>     Trees, and later may be accessed (node by node) in PHP extensions,
>     preprocessors and PHP scripts their selves. I think this ability
>     may be useful for "Design By Contract", other formal verification
>     systems, Aspect Oriented Programming, etc
>
>
>     https://wiki.php.net/rfc/attributes
>
>
>     Note that this approach is going to be native, in contrast to
>     doc-comment approach that uses not well defined syntax, and even
>     not parsed by PHP itself.
>
>
>     Additional ideas, endorsement and criticism are welcome.
>
>
> I love it!
>
> Syntax is good, and i like that it just returns plain arrays. 
> Everything else (more formal) can be added on top by Doctrine 
> Annotations for example.

thanks for support :)
>
> About expressions, isn't there an ambigoutiy? <<test(1)>> is a "plain" 
> name, value based attribute. But it could also be an ast\node of a 
> function call to "test(1)"
even in AST scalars are scalars.
so <<test(1+2)>> would return: ast\node "+" with two children int(1) and 
int(2).

> I am wondering if they shouldn't get their own start/end signs to 
> clear that up, <<<test(1)>> vs <<test(1)>>.

no need for extra complication.

Thanks. Dmitry.

---

## #92618 — Ryan Pallas — 2016-04-21T23:02:26+00:00

URL: https://externals.io/message/92609#92618 · In reply to: #92617

>
>
> > […]
> even in AST scalars are scalars.
> so <<test(1+2)>> would return: ast\node "+" with two children int(1) and
> int(2).
>
> I am wondering if they shouldn't get their own start/end signs to clear
> > […]
>
> no need for extra complication.
>
> Since the encapsulated meta-data is an AST, and as you say any valid php
expression will be valid here, what about bit shifting?

<<Test(FOO >> BAR)>>

Are there concerns about finding the `T_SR` token, which is also the end
annotation symbol? I've not done any work in the parser, so excuse me if
that is an insanely stupid question :)

Otherwise, I think this RFC looks great, and appreciate your work on this :)

Ryan

---

## #92619 — Colin O'Dell — 2016-04-21T23:09:31+00:00

URL: https://externals.io/message/92609#92619 · In reply to: #92617

> A more robust alternative would be something along the same lines that
> Doctrine uses: Make annotations actual classes.

Just spitballing here - what if both approaches were supported, but
class-based annotations were prefixed with a special character (perhaps
"@") to differentiate them?  For example:

<<ArbitraryAnnotation("Hello world")>>
<<@ORM\Entity(table => "foo")>>
class Foo {
    // ...
}

namespace ORM;
class Entity implements \Attribute {
    // ...
}

$r = new ReflectionClass('ORM\Entity');
var_dump($r->getAttributes());

-----

array(2) {
    ["ArbitraryAnnotation"]=>
    string(11) "Hello world"
    ["ORM\Entity"] =>
    object(ORM\Entity)#1 (0) { ... }
}

-----

Again, I'm not necessarily advocating this - just throwing the idea out
there for discussion.

Regards,

Colin

---

## #92620 — Colin O'Dell — 2016-04-21T23:11:37+00:00

URL: https://externals.io/message/92609#92620 · In reply to: #92619

>
> $r = new ReflectionClass('ORM\Entity');
> var_dump($r->getAttributes());
>

Oops, that should've been:

$r = new ReflectionClass('Foo');
var_dump($r->getAttributes());

Colin

---

## #92621 — Dominic Grostate — 2016-04-21T23:16:19+00:00

URL: https://externals.io/message/92609#92621 · In reply to: #92609

This is amazing.  It would actually allow us to implement our automated
assertions ourselves, as opposed to requiring it within the language.

Could it also support references?

<<sanitize(&$a)>>
function foo($a) {

}


> Hi,
>
>
> I would like to present an RFC proposing support for native annotation.
>
> The naming, syntax and behavior are mostly influenced by HHVM Hack, but
> not exactly the same.
>
> The most interesting difference is an ability to use arbitrary PHP
> expressions as attribute values.
>
> These expressions are not evaluated, but stored as Abstract Syntax Trees,
> and later may be accessed (node by node) in PHP extensions, preprocessors
> and PHP scripts their selves. I think this ability may be useful for
> "Design By Contract", other formal verification systems, Aspect Oriented
> Programming, etc
>
>
> https://wiki.php.net/rfc/attributes
>
>
> Note that this approach is going to be native, in contrast to doc-comment
> approach that uses not well defined syntax, and even not parsed by PHP
> itself.
>
>
> Additional ideas, endorsement and criticism are welcome.
>
>
> Thanks. Dmitry.

---

## #92622 — Dmitry Stogov — 2016-04-21T23:19:46+00:00

URL: https://externals.io/message/92609#92622 · In reply to: #92618

>
>
> On Thu, Apr 21, 2016 at 4:51 PM, Dmitry Stogov <dmitry@zend.com 
> <mailto:dmitry@zend.com>> wrote:
>
>
>         About expressions, isn't there an ambigoutiy? <<test(1)>> is a
>         "plain" name, value based attribute. But it could also be an
>         ast\node of a function call to "test(1)"
>
>     even in AST scalars are scalars.
>     so <<test(1+2)>> would return: ast\node "+" with two children
>     int(1) and int(2).
>
>         I am wondering if they shouldn't get their own start/end signs
>         to clear that up, <<<test(1)>> vs <<test(1)>>.
>
>
>     no need for extra complication.
>
> Since the encapsulated meta-data is an AST, and as you say any valid 
> php expression will be valid here, what about bit shifting?
>
> <<Test(FOO >> BAR)>>
This works because attributes are implemented as native part of 
context-free PHP grammar.
>
> Are there concerns about finding the `T_SR` token, which is also the end 
> annotation symbol? I've not done any work in the parser, so excuse me 
> if that is an insanely stupid question :)
Not a problem. Better to get false alarm then miss a real one :)
>
> Otherwise, I think this RFC looks great, and appreciate your work on 
> this :)
>
Thanks. Dmitry.

> Ryan

---

## #92623 — Dmitry Stogov — 2016-04-21T23:26:50+00:00

URL: https://externals.io/message/92609#92623 · In reply to: #92619

> > […]
>
> Just spitballing here - what if both approaches were supported, but 
> class-based annotations were prefixed with a special character 
> (perhaps "@") to differentiate them?  For example:
>
> <<ArbitraryAnnotation("Hello world")>>
> <<@ORM\Entity(table => "foo")>>
> class Foo {
>     // ...
> }
>
> namespace ORM;
> class Entity implements \Attribute {
>     // ...
> }
>
> $r = new ReflectionClass('ORM\Entity');
> var_dump($r->getAttributes());
>
> -----
>
> array(2) {
>     ["ArbitraryAnnotation"]=>
>     string(11) "Hello world"
>     ["ORM\Entity"] =>
>     object(ORM\Entity)#1 (0) { ... }
> }
>
> -----
>
> Again, I'm not necessarily advocating this - just throwing the idea 
> out there for discussion.

Current proposal doen't support this, but this may be a good idea.
1) Attribute names might be not just strings, but also namespace qualified.
2) They may be optionally prefexed by some special character.

To create or not to create attribute objects is the question for next 
layer, but the base layer should provide necessary information.

Thanks. Dmitry.


>
> Regards,
>
> Colin

---

## #92624 — Dmitry Stogov — 2016-04-21T23:44:17+00:00

URL: https://externals.io/message/92609#92624 · In reply to: #92621

>
> This is amazing.  It would actually allow us to implement our 
> automated assertions ourselves, as opposed to requiring it within the 
> language.
>
this was the idea - to give a good tool instead of implementing every 
possible use-case in the language.

> Could it also support references?
>
> <<sanitize(&$a)>>
> function foo($a) {
>
> }
>
yes. "&$a" is a valid PHP expression.

If you plan to use this, I would appreciate, if you to build the patched 
PHP and try it.
The early we find problems the better feature we will get at the end.

Thanks. Dmitry.

> On 21 Apr 2016 10:13 p.m., "Dmitry Stogov" <dmitry@zend.com 
> <mailto:dmitry@zend.com>> wrote:
>
>     Hi,
>
>
>     I would like to present an RFC proposing support for native
>     annotation.
>
>     The naming, syntax and behavior are mostly influenced by HHVM
>     Hack, but not exactly the same.
>
>     The most interesting difference is an ability to use arbitrary PHP
>     expressions as attribute values.
>
>     These expressions are not evaluated, but stored as Abstract Syntax
>     Trees, and later may be accessed (node by node) in PHP extensions,
>     preprocessors and PHP scripts their selves. I think this ability
>     may be useful for "Design By Contract", other formal verification
>     systems, Aspect Oriented Programming, etc
>
>
>     https://wiki.php.net/rfc/attributes
>
>
>     Note that this approach is going to be native, in contrast to
>     doc-comment approach that uses not well defined syntax, and even
>     not parsed by PHP itself.
>
>
>     Additional ideas, endorsement and criticism are welcome.
>
>
>     Thanks. Dmitry.

---

## #92625 — guilhermeblanco@gmail.com — 2016-04-22T01:05:56+00:00

URL: https://externals.io/message/92609#92625 · In reply to: #92624

Hi Dmitry,

As a previous suggester of metadata information built-in into PHP, and also
one of developers of the most used metadata library written in PHP, I
understand this feature implementation requires several design decisions
and also a good understanding of specific situations users may require.

While I am a strong supporter of a more robust solution, this is already a
good start.
A few things I'd like to ask for my own understanding and also suggestions
too:

1- I understand you took a minimalistic approach towards a "dumb"
implementation for attributes (when I mean "dumb", the idea here is towards
a non-OO approach). Can you explain your motivations towards this approach?

I see two distinct approaches of implementation for this feature. Both of
them have some common demands, like lazy initialization of metadata. Here
they are:

- Simplistic approach, which lets consumers of the feature do all the work
related to validation, assertion of valid keys, values, etc
This does not invalidate the ability to leverage of some features that a
more robust implementation demands.

- Robust approach: language takes the burden of instantiating complex
structures, validating, assertion of valid keys, values, if this complex
structure is allowed to be instantiated in that given class, method, etc.

1- Your approach is basically defining an array. Could you explain your
line of thinking on why you didn't consider a syntax like the one below?

<["key" => "value"]>
class Foo {}

2- I see that you added support over functions, classes, constants and
properties. According to the RFC, getAttributes() was added over
ReflectionFunction. Is there a reason why support was not added to methods
(ReflectionMethod extends ReflectionFunctionAbstract, which was not
mentioned on RFC)? Any reason to not support it in function/method
parameters?

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?

4- I understand that a more robust attribute solution would be required to
achieve this, but one of the biggest advantages of AOP is the ability to
perform custom logic before, after or around... However, I don't know if
any kind of triggers came in your head or are planned as a future RFC.
Let me highlight one example: Every time a class, property or method is
called that is annotated as <<deprecated>>, I would like to issue an
 `E_USER_DEPRECATED` warning. A trigger-like solution would be required. Did
this concept came to your mind?



Regards,



>
>
> 
>
> > […]
> possible use-case in the language.
>
> Could it also support references?
> > […]
>
> If you plan to use this, I would appreciate, if you to build the patched
> PHP and try it.
> The early we find problems the better feature we will get at the end.
>
> Thanks. Dmitry.
>
>
> On 21 Apr 2016 10:13 p.m., "Dmitry Stogov" <dmitry@zend.com <mailto:
> > […]
>


-- 
Guilherme Blanco
Lead Architect at E-Block

---

## #92626 — Sara Golemon — 2016-04-22T02:15:35+00:00

URL: https://externals.io/message/92609#92626 · In reply to: #92609

> I would like to present an RFC proposing support for native annotation.
>
I'm trying to imagine where the benefit of non-constant expressions comes in.

<<foo($a < 1)>>

Assuming we roll in php-ast at the same time (which is a big addition,
IMO, and deserves its own separate RFC), what are users meant to do
with this?  Even if there's a use-case here, one could accomplish the
same thing with:

<<foo('$a < 1')>>

And manually running that string into php-ast if that's what the caller wanted.

Also, maybe I missed it, but I didn't see an answer to the question of
ambiguity between parsing the above as a straight string, versus
parsing it as a ZEND_AST_ZVAL.  I'm sure the answer is "If the AST
tree is just a ZVAL, then it's provided as the compile-time
expression, but what about something else like this:

<<foo(1+1)>>

Logically, this is reducible to a single compile-time value, but it's
a complex expression, so would it be the value int(2)? Or
ZEND_AST_BINARY_OP(int(1), int(1))?

I just think that over-engineers what should be a simple annotation feature.

All that said, I love the proposal overall, and I can't wait to
propose builtin annotations like <<__Memoize>>, <<__Mock>>, and
similar.

-Sara

---

## #92629 — Dmitry Stogov — 2016-04-22T07:07:30+00:00

URL: https://externals.io/message/92609#92629 · In reply to: #92625

> Hi Dmitry,
>
> As a previous suggester of metadata information built-in into PHP, and 
> also one of developers of the most used metadata library written in 
> PHP, I understand this feature implementation requires several design 
> decisions and also a good understanding of specific situations users 
> may require.
>
> While I am a strong supporter of a more robust solution, this is 
> already a good start.
> A few things I'd like to ask for my own understanding and also 
> suggestions too:
>
> 1- I understand you took a minimalistic approach towards a "dumb" 
> implementation for attributes (when I mean "dumb", the idea here is 
> towards a non-OO approach). Can you explain your motivations towards 
> this approach?
>
> I see two distinct approaches of implementation for this feature. Both 
> of them have some common demands, like lazy initialization of 
> metadata. Here they are:
>
> - Simplistic approach, which lets consumers of the feature do all the 
> work related to validation, assertion of valid keys, values, etc
> This does not invalidate the ability to leverage of some features that 
> a more robust implementation demands.
>
> - Robust approach: language takes the burden of instantiating complex 
> structures, validating, assertion of valid keys, values, if this 
> complex structure is allowed to be instantiated in that given class, 
> method, etc.

I didn't exactly understand what do you suggest.
If you are talking about Attribute objects initialization during 
compilation - this is just not possible from implementation point of view.
Now attributes may be stored in opcache SHM and relive request boundary.
Objects can't relive requests.
>
> 1- Your approach is basically defining an array. Could you explain 
> your line of thinking on why you didn't consider a syntax like the one 
> below?
>
> <["key" => "value"]>
> class Foo {}
I didn't try to invite new syntax. Just completely took it from HHVM.

>
> 2- I see that you added support over functions, classes, constants and 
> properties. According to the RFC, getAttributes() was added over 
> ReflectionFunction. Is there a reason why support was not added to 
> methods (ReflectionMethod extends ReflectionFunctionAbstract, which 
> was not mentioned on RFC)? Any reason to not support it in 
> function/method parameters?
ReflectionMethod is a child of ReflectinFunction, so it's supported.
Attributes are allowed for the same entities as doc-comments (they are 
not allowed for parameters)

>
> 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.
>
> 4- I understand that a more robust attribute solution would be 
> required to achieve this, but one of the biggest advantages of AOP is 
> the ability to perform custom logic before, after or around... 
> However, I don't know if any kind of triggers came in your head or are 
> planned as a future RFC.
> Let me highlight one example: Every time a class, property or method 
> is called that is annotated as <<deprecated>>, I would like to issue 
> an `E_USER_DEPRECATED` warning. A trigger-like solution would be 
> required. Did this concept came to your mind?
This is not a subject of this RFC.
Attributes provides a storage for metadata, but don't define how to use 
them.
Especially, for your use-case:
1) it's possible to create preprocessor that embeds corresponding 
 `trigger_error()` call
2) it's possible to write a PHP extension that plugs-into compiler chain 
and checks <<deprecated>> attribute for each compiles function, then 
sets ZEND_ACC_DEPRECATED flag
3) It's also possible to override DO_FCALL opcodes and perform checks 
there (this is inefficient)

Thanks. Dmitry.

>
>
>
> Regards,
>
> On Thu, Apr 21, 2016 at 7:44 PM, Dmitry Stogov <dmitry@zend.com 
> <mailto:dmitry@zend.com>> wrote:
>
>
>
>     
>
>
>         This is amazing.  It would actually allow us to implement our
>         automated assertions ourselves, as opposed to requiring it
>         within the language.
>
>     this was the idea - to give a good tool instead of implementing
>     every possible use-case in the language.
>
>         Could it also support references?
>
>         <<sanitize(&$a)>>
>         function foo($a) {
>
>         }
>
>     yes. "&$a" is a valid PHP expression.
>
>     If you plan to use this, I would appreciate, if you to build the
>     patched PHP and try it.
>     The early we find problems the better feature we will get at the end.
>
>     Thanks. Dmitry.
>
>
>         On 21 Apr 2016 10:13 p.m., "Dmitry Stogov" <dmitry@zend.com
>         <mailto:dmitry@zend.com> <mailto:dmitry@zend.com
>         <mailto:dmitry@zend.com>>> wrote:
>
>             Hi,
>
>
>             I would like to present an RFC proposing support for native
>             annotation.
>
>             The naming, syntax and behavior are mostly influenced by HHVM
>             Hack, but not exactly the same.
>
>             The most interesting difference is an ability to use
>         arbitrary PHP
>             expressions as attribute values.
>
>             These expressions are not evaluated, but stored as
>         Abstract Syntax
>             Trees, and later may be accessed (node by node) in PHP
>         extensions,
>             preprocessors and PHP scripts their selves. I think this
>         ability
>             may be useful for "Design By Contract", other formal
>         verification
>             systems, Aspect Oriented Programming, etc
>
>
>         https://wiki.php.net/rfc/attributes
>
>
>             Note that this approach is going to be native, in contrast to
>             doc-comment approach that uses not well defined syntax,
>         and even
>             not parsed by PHP itself.
>
>
>             Additional ideas, endorsement and criticism are welcome.
>
>
>             Thanks. Dmitry.
>
>
>
>
>
> -- 
> Guilherme Blanco
> Lead Architect at E-Block

---

## #92630 — Dmitry Stogov — 2016-04-22T07:17:42+00:00

URL: https://externals.io/message/92609#92630 · In reply to: #92626

> 
> > […]
> I'm trying to imagine where the benefit of non-constant expressions comes in.
>
> <<foo($a < 1)>>
>
> Assuming we roll in php-ast at the same time (which is a big addition,
> IMO, and deserves its own separate RFC), what are users meant to do
> with this?  Even if there's a use-case here, one could accomplish the
> same thing with:
>
> <<foo('$a < 1')>>
>
> And manually running that string into php-ast if that's what the caller wanted.

Good point. It's really not a big deal to run 
ast\parse_code($r->getAttributes()["foo"])
This would simplify the implementation a bit.
>
> Also, maybe I missed it, but I didn't see an answer to the question of
> ambiguity between parsing the above as a straight string, versus
> parsing it as a ZEND_AST_ZVAL.  I'm sure the answer is "If the AST
> tree is just a ZVAL, then it's provided as the compile-time
> expression, but what about something else like this:
>
> <<foo(1+1)>>
>
> Logically, this is reducible to a single compile-time value, but it's
> a complex expression, so would it be the value int(2)? Or
> ZEND_AST_BINARY_OP(int(1), int(1))?
Currently this going to be an AST - ZEND_AST_BINARY_OP(int(1), int(1))
>
> I just think that over-engineers what should be a simple annotation feature.

This makes sense. I think, I'll follow your suggestion.
The only missing ability is syntax check for <expression> attribute values.

>
> All that said, I love the proposal overall, and I can't wait to
> propose builtin annotations like <<__Memoize>>, <<__Mock>>, and
> similar.
I'm looking forward as well. :)

Thanks. Dmitry.

>
> -Sara

---

## #92631 — Dominic Grostate — 2016-04-22T08:31:26+00:00

URL: https://externals.io/message/92609#92631

I'm having a crack at it now.  Seeing if I can use it to plug a new
Annotation driver for Doctrine.

Couple of things I've found so far are:

<<Entity>> with empty args doesn't work.
<<ORM\Entity>> namespace doesn't work.

On the subject of using @, that could denote a class constructor, unless
someone already mentioned that.






This is amazing.  It would actually allow us to implement our automated
assertions ourselves, as opposed to requiring it within the language.

this was the idea - to give a good tool instead of implementing every
possible use-case in the language.


Could it also support references?

<<sanitize(&$a)>>
function foo($a) {

}

yes. "&$a" is a valid PHP expression.

If you plan to use this, I would appreciate, if you to build the patched
PHP and try it.
The early we find problems the better feature we will get at the end.

Thanks. Dmitry.




> Hi,
>
>
> I would like to present an RFC proposing support for native annotation.
>
> The naming, syntax and behavior are mostly influenced by HHVM Hack, but
> not exactly the same.
>
> The most interesting difference is an ability to use arbitrary PHP
> expressions as attribute values.
>
> These expressions are not evaluated, but stored as Abstract Syntax Trees,
> and later may be accessed (node by node) in PHP extensions, preprocessors
> and PHP scripts their selves. I think this ability may be useful for
> "Design By Contract", other formal verification systems, Aspect Oriented
> Programming, etc
>
>
> https://wiki.php.net/rfc/attributes
>
>
> Note that this approach is going to be native, in contrast to doc-comment
> approach that uses not well defined syntax, and even not parsed by PHP
> itself.
>
>
> Additional ideas, endorsement and criticism are welcome.
>
>
> Thanks. Dmitry.

---

## #92632 — Jordi Boggiano — 2016-04-22T09:04:42+00:00

URL: https://externals.io/message/92609#92632 · In reply to: #92630

>
>
> 
> > […]
>
> Good point. It's really not a big deal to run
> ast\parse_code($r->getAttributes()["foo"])
> This would simplify the implementation a bit.

I can't speak for the implementation details, but I see a few benefits 
of having real AST vs a string.. You get syntax highlighting in editors, 
and most importantly compile time syntax errors if you messed up.

Cheers

-- 
Jordi Boggiano
@seldaek - http://seld.be

---

## #92636 — Lester Caine — 2016-04-22T10:30:48+00:00

URL: https://externals.io/message/92609#92636 · In reply to: #92609

> I would like to present an RFC proposing support for native annotation.

I thought that the debate had been completed on annotation, and since
most of the work can be done in a stand alone extension, the various
parties were going to take that route and develop working options which
could then be compared to decide if any provide a suitable replacement
for the current docbloc 'process' that most of the IDE's currently
recognise.

There is room for proper documentation of the current standard as some
elements are not followed reliably, but on the whole the system works,
and any of the new extensions need to be addressed via IDE projects
before they can replace that.

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #92637 — Dmitry Stogov — 2016-04-22T11:13:34+00:00

URL: https://externals.io/message/92609#92637

<<Entry>> works fine


sapi/cli/php attr6.php
array(1) {
  ["Entity"]=>
  bool(true)
}


$ cat attr6.php
<?php
<<Entity>>
function foo() {}
$r = new ReflectionFunction("foo");
var_dump($r->getAttributes());
?>
[dmitry@tpl2 CGI-DEBUG]$ sapi/cli/php attr6.php
array(1) {
  ["Entity"]=>
  bool(true)
}


<<ORM\Entity>> - doesn't work now, but I'll implement this and extend RFC on next week.


Thanks. Dmitry.

---

## #92639 — Thomas Punt — 2016-04-22T11:46:27+00:00

URL: https://externals.io/message/92609#92639 · In reply to: #92609

Hi Dmitry!

> Hi,
>
>
> I would like to present an RFC proposing support for native annotation.
>
> The naming, syntax and behavior are mostly influenced by HHVM Hack, but not exactly the same.
>
> The most interesting difference is an ability to use arbitrary PHP expressions as attribute values.
>
> These expressions are not evaluated, but stored as Abstract Syntax Trees, and later may be accessed (node by node) in PHP extensions, preprocessors and PHP scripts their selves. I think this ability may be useful for "Design By Contract", other formal verification systems, Aspect Oriented Programming, etc
>
>
> https://wiki.php.net/rfc/attributes
>
>
> Note that this approach is going to be native, in contrast to doc-comment approach that uses not well defined syntax, and even not parsed by PHP itself.
>
>
> Additional ideas, endorsement and criticism are welcome.

Just a couple of comments on this:

1. I'd definitely reuse the php-ast extension for parsing the code into an
AST. It performs a number of transformations on PHP's underlying AST
that make it much nicer to use (namely better consistency). It is also
less fragile by having the abstraction between PHP's internal AST and
the AST that is exposed to userland (enabling for internal AST changes
without impacting the AST exposed to userland).

2. You mentioned about moving some of the php-ast extension into core.
I wonder if it would be better to just move the whole extension into the
core first, and then enable this functionality if the php-ast extension is
enabled.

Also, slightly tangential, but the RFC says attributes are supported on
class constants, yet doc comments (IIRC) are not. I wonder if support
for doc comments should be added for class constants?

Thanks,
Tom

---

## #92648 — guilhermeblanco@gmail.com — 2016-04-22T15:39:52+00:00

URL: https://externals.io/message/92609#92648 · In reply to: #92629

>
>
> 
>
> Hi Dmitry,
>
> As a previous suggester of metadata information built-in into PHP, and
> also one of developers of the most used metadata library written in PHP, I
> understand this feature implementation requires several design decisions
> and also a good understanding of specific situations users may require.
>
> While I am a strong supporter of a more robust solution, this is already a
> good start.
> A few things I'd like to ask for my own understanding and also suggestions
> too:
>
> 1- I understand you took a minimalistic approach towards a "dumb"
> implementation for attributes (when I mean "dumb", the idea here is towards
> a non-OO approach). Can you explain your motivations towards this approach?
>
> I see two distinct approaches of implementation for this feature. Both of
> them have some common demands, like lazy initialization of metadata. Here
> they are:
>
> - Simplistic approach, which lets consumers of the feature do all the work
> related to validation, assertion of valid keys, values, etc
> This does not invalidate the ability to leverage of some features that a
> more robust implementation demands.
>
> - Robust approach: language takes the burden of instantiating complex
> structures, validating, assertion of valid keys, values, if this complex
> structure is allowed to be instantiated in that given class, method, etc.
>
>
> I didn't exactly understand what do you suggest.
> If you are talking about Attribute objects initialization during
> compilation - this is just not possible from implementation point of view.
> Now attributes may be stored in opcache SHM and relive request boundary.
> Objects can't relive requests.
>


I know that object instances are not cross-requests. Explicitly, I
mentioned that both approaches require lazy-initialization (which means,
whenever you call getAttributes() or getAttribute()).

What I mentioning is that your approach is basically a new key/value syntax
that are used specifically for Attributes. We could easily turn this into a
more robust approach if instead of defining key/value pairs, we instantiate
objects or call functions. You already demonstrated interest to support
<<ORM\Entity>> reusing the imports (which is our biggest headache in
Doctrine Annotations), so why not issue constructor or function calls
there? That would simplify the work needed for consumers and also add room
for later improvements.

So basically in this example:

use Doctrine\ORM;

<<ORM\Entity("user")>>
class User {}

$reflClass = new \ReflectionClass("User");
var_dump($reflClass->getAttributes());

We'd be changing from this:

array(1) {
  ["Doctrine\ORM\Entity"]=>
  array(1) {
    [0]=>
    string(4) "user"
  }
}

Into this:

array(1) {
  ["Doctrine\ORM\Entity"]=>
  object(Doctrine\ORM\Entity)#1 (1) {
    ["tableName"]=>
    string(4) "user"
  }
}


>
> 1- Your approach is basically defining an array. Could you explain your
> line of thinking on why you didn't consider a syntax like the one below?
>
> <["key" => "value"]>
> class Foo {}
>
> I didn't try to invite new syntax. Just completely took it from HHVM.
>

My idea was based on your current proposal, which is basically a way to
define key/value pairs.
If you decide to go minimalistic, that is probably my best line of thinking.


>
>
>
> 2- I see that you added support over functions, classes, constants and
> properties. According to the RFC, getAttributes() was added over
> ReflectionFunction. Is there a reason why support was not added to methods
> (ReflectionMethod extends ReflectionFunctionAbstract, which was not
> mentioned on RFC)? Any reason to not support it in function/method
> parameters?
>
> ReflectionMethod is a child of ReflectinFunction, so it's supported.
>
Attributes are allowed for the same entities as doc-comments (they are not
> allowed for parameters)
>

I was asking if there was a purpose to not support Attributes over
ReflectionParameter. Example:

class Foo {
    public function bar(<<Qux>> Bar $bar) : bool {
        // ...
    }
}

$reflClass = new \ReflectionClas("Foo");
$reflMethod = $reflClass->getMethod("bar");
$reflParameter = $reflMethod->getParameters()[0];

var_dump($reflParameter->getAttributes());


>
>
>
> 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.


>
> 4- I understand that a more robust attribute solution would be required to
> achieve this, but one of the biggest advantages of AOP is the ability to
> perform custom logic before, after or around... However, I don't know if
> any kind of triggers came in your head or are planned as a future RFC.
> Let me highlight one example: Every time a class, property or method is
> called that is annotated as <<deprecated>>, I would like to issue an
> `E_USER_DEPRECATED` warning. A trigger-like solution would be required. Did
> this concept came to your mind?
>
> This is not a subject of this RFC.
> Attributes provides a storage for metadata, but don't define how to use
> them.
> Especially, for your use-case:
> 1) it's possible to create preprocessor that embeds corresponding
> `trigger_error()` call
> 2) it's possible to write a PHP extension that plugs-into compiler chain
> and checks <<deprecated>> attribute for each compiles function, then sets
> ZEND_ACC_DEPRECATED flag
> 3) It's also possible to override DO_FCALL opcodes and perform checks
> there (this is inefficient)
>
>
With this simplistic approach, I agree there's 0 value into considering
this.
However, taking a more robust approach would potentially open this
possibility through a simpler extension.



> Thanks. Dmitry.
>
>
>
>
>
> Regards,
>
> 
>
> > […]
>
>
> --
> Guilherme Blanco
> Lead Architect at E-Block
>
>
>


-- 
Guilherme Blanco
Lead Architect at E-Block

---

## #92649 — Larry Garfield — 2016-04-22T15:56:13+00:00

URL: https://externals.io/message/92609#92649 · In reply to: #92648

> 
>
>
> > […]
> 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.)

-- 
--Larry Garfield

---

## #92650 — Pierrick Charron — 2016-04-22T19:15:48+00:00

URL: https://externals.io/message/92609#92650 · In reply to: #92648

On 22 April 2016 at 11:39, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:

> 
>
> > […]
> I
> > […]
> a
> > […]
> suggestions
> > […]
> towards
> > […]
> approach?
> > […]
> work
> > […]
> view.
> > […]
>
>
> I know that object instances are not cross-requests. Explicitly, I
> mentioned that both approaches require lazy-initialization (which means,
> whenever you call getAttributes() or getAttribute()).
>
> What I mentioning is that your approach is basically a new key/value syntax
> that are used specifically for Attributes. We could easily turn this into a
> more robust approach if instead of defining key/value pairs, we instantiate
> objects or call functions. You already demonstrated interest to support
> <<ORM\Entity>> reusing the imports (which is our biggest headache in
> Doctrine Annotations), so why not issue constructor or function calls
> there? That would simplify the work needed for consumers and also add room
> for later improvements.
>
> So basically in this example:
>
> use Doctrine\ORM;
>
> <<ORM\Entity("user")>>
> class User {}
>
> $reflClass = new \ReflectionClass("User");
> var_dump($reflClass->getAttributes());
>
> We'd be changing from this:
>
> array(1) {
>   ["Doctrine\ORM\Entity"]=>
>   array(1) {
>     [0]=>
>     string(4) "user"
>   }
> }
>
> Into this:
>
> array(1) {
>   ["Doctrine\ORM\Entity"]=>
>   object(Doctrine\ORM\Entity)#1 (1) {
>     ["tableName"]=>
>     string(4) "user"
>   }
> }
>

+1


>
>
> > […]
>
> My idea was based on your current proposal, which is basically a way to
> define key/value pairs.
> If you decide to go minimalistic, that is probably my best line of
> thinking.
>
>
> > […]
> methods
> > […]
> Attributes are allowed for the same entities as doc-comments (they are not
> > […]
>
> I was asking if there was a purpose to not support Attributes over
> ReflectionParameter. Example:
>
> class Foo {
>     public function bar(<<Qux>> Bar $bar) : bool {
>         // ...
>     }
> }
>
> $reflClass = new \ReflectionClas("Foo");
> $reflMethod = $reflClass->getMethod("bar");
> $reflParameter = $reflMethod->getParameters()[0];
>
> var_dump($reflParameter->getAttributes());
>
>
> > […]
>
> 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.
>
>
> > […]
> to
> > […]
> With this simplistic approach, I agree there's 0 value into considering
> this.
> However, taking a more robust approach would potentially open this
> possibility through a simpler extension.
>
>
>
> > […]
>
>
> --
> Guilherme Blanco
> Lead Architect at E-Block

---

## #92653 — Dmitry Stogov — 2016-04-23T10:43:27+00:00

URL: https://externals.io/message/92609#92653 · In reply to: #92639

> Hi Dmitry!
>
> > […]
> Just a couple of comments on this:
>
> 1. I'd definitely reuse the php-ast extension for parsing the code into an
> AST. It performs a number of transformations on PHP's underlying AST
> that make it much nicer to use (namely better consistency). It is also
> less fragile by having the abstraction between PHP's internal AST and
> the AST that is exposed to userland (enabling for internal AST changes
> without impacting the AST exposed to userland).
I'm not sure. Both approaches make sense.

>
> 2. You mentioned about moving some of the php-ast extension into core.
> I wonder if it would be better to just move the whole extension into the
> core first, and then enable this functionality if the php-ast extension is
> enabled.
Even if we move php-ast into core (I think we will do it), it's going to 
be optional.
However attributes should always work.

>
> Also, slightly tangential, but the RFC says attributes are supported on
> class constants, yet doc comments (IIRC) are not. I wonder if support
> for doc comments should be added for class constants?

it is already implemented.

Thanks. Dmitry.
>
> Thanks,
> Tom

---

Next page: https://externals.io/message/92609.md?page=2
