Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:65546 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 74803 invoked from network); 31 Jan 2013 19:52:58 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 31 Jan 2013 19:52:58 -0000 Authentication-Results: pb1.pair.com smtp.mail=nathan.bruer@starin.biz; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=nathan.bruer@starin.biz; sender-id=unknown Received-SPF: error (pb1.pair.com: domain starin.biz from 207.198.105.69 cause and error) X-PHP-List-Original-Sender: nathan.bruer@starin.biz X-Host-Fingerprint: 207.198.105.69 hawk.starindns.com Received: from [207.198.105.69] ([207.198.105.69:34916] helo=hawk.starindns.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id A5/C6-25207-89BCA015 for ; Thu, 31 Jan 2013 14:52:56 -0500 Received: from 173-167-160-145-illinois.hfc.comcastbusiness.net ([173.167.160.145]:56153 helo=NathanBruerHP) by hawk.starindns.com with esmtpa (Exim 4.80) (envelope-from ) id 1U10Bo-00066e-DZ; Thu, 31 Jan 2013 13:52:52 -0600 Sender: "Nathan Bruer" To: "'Alexander Lissachenko'" , "'Sebastian Krebs'" Cc: "'PHP internals list'" References: In-Reply-To: Date: Thu, 31 Jan 2013 13:53:00 -0600 Message-ID: <00b601cdffec$93541ba0$b9fc52e0$@starin.biz> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Mailer: Microsoft Outlook 14.0 thread-index: AQJijmfokNowIxESwWxiB7laUR+PtQINxqo5Aqoe0nMCfkMqtwEh67YFlvfpbVA= Content-Language: en-us X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - hawk.starindns.com X-AntiAbuse: Original Domain - lists.php.net X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - starin.biz X-Get-Message-Sender-Via: hawk.starindns.com: authenticated_id: nathan.bruer@starin.biz Subject: RE: [PHP-DEV] [Reflection] Improve logic of ReflectionMethod->invokeArgs() for static methods From: nathan@starin.biz Maybe I can help explain a good example on were this is useful as I also = suggested this improvement and created the patch for it: = (http://bugs.php.net/bug.php?id=3D62113) This is actually something I am using in one of my primary projects as a = framework (this example shows the concept not the actual code I am = using). This allows you to create new "Models" and extend (using traits) = the specific functions you'd like to attach to each extended model = class. /* Was a bit large so I posted here */ https://gist.github.com/4685694 There is a workaround so it was not super important for me to push for = it to be implemented (see commented code from line: 13-24). Full breakdown of what it does: There is a primary "Model" abstract class which pre-defines and forces = certain functions and variables to be set. There are various traits set = which a user may define themselves that allow certain parts of the code = to be "hooked" into and modify it's behavior without having to = re-declare the entire function. The advantages to this is that it allows = new Models to be added and extended without having to worry about = replacing an entire function and losing any potential updates to the = original function and gives the ability for multiple traits to hook = themselves into specific functions. In this example I have 2 traits, = "Check_Permissions" and "Log_Changes" which both do a dummed down = version of their job... If a certain Model needs to be logged for when = changes happen it can just add the trait "Log_Changes" to it and it will = auto-hook into the update and create functions. If a certain model needs = permission checks to update or insert it can extend the = "Check_Permissions" trait. (although in my example one extends the = "after" function hook and the other extends the "before" function hook, = the idea of why it'd be useful is good enough). Although yes there is a workaround, the workaround requires a new = closure to be created for each function being executed every time. but = if the "ReflectionMethod::invokeArgs()" function would allow the first = argument to be a string of class or the object itself it wants to bind = too it would save a new closure from having to be created for every hook = being executed. (Sorry for the long code, but I wanted to make sure I got my point = across on why it'd be useful) Software Developer Nathan Bruer -----Original Message----- From: Alexander Lissachenko [mailto:lisachenko.it@gmail.com]=20 Sent: Monday, January 14, 2013 2:16 PM To: Sebastian Krebs Cc: PHP internals list Subject: Re: [PHP-DEV] [Reflection] Improve logic of = ReflectionMethod->invokeArgs() for static methods Probably, it will be better to give a link to the one of examples of AOP = integration for laravel framework (requires 5.4.10 to work): https://github.com/lisachenko/laravel-aspect (just clone, install = dependencies and look at result) I need to perform weaving of aspects into the original methods, so here = is an example of generated source code: getAliases(), $aliases); static::$instance->setAliases($aliases); return static::$instance; } /** * Load a class alias if it is registered. * * @param string $alias * @return void */ public function load($alias) { if (isset($this->aliases[$alias])) { return class_alias($this->aliases[$alias], $alias); } } // more source code here } class AliasLoader extends AliasLoader__AopProxied { /** *Property was created automatically, do not change it manually */ private static $__joinPoints =3D array(); // some source code here /** * Get or create the singleton alias loader instance. * * @param array $aliases * @return Illuminate\Foundation\AliasLoader */ public static function getInstance(array $aliases =3D array()) { return = self::$__joinPoints['static:getInstance']->__invoke(get_called_class(), array($aliases)); } /** * Load a class alias if it is registered. * * @param string $alias * @return void */ public function load($alias) { return self::$__joinPoints['method:load']->__invoke($this, array($alias)); } // some source code here } You can notice, that original class name is pointing to the decorator = class after weaving. Source code still use $class =3D new AliasLoader(), = but the class now contains additional logic that was introduced by = aspects. 2013/1/14 Sebastian Krebs : > > > > 2013/1/14 Alexander Lissachenko >> >> My use-case is weaving aspects into the methods. Yeah! ) >> >> So, I take the original class, rename it and then create a decorator=20 >> class instead of original class with overridden dynamic and static=20 >> methods. Method in the decorator should make some specific logic and=20 >> then just invokes the original static method with Reflection, but the = >> scope should be also correct. >> >> For example, previous class First will be renamed during load-time to = >> the First_AopProxied: >> >> class First_AopProxied >> { >> public static function foo() >> { >> echo get_called_class(); >> } >> } >> >> and decorator will be created >> >> class First extends First_AopProxied >> { >> public static function foo() >> { >> // some logic here, that should call parent method and=20 >> preserve the scope (class First) >> // can not use parent::foo() here, because around advice=20 >> should be able to call this method somewhere in the closure... >> } >> } > > > I must say this example is not really better than the last one (it=20 > feels like it is exactly the same with 2 lines more comments). Also I=20 > don't know, what you mean by "call this method somewhere in the=20 > closure"; which closure?!? > I guess you are in fact looking for regular instance methods. > >> >> >> 2013/1/14 Sebastian Krebs : >> > >> > >> > >> > 2013/1/14 Alexander Lissachenko >> >> >> >> Hi! It's my first letter here ) >> >> >> >> I want to suggest a small improvement for=20 >> >> ReflectionMethod->invoke() and ReflectionMethod->invokeArgs()=20 >> >> methods to support LSB for overridden static methods. Currently,=20 >> >> for invoking static methods first argument should be null,=20 >> >> information about class (scope) is taken from the reflection=20 >> >> class. However, there is one issue that can not be solved at the = current time. >> >> >> >> Suppose, we have two classes: >> >> >> >> class First >> >> { >> >> public static function foo() >> >> { >> >> echo get_called_class(); >> >> } >> >> } >> >> >> >> class Second extends First >> >> { >> >> public static function foo() >> >> { >> >> echo "Do not call me, please"; >> >> } >> >> } >> >> >> >> Now I want to invoke the First::foo() method with Reflection from=20 >> >> the Second class scope for using LSB. Currently this is = impossible: >> >> $class =3D new ReflectionClass('First');=20 >> >> $class->getMethod('foo')->invokeArgs(null, array()); // Outputs=20 >> >> 'First' as no scope information is passed >> >> >> >> >> >> $class =3D new ReflectionClass('Second');=20 >> >> $class->getMethod('foo')->invokeArgs(null, array()); // Outputs=20 >> >> 'Do not call me, please' as method is redefined >> >> >> >> So, there is no way now to invoke the static First::foo() method=20 >> >> from the child scope because it was redefined. However, this can=20 >> >> be easily implemented by adding the scope for static methods=20 >> >> invocation (like >> >> Closure::bindTo()): >> >> >> >> $class =3D new ReflectionClass('First');=20 >> >> $class->getMethod('foo')->invokeArgs('Second', array()); //=20 >> >> Outputs 'Second' >> >> >> >> This improvement can be very useful for building proxies for=20 >> >> static methods, that use LSB. Can it be implemented for PHP = 5.3-5.5? Thanks! >> > >> > >> > Maybe it's just me, but could you explain which use-case want to = solve? >> > The >> > example isn't very useful, because you can achieve this quite easy=20 >> > without reflection. Also why do you override the method, when you=20 >> > don't want it to get called? Shouldn't they two separate methods=20 >> > then? >> > >> > > > class First >> > { >> > public static function foo() >> > { >> > echo get_called_class(); >> > } >> > } >> > >> > class Second extends First >> > { >> > public static function foo() >> > { >> > echo "Do not call me, please"; >> > } >> > public static function bar() { >> > parent::foo(); >> > } >> > } >> > Second::bar(); >> > >> > http://codepad.viper-7.com/fwG5GB >> > >> >> >> >> >> >> -- >> >> PHP Internals - PHP Runtime Development Mailing List To=20 >> >> unsubscribe, visit: http://www.php.net/unsub.php >> >> >> > >> > >> > >> > -- >> > github.com/KingCrunch > > > > > -- > github.com/KingCrunch -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, = visit: http://www.php.net/unsub.php