2014-12-21 12 views
5

In Javascript, i this an eine andere Funktion binden kann, und rufen Sie es mit .call oder .applyPHP call_user_func binden thisArg wie Call Javascript

In PHP, ich kann das tun mit call_user_func oder call_user_func_array, aber wie kann ich $this binden in die Funktion?

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:

Danke für die Reflection Idee @deceze, habe ich diese Lösungen gefunden, aber ich glaube nicht, es ist gut, für die Leistung (x10 langsamer als direkt anrufen), aber viel klar beim Lesen.

Ich habe schreibt zwei Funktionen:

// 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)); 
} 

und ersetzen call_user_func-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

Warum zur Folge haben Sie kein Argument für diese Funktion hinzufügen, und die Variable als Argument übergeben ? Sonst kann Ihnen das Schlüsselwort 'use' helfen. (http://php.net/functions.anonymous) Aber ich bin mir nicht wirklich sicher. –

+0

Mögliches Duplikat von http://stackoverflow.com/questions/27014664/php-equivalent-of-avascript-bind – haim770

+0

wie ich weiß, ist dies eine Lösung, die '$ this' als Argument übergeben, nur neugierig, gibt es irgendeine Möglichkeit, wie funktioniert Javascript – user1542316

Antwort

3

PHP ist nicht JavaScript: Sie sind nicht frei Funktionen innerhalb und außerhalb Klassen definiert mischen, Schalen ihren Kontext wie du sie nennst. Jeder Versuch, $this wie beschrieben zu verwenden, führt zu einem schwerwiegenden Fehler: Using $this when not in object context.

Wiederum kann derselbe Effekt mit einer einfachen Konvention für klassenlose Funktionen erreicht werden: übergeben Sie den Kontext, mit dem sie arbeiten sollten, als ihren ersten Parameter. Offensichtlich können Sie nur die öffentliche Schnittstelle des Kontextobjekts verwenden - aber genauso wie bei JavaScript. Außerdem können Sie als Bonus eine Typüberprüfung mit Klassenhinweisen durchführen. Zum Beispiel:

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

Sie können * $ this' mit der Reflection-API binden ... aber es ist nicht etwas, was ich in der Produktion tun würde, da, wie Sie sagten, PHP kein Javascript ist. +1 – deceze

1

können Sie Closure verwenden :: bind Funktion

<?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(); 

und

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