Hello David,

Tuesday, December 23, 2008, 5:02:43 PM, you wrote:

> Hi folks,

> I played with __invoke today:

> class Curry
> {
>    protected $callable;
>    protected $args;

>    public static function create($callable)
>    {
>      $curry = new self($callable, array_slice(func_get_args(), 1));
>      return $curry;
>    }

>    protected function __construct($callable, $args)
>    {
>      $this->callable = $callable;
>      $this->args = $args;
>    }

>    public function __invoke()
>    {
>      return call_user_func_array($this->callable, array_merge($this- 
 >>args, func_get_args()));
>    }
> }

> However, it doesn't work consistently.

> This works fine:
>    $d = new DateTime();
>    $getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
>    echo $getAtom();

> This gives a fatal "Call to undefined method DateTime::getAtom()"
>    $d = new DateTime();
>    $d->getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
>    echo $d->getAtom();

> Is that intentional?

So far it is. Yet I as much as you do not like the inconsistency. So I
spend a little bit on providing the following patch that should do what
you were looking for.

The disadvantage: Calling properties is case sensitive while calling
methods isn't. But since this has nothign to do with this patch and the
patch only increases consistency I am all for applying it.

Comments? Lukas/Johannes?

Oh I hate that case insensitivity.... and inconsistency....

> Cheers,

> David





Best regards,
 Marcus
Index: Zend/zend_object_handlers.c
===================================================================
RCS file: /repository/ZendEngine2/zend_object_handlers.c,v
retrieving revision 1.135.2.6.2.22.2.23
diff -u -p -d -r1.135.2.6.2.22.2.23 zend_object_handlers.c
--- Zend/zend_object_handlers.c 31 Dec 2008 11:15:32 -0000      
1.135.2.6.2.22.2.23
+++ Zend/zend_object_handlers.c 31 Dec 2008 16:26:52 -0000
@@ -791,6 +791,22 @@ static union _zend_function *zend_std_ge
 
        zobj = Z_OBJ_P(object);
        if (zend_hash_find(&zobj->ce->function_table, lc_method_name, 
method_len+1, (void **)&fbc) == FAILURE) {
+               if (Z_OBJ_HT_PP(object_ptr)->read_property) {
+                       zval *callable, property, *callable_obj;
+                       zend_class_entry *ce_ptr;
+                       
+                       INIT_PZVAL(&property);
+                       ZVAL_STRINGL(&property, method_name, method_len, 0);
+                       callable = 
Z_OBJ_HANDLER_PP(object_ptr,read_property)(*object_ptr, &property, BP_VAR_IS 
TSRMLS_CC);
+
+                       if (Z_TYPE_P(callable) == IS_OBJECT
+                       && Z_OBJ_HANDLER_P(callable, get_closure)
+                       && Z_OBJ_HANDLER_P(callable, get_closure)(callable, 
&ce_ptr, &fbc, &callable_obj TSRMLS_CC) == SUCCESS) {
+                               *object_ptr = callable_obj;
+                               free_alloca(lc_method_name, use_heap);
+                               return fbc;
+                       }
+               } 
                free_alloca(lc_method_name, use_heap);
                if (zobj->ce->__call) {
                        zend_internal_function *call_user_call = 
emalloc(sizeof(zend_internal_function));
Index: Zend/tests/closure_033.phpt
===================================================================
RCS file: Zend/tests/closure_033.phpt
diff -N Zend/tests/closure_033.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/closure_033.phpt 31 Dec 2008 16:26:52 -0000
@@ -0,0 +1,31 @@
+--TEST--
+Closure 033: Calling property Closure
+--FILE--
+<?php
+
+class Test {
+       public $func;
+       function __construct() {
+               $this->func = function() {
+                       echo __METHOD__ . "()\n";
+               };
+       }
+}
+
+$o = new Test;
+ReflectionProperty::export($o, 'func');
+var_dump($o->func);
+$f = $o->func;
+$f();
+$o->func();
+
+?>
+===DONE===
+--EXPECTF--
+Property [ <default> public $func ]
+
+object(Closure)#%d (0) {
+}
+Test::{closure}()
+Test::{closure}()
+===DONE===
Index: Zend/tests/closure_034.phpt
===================================================================
RCS file: Zend/tests/closure_034.phpt
diff -N Zend/tests/closure_034.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/closure_034.phpt 31 Dec 2008 16:26:52 -0000
@@ -0,0 +1,46 @@
+--TEST--
+Closure 034: Calling property supporting __invoke
+--FILE--
+<?php
+
+class Curry
+{
+  protected $callable;
+  protected $args;
+
+  public static function create($callable)
+  {
+    $curry = new self($callable, array_slice(func_get_args(), 1));
+    return $curry;
+  }
+
+  protected function __construct($callable, $args)
+  {
+    $this->callable = $callable;
+    $this->args = $args;
+  }
+
+  public function __invoke()
+  {
+    return call_user_func_array($this->callable, array_merge($this->args, 
func_get_args()));
+  }
+}
+
+$d = new DateTime();
+$getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
+var_dump(is_Callable($getAtom));
+var_dump($getAtom());
+
+$d = new DateTime();
+$d->getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
+var_dump(is_Callable($d->getAtom));
+var_dump($d->getAtom());
+
+?>
+===DONE===
+--EXPECTF--
+bool(true)
+string(%d) "2%d-%d-%dT%d:%d:%d%s"
+bool(true)
+string(%d) "2%d-%d-%dT%d:%d:%d%s"
+===DONE===
-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to