2012-08-30 50 views
2

確定我有以下在PHP中存儲一個閉合功能的類屬性

<?php 
    class foo{ 
     public $bar = NULL; 

     public function boo(){ 
      $this->bar(); 
     } 
    } 

    $mee = new foo(); 

    //save a closure function on the property 
    $mee->bar = function(){ 
     echo 'hahaha'; 
    }; 

    //invoke the closure function by using a class method 
    $mee->boo(); 
?> 

的代碼,你可以看到它運行在這裏http://codepad.org/s1jhi7cv

現在我想在這裏什麼是存儲閉合功能在類方法上。

以及閉包是儘可能我讀到它的文檔在這裏http://php.net/manual/en/functions.anonymous.php

這可能嗎?我錯了嗎?請糾正我

+0

你不應該爲此使用「codepad.org」,他們正在使用一個尚未支持閉包的漂亮舊版本的PHP。 – Niko

回答

10

您在codepad.org上的示例代碼不起作用,因爲codepad.org使用PHP 5.2.5,並且僅在5.3中添加了閉包支持。

然而,你的代碼也不會在支持關閉一個PHP版本的工作,雖然你會得到一個不同的錯誤:http://codepad.viper-7.com/Ob0bH5

這是目前PHP的限制。 $obj->member()尋找名爲member的方法,並且不會查看屬性以查看它們是否可調用。坦率地說,這很煩人。

我知道的,使這項工作不call_user_func()/call_user_func_array()的唯一方法是:

public function boo() { 
    $func = $this->bar; 
    $func(); 
} 
+0

似乎沒有運行.. http://codepad.org/AUkcKHPC –

+2

@Mahan它不會在codepad.org上工作(見上面的編輯),你至少需要5.3。作品[這裏](http://codepad.viper-7.com/dB3ckH) – DaveRandom

1

PHP是不是一個基於原型的語言,因此你無法重新定義函數

2

您將無法去做。

就拿這個代碼:

class T { 
    function foo() { 
    echo 'T::foo'; 
    } 
} 

$t = new T; 
$t->foo = function() { 
    echo 'Closure::foo'; 
}; 
$t->foo(); 

它適用於PHP 5.4.6和/或PHP 5.3.16罰款,但它會導致T::foo得到打印。

發生這種情況是因爲PHP中的方法不是可修改的類屬性,因爲它們例如在javascript中。

然而,

$foo = $t->foo; 
$foo(); 

將打印Closure::foo預期。

1

使用__call捕獲所有未定義的方法,然後查找閉包並調用它。看看我的帖子SitePoint thread

+0

你能舉個例子代碼嗎?對不起,我沒有經驗使用__call謝謝 –

+0

@Mahan請參閱編輯與主題鏈接。 –

+0

您可以在[我的答案](http://stackoverflow.com/a/12196625/367456)中找到示例性的'__call'函數。 – hakre

4

你需要利用PHP的一些魔術功能(__call)來利用它。例如,從Extendable延伸:例如:

class Extendable { 
    static function import($context) { 
     $self = new static(); 
     while (is_callable($context)) $context = $context($self); 
     if (is_array($context) || is_object($context) || is_a($context, 'Traversable')) { 
      foreach($context as $key => $value) 
       $self->$key = &$value; # preserve keys if 
     } 
     return $self; 
    } 
    public function __call($name, $args) { 
     if (isset($this->$name) && is_callable($this->$name)) { 
      return call_user_func_array($this->$name, $args); 
     } 
     throw new BadFunctionCallException(sprintf('Undefined function %s.', $name)); 
    } 
} 

您可以完成這項工作。這不是很好。背景和例子都在我的博客文章之一:

你自然可以實現該功能的魔法你自己了。

+0

不錯,如果你想用這個功能擴展一些其他的基類,可以很容易地變成一個特徵。 – DaveRandom

+0

是的,沒錯。然而,我不知道如果使用特質的魔法功能並不是首先要求麻煩;) – hakre

+0

+1。不過,我會拋出['BadMethodCallException'](http://www.php.net/manual/en/class.badmethodcallexception.php)。 – FtDRbwLXw6

1

使用call_user_func()功能:

<?php 
    class foo{ 
     public $bar = NULL; 

     public function boo(){ 
      call_user_func($this->bar); 
     } 
    } 

    $mee = new foo(); 

    //save a closure function on the property 
    $mee->bar = function(){ 
     echo 'hahaha'; 
    }; 

    //invoke the closure function by using a class method 
    $mee->boo(); 

這將顯示 「ahahah」

希望它能幫助。