Hi! It's my first letter here )
I want to suggest a small improvement for ReflectionMethod->invoke()
and ReflectionMethod->invokeArgs() methods to support LSB for
overridden static methods. Currently, for invoking static methods
first argument should be null, information about class (scope) is
taken from the reflection 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 the
Second class scope for using LSB. Currently this is impossible:
$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs
'First' as no scope information is passed
$class = new ReflectionClass('Second');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs 'Do
not call me, please' as method is redefined
So, there is no way now to invoke the static First::foo() method from
the child scope because it was redefined. However, this can be easily
implemented by adding the scope for static methods invocation (like
Closure::bindTo()):
$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs('Second', array()); // Outputs 'Second'
This improvement can be very useful for building proxies for static
methods, that use LSB. Can it be implemented for PHP 5.3-5.5? Thanks!
2013/1/14 Alexander Lissachenko lisachenko.it@gmail.com
Hi! It's my first letter here )
I want to suggest a small improvement for ReflectionMethod->invoke()
and ReflectionMethod->invokeArgs() methods to support LSB for
overridden static methods. Currently, for invoking static methods
first argument should be null, information about class (scope) is
taken from the reflection 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()
{
echoget_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 the
Second class scope for using LSB. Currently this is impossible:
$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs
'First' as no scope information is passed
$class = new ReflectionClass('Second');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs 'Do
not call me, please' as method is redefinedSo, there is no way now to invoke the static First::foo() method from
the child scope because it was redefined. However, this can be easily
implemented by adding the scope for static methods invocation (like
Closure::bindTo()):$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs('Second', array()); // Outputs
'Second'This improvement can be very useful for building proxies for 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 without
reflection. Also why do you override the method, when you don't want it to
get called? Shouldn't they two separate methods then?
<?php
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
--
My use-case is weaving aspects into the methods. Yeah! )
So, I take the original class, rename it and then create a decorator
class instead of original class with overridden dynamic and static
methods. Method in the decorator should make some specific logic and
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
preserve the scope (class First)
// can not use parent::foo() here, because around advice
should be able to call this method somewhere in the closure...
}
}
2013/1/14 Sebastian Krebs krebs.seb@gmail.com:
2013/1/14 Alexander Lissachenko lisachenko.it@gmail.com
Hi! It's my first letter here )
I want to suggest a small improvement for ReflectionMethod->invoke()
and ReflectionMethod->invokeArgs() methods to support LSB for
overridden static methods. Currently, for invoking static methods
first argument should be null, information about class (scope) is
taken from the reflection 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()
{
echoget_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 the
Second class scope for using LSB. Currently this is impossible:
$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs
'First' as no scope information is passed$class = new ReflectionClass('Second');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs 'Do
not call me, please' as method is redefinedSo, there is no way now to invoke the static First::foo() method from
the child scope because it was redefined. However, this can be easily
implemented by adding the scope for static methods invocation (like
Closure::bindTo()):$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs('Second', array()); // Outputs
'Second'This improvement can be very useful for building proxies for 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 without
reflection. Also why do you override the method, when you don't want it to
get called? Shouldn't they two separate methods then?<?php
class First
{
public static function foo()
{
echoget_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
--
Alexander,
So, I take the original class, rename it and then create a decorator
class instead of original class with overridden dynamic and static
methods. Method in the decorator should make some specific logic and
then just invokes the original static method with Reflection, but the
scope should be also correct.
I have to ask: why? Why are you using static methods like that? It seems
to me that you're trying to use LSB to introduce a form of polymorphism
where it's not really designed for it... Why not just use instances in this
case (which are supported for your use-case)...?
Anthony
I do not use static methods, frameworks and applications use them )).
I just want to extend logic of class methods in the application with
custom behavior (Logging, Caching) and preserve original scope. It's
already done for PHP 5.4 with closures and my library works well with
any PHP framework. For 5.3 it works only for dynamic methods and
static methods without LSB.
2013/1/14 Anthony Ferrara ircmaxell@gmail.com:
Alexander,
So, I take the original class, rename it and then create a decorator
class instead of original class with overridden dynamic and static
methods. Method in the decorator should make some specific logic and
then just invokes the original static method with Reflection, but the
scope should be also correct.I have to ask: why? Why are you using static methods like that? It seems
to me that you're trying to use LSB to introduce a form of polymorphism
where it's not really designed for it... Why not just use instances in this
case (which are supported for your use-case)...?Anthony
2013/1/14 Alexander Lissachenko lisachenko.it@gmail.com
My use-case is weaving aspects into the methods. Yeah! )
So, I take the original class, rename it and then create a decorator
class instead of original class with overridden dynamic and static
methods. Method in the decorator should make some specific logic and
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()
{
echoget_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
preserve the scope (class First)
// can not use parent::foo() here, because around advice
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 feels
like it is exactly the same with 2 lines more comments). Also I don't know,
what you mean by "call this method somewhere in the closure"; which
closure?!?
I guess you are in fact looking for regular instance methods.
2013/1/14 Sebastian Krebs krebs.seb@gmail.com:
2013/1/14 Alexander Lissachenko lisachenko.it@gmail.com
Hi! It's my first letter here )
I want to suggest a small improvement for ReflectionMethod->invoke()
and ReflectionMethod->invokeArgs() methods to support LSB for
overridden static methods. Currently, for invoking static methods
first argument should be null, information about class (scope) is
taken from the reflection 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()
{
echoget_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 the
Second class scope for using LSB. Currently this is impossible:
$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs
'First' as no scope information is passed$class = new ReflectionClass('Second');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs 'Do
not call me, please' as method is redefinedSo, there is no way now to invoke the static First::foo() method from
the child scope because it was redefined. However, this can be easily
implemented by adding the scope for static methods invocation (like
Closure::bindTo()):$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs('Second', array()); // Outputs
'Second'This improvement can be very useful for building proxies for 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
without
reflection. Also why do you override the method, when you don't want it
to
get called? Shouldn't they two separate methods then?<?php
class First
{
public static function foo()
{
echoget_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
--
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:
<?php namespace Illuminate\Foundation;
class AliasLoader__AopProxied {
// .. source code here
/**
* Get or create the singleton alias loader instance.
*
* @param array $aliases
* @return Illuminate\Foundation\AliasLoader
*/
public static function getInstance(array $aliases = array())
{
if (is_null(static::$instance)) static::$instance = new static($aliases);
$aliases = array_merge(static::$instance->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 = 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 = 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 = new AliasLoader(),
but the class now contains additional logic that was introduced by
aspects.
2013/1/14 Sebastian Krebs krebs.seb@gmail.com:
2013/1/14 Alexander Lissachenko lisachenko.it@gmail.com
My use-case is weaving aspects into the methods. Yeah! )
So, I take the original class, rename it and then create a decorator
class instead of original class with overridden dynamic and static
methods. Method in the decorator should make some specific logic and
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()
{
echoget_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
preserve the scope (class First)
// can not use parent::foo() here, because around advice
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 feels
like it is exactly the same with 2 lines more comments). Also I don't know,
what you mean by "call this method somewhere in the closure"; which
closure?!?
I guess you are in fact looking for regular instance methods.2013/1/14 Sebastian Krebs krebs.seb@gmail.com:
2013/1/14 Alexander Lissachenko lisachenko.it@gmail.com
Hi! It's my first letter here )
I want to suggest a small improvement for ReflectionMethod->invoke()
and ReflectionMethod->invokeArgs() methods to support LSB for
overridden static methods. Currently, for invoking static methods
first argument should be null, information about class (scope) is
taken from the reflection 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()
{
echoget_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 the
Second class scope for using LSB. Currently this is impossible:
$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs
'First' as no scope information is passed$class = new ReflectionClass('Second');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs 'Do
not call me, please' as method is redefinedSo, there is no way now to invoke the static First::foo() method from
the child scope because it was redefined. However, this can be easily
implemented by adding the scope for static methods invocation (like
Closure::bindTo()):$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs('Second', array()); // Outputs
'Second'This improvement can be very useful for building proxies for 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
without
reflection. Also why do you override the method, when you don't want it
to
get called? Shouldn't they two separate methods then?<?php
class First
{
public static function foo()
{
echoget_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
--
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=62113)
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]
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:
<?php namespace Illuminate\Foundation;
class AliasLoader__AopProxied {
// .. source code here
/**
* Get or create the singleton alias loader instance.
*
* @param array $aliases
* @return Illuminate\Foundation\AliasLoader
*/
public static function getInstance(array $aliases = array())
{
if (is_null(static::$instance)) static::$instance = new static($aliases);
$aliases = array_merge(static::$instance->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 = 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 = 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 = new AliasLoader(), but the class now contains additional logic that was introduced by aspects.
2013/1/14 Sebastian Krebs krebs.seb@gmail.com:
2013/1/14 Alexander Lissachenko lisachenko.it@gmail.com
My use-case is weaving aspects into the methods. Yeah! )
So, I take the original class, rename it and then create a decorator
class instead of original class with overridden dynamic and static
methods. Method in the decorator should make some specific logic and
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()
{
echoget_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
preserve the scope (class First)
// can not use parent::foo() here, because around advice
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
feels like it is exactly the same with 2 lines more comments). Also I
don't know, what you mean by "call this method somewhere in the
closure"; which closure?!?
I guess you are in fact looking for regular instance methods.2013/1/14 Sebastian Krebs krebs.seb@gmail.com:
2013/1/14 Alexander Lissachenko lisachenko.it@gmail.com
Hi! It's my first letter here )
I want to suggest a small improvement for
ReflectionMethod->invoke() and ReflectionMethod->invokeArgs()
methods to support LSB for overridden static methods. Currently,
for invoking static methods first argument should be null,
information about class (scope) is taken from the reflection
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()
{
echoget_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
the Second class scope for using LSB. Currently this is impossible:
$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs
'First' as no scope information is passed$class = new ReflectionClass('Second');
$class->getMethod('foo')->invokeArgs(null, array()); // Outputs
'Do not call me, please' as method is redefinedSo, there is no way now to invoke the static First::foo() method
from the child scope because it was redefined. However, this can
be easily implemented by adding the scope for static methods
invocation (like
Closure::bindTo()):$class = new ReflectionClass('First');
$class->getMethod('foo')->invokeArgs('Second', array()); //
Outputs 'Second'This improvement can be very useful for building proxies for
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
without reflection. Also why do you override the method, when you
don't want it to get called? Shouldn't they two separate methods
then?<?php
class First
{
public static function foo()
{
echoget_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
--
To
unsubscribe, visit: http://www.php.net/unsub.php