2014-12-21 13 views
5

w JavaScript, mogę związać this do innej funkcji i wywołać ją z .call lub .applyPHP call_user_func wiążą thisArg jak Javascript rozmowy

W PHP mogę zrobić z call_user_func lub call_user_func_array, ale jak mogę związać $this do funkcja?

Javascript:

function greet() { 
    alert('Hello ' + this.name); 
} 

function SomeClass() {} 
SomeClass.prototype = { 
    name: 'John', 
    test: function() { 
    greet.call(this); 
    } 
} 

var me = new SomeClass(); 
me.test(); // Hello John 

PHP:

function greet() { 
    echo 'Hello ' . $this->name; 
} 

class SomeClass { 
    public $name = 'John'; 

    function test() { 
    call_user_func('greet'); 
    } 
} 

$me = new SomeClass; 
$me->test(); // Fatal error: Using $this when not in object context 

UPDATE:

Dzięki @deceze dla Reflection pomysł, Znalazłem te rozwiązania, ale nie sądzę, że to dobry dla wydajności (x10 wolniej niż bezpośrednie wywołanie), ale wyraźnie na czytanie.

ja napisałem dwie funkcje:

// See also Javascript: Function.prototype.apply() 
function function_apply($fn, $thisArg, $argsArray = array()) { 
    static $registry; 
    if (is_string($fn)) { 
    if (!isset($registry[$fn])) { 
     $ref = new \ReflectionFunction($fn); 
     $registry[$fn] = $ref->getClosure(); 
    } 
    $fn = $registry[$fn]; 
    } 
    return call_user_func_array($fn->bindTo($thisArg), $argsArray); 
} 

// See also Javascript: Function.prototype.call() 
function function_call($fn, $thisArg /*, arg1, arg2 ... */) { 
    return function_apply($fn, $thisArg, array_slice(func_get_args(), 2)); 
} 

i zastąpić call_user_func do function_call:

function greet() { 
    echo 'Hello ' . $this->name; 
} 

class SomeClass { 
    public $name = 'John'; 

    function test() { 
    function_call('greet', $this); 
    } 
} 

$me = new SomeClass; 
$me->test(); // Hello John 
+0

Dlaczego nie dodać argument tej funkcji i przekazać zmienną jako argument ? W przeciwnym razie może ci pomóc słowo kluczowe "use". (http://php.net/functions.anonymous) Ale nie jestem naprawdę pewien. –

+0

Możliwy duplikat http://stackoverflow.com/questions/27014664/php-equivalent-of-javascript-bind – haim770

+0

ponieważ wiem, że jest to rozwiązanie, które przekazuje '$ this' jako argument, po prostu ciekawy czy istnieje jakakolwiek możliwość działania JavaScript – user1542316

Odpowiedz

3

PHP nie jest javascript: nie można swobodnie mieszać funkcje zdefiniowane wewnątrz i na zajęcia na zewnątrz, przełączenie kontekstu jak je nazywacie. Każda próba użycia metody $this w opisany sposób spowoduje błąd krytyczny: Using $this when not in object context.

Znowu ten sam efekt można osiągnąć dzięki prostej konwencji dla funkcji bezklasowych: przekazać kontekst, w którym powinny pracować, jako pierwszy parametr. Wygląda na to, że będziesz mógł używać tylko publicznego interfejsu obiektu kontekstowego - ale z drugiej strony jest taki sam jak w przypadku JavaScript. Dodatkowo, jako bonus, będziesz mieć możliwość sprawdzenia typu z podpowiedziami do klasy. Na przykład:

function greet(SomeClass $_this) { 
    echo 'Hello ' . $_this->name; 
} 

class SomeClass { 
    public $name = 'John'; 

    function test() { 
    call_user_func('greet', $this); 
    } 
} 

$me = new SomeClass; 
$me->test(); // Hello John 
+0

Możesz * ponownie * powiązać '$ this' za pomocą interfejsu API Reflection ... ale nie jest to coś, co polecałbym robić w produkcji, ponieważ, jak powiedziałeś, PHP nie jest Javascriptem. +1 – deceze

1

można użyć funkcji Zamknięcie :: powiązania

<?php 

class AAA { 

    public function ccc() 
    { 
     $bbb = new BBB; 
     $r = $bbb->abc()[0]; 
     var_dump($r, Closure::bind($r, $this)); 
    } 

} 

class BBB { 

    public function abc() 
    { 
     return [function() { 

     }]; 
    } 

} 

$aaa = new AAA; 
$aaa->ccc(); 

i spowodować

object(Closure)#3 (1) { 
    ["this"]=> 
    object(BBB)#2 (0) { 
    } 
} 
object(Closure)#4 (1) { 
    ["this"]=> 
    object(AAA)#1 (0) { 
    } 
}