Edit report at https://bugs.php.net/bug.php?id=50029&edit=1

 ID:                 50029
 Comment by:         marc dot gray at gmail dot com
 Reported by:        marc dot gray at gmail dot com
 Summary:            Weird invoke issue on class as property
 Status:             Analyzed
 Type:               Feature/Change Request
 Package:            Class/Object related
 Operating System:   Ubuntu 9.04
 PHP Version:        5.3.0
 Block user comment: N
 Private report:     N

 New Comment:

I've been thinking about this since the same issue appears to exist with 
assigning a closure to a static 
variable too (tested in 5.3.5, 5.3.8 & 5.4alpha3.

//----------------------------------
// Create a very basic static class
class closureProperty {
        static public $myClosure;
}

// Assign a closure to a class property
closureProperty::$myClosure = function() { echo('Hi'); };

// Fatal error: Function name must be a string
closureProperty::$myClosure();

// Works as expected
$safeCopy = closureProperty::$myClosure;
$safeCopy();
//----------------------------------

I can understand why it happens with dynamic properties, apparently you can 
have a variable and function named 
identically? I admit I've never tried.

I would propose making identically named variables and functions as deprecated 
(does anyone who's any good 
actually do that? Talk about poor readability...) and implement a collision 
warning in the mean time. I would 
also suggest this makes less sense in a static case (due to $ variable prefix) 
than it did in a dynamic case, 
and should be changed.

If nothing else, some discussion on the matter would be lovely.

Thoughts?


Previous Comments:
------------------------------------------------------------------------
[2011-02-07 22:36:54] dhaarbrink at gmail dot com

@bkarwin: The control would be passed to __call(), since there is no way to 
disambiguate. __call() would then be responsible for deciding what to do.

I have to agree with Matthew, it's a huge WTF. It just doesn't work as it 
should (that's beyond what is expected).

------------------------------------------------------------------------
[2010-04-07 20:22:38] bkar...@php.net

How would Matthew's suggestion work if a magic __call() method is present?

class b {
  private $x;

  public function __call($method, $args) { echo "Called\n"; }

  function __construct() { 
    $this->x = new a(); 
    $this->x(); 
  } 

}

Should this execute $this->__call("x") and output "Called" or should it execute 
$this->x->__invoke() and output "Invoked"?

------------------------------------------------------------------------
[2010-04-07 14:52:19] ballouc at gmail dot com

I'm in agreement with the Matt's last suggestion.  I believe that errors should 
only be raised in the event of a collision.  The current implementation of the 
__invoke method, IMO, would not perform as a third party developer would have 
anticipated.  My personal choice would be to throw an E_WARNING for collisions 
as I have seen ~E_NOTICE far too often.  

Personally, I believe that an __invoke collision occurring would be more 
indicative of a developer error than intentional.  If this is not the case, and 
you find many people readily anticipate having both foo() and __invoke called 
in succession, this would need to be discussed further as that is also a viable 
option.

------------------------------------------------------------------------
[2010-04-07 13:41:14] weierophin...@php.net

I can understand wanting to ensure that collisions between existing methods and 
invokable properties don't occur, but when there aren't any collisions, it 
doesn't make sense.

I'd argue that the following behavior should be implemented:
* If no matching method exists, simply allow invoking.
* If a matching method exists, call the method, and raise either an E_NOTICE or 
E_WARNING indicating the collision.

Right now, it's a fairly big WTF moment -- you expect it to work, and instead 
get an E_FATAL. Copying to a temporary variable is code clutter, particularly 
when you know the object is invokable.

------------------------------------------------------------------------
[2009-11-02 15:58:23] ka...@php.net

There was lots of discussion about this, because it could override class 
methods like:

class Test { 
  private $closure;

  public function __construct() {
    $this->closure = function() {
      echo 'Hello World';
    };
  }

  public function closure() {
    echo 'Hello PHP';
  }

  public function call() {
    $this->closure();
  }
}

$test = new Test;

// Call Test::$closure or Test::closure() now?
$test->call();


What you need to do is to copy the instance into a variable like:
$closoure = $this->closure;
$closure();

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=50029


-- 
Edit this bug report at https://bugs.php.net/bug.php?id=50029&edit=1

Reply via email to