On 22 April 2016 at 11:39, guilhermebla...@gmail.com < guilhermebla...@gmail.com> wrote:
> On Fri, Apr 22, 2016 at 3:07 AM, Dmitry Stogov <dmi...@zend.com> wrote: > > > > > > > On 04/22/2016 04:05 AM, guilhermebla...@gmail.com wrote: > > > > 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 > > > > > > 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, > > > > On Thu, Apr 21, 2016 at 7:44 PM, Dmitry Stogov <dmi...@zend.com> wrote: > > > >> > >> > >> On 04/22/2016 02:16 AM, Dominic Grostate 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" < <dmi...@zend.com> > >>> dmi...@zend.com <mailto: <dmi...@zend.com>dmi...@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 > > > > > > > > > -- > Guilherme Blanco > Lead Architect at E-Block >