source

객체 속성에 직접 할당된 호출 종료

manycodes 2022. 12. 5. 21:26
반응형

객체 속성에 직접 할당된 호출 종료

객체의 속성에 할당한 닫힘을 변수에 재할당하여 호출하지 않고 직접 호출할 수 있도록 합니다.이게 가능합니까?

않고 이 됩니다.Fatal error: Call to undefined method stdClass::callback().

$obj = new stdClass();
$obj->callback = function() {
    print "HelloWorld!";
};
$obj->callback();

PHP7에서는 다음을 수행할 수 있습니다.

$obj = new StdClass;
$obj->fn = function($arg) { return "Hello $arg"; };
echo ($obj->fn)('World');

또는 Closure::call()사용합니다.단, 이 기능은StdClass.


PHP7을하기 전에 매직 __call(「콜백」은 할 수 ).StdClass이 때, 이 말은 수 에, 이 말은 붙일 수 없습니다.__call□□□□□□□□★

class Foo
{
    public function __call($method, $args)
    {
        if(is_callable(array($this, $method))) {
            return call_user_func_array($this->$method, $args);
        }
        // else throw exception
    }
}

$foo = new Foo;
$foo->cb = function($who) { return "Hello $who"; };
echo $foo->cb('World');

할 수 없는 것에 주의해 주세요.

return call_user_func_array(array($this, $method), $args);

__call은 「」, 「」의 트리거가 입니다.__call무한 루프에 있습니다.

오브젝트가 함수처럼 동작하기 위해 사용하는 매직 메서드이기 때문에 폐쇄 시 __invoke를 호출하여 이를 수행할 수 있습니다.

$obj = new stdClass();
$obj->callback = function() {
    print "HelloWorld!";
};
$obj->callback->__invoke();

물론 콜백이 배열 또는 문자열(PHP에서도 유효한 콜백일 수 있음)인 경우에는 작동하지 않습니다. __invoke 동작을 가진 클로저 및 기타 오브젝트에만 해당됩니다.

PHP 7에서는 다음을 수행할 수 있습니다.

($obj->callback)();

PHP 7에서는 다음 메서드를 사용하여 닫힘을 호출할 수 있습니다.

$obj->callback->call($obj);

PHP 7은 임의의 조작을 실행할 수 있기 때문에(...)표현도 마찬가지입니다(Korikulum 설명 참조).

($obj->callback)();

기타 일반적인 PHP 5 접근법은 다음과 같습니다.

  • 마법의 방법(브릴리언드에 의해 설명됨)을 사용하는

    $obj->callback->__invoke();
    
  • 기능을 사용하여

    call_user_func($obj->callback);
    
  • 식에서 중간 변수 사용

    ($_ = $obj->callback) && $_();
    

각각의 방법에는 장단점이 있지만, 가장 급진적이고 결정적인 해결책은 여전히 고든이 제시한 해결책으로 남아 있다.

class stdKlass
{
    public function __call($method, $arguments)
    {
        // is_callable([$this, $method])
        //   returns always true when __call() is defined.

        // is_callable($this->$method)
        //   triggers a "PHP Notice: Undefined property" in case of missing property.

        if (isset($this->$method) && is_callable($this->$method)) {
            return call_user_func($this->$method, ...$arguments);
        }

        // throw exception
    }
}

$obj = new stdKlass();
$obj->callback = function() { print "HelloWorld!"; };
$obj->callback();

하면 될 것 요.call_user_func().

call_user_func($obj->callback);

우아하지는 않지만…@Gordon이 말하는 것만이 유일한 방법일 것입니다.

음, 정 그러시다면요.또 다른 회피책은 다음과 같습니다.

$obj = new ArrayObject(array(),2);

$obj->callback = function() {
    print "HelloWorld!";
};

$obj['callback']();

하지만 그것은 가장 좋은 구문이 아닙니다.

PHP ,, PHP를 처리합니다.T_OBJECT_OPERATOR,IDENTIFIER,(메서드 호출로 지정됩니다. 문제를 해결할 방법은 없는 것 같습니다.->아트리뷰트

오래된 건 알지만 PHP 5.4+를 사용한다면 Features는 이 문제를 잘 처리할 수 있을 것 같습니다.

먼저 속성을 호출할 수 있는 특성을 만듭니다.

trait CallableProperty {
    public function __call($method, $args) {
        if (property_exists($this, $method) && is_callable($this->$method)) {
            return call_user_func_array($this->$method, $args);
        }
    }
}

그런 다음 해당 특성을 수업에 사용할 수 있습니다.

class CallableStdClass extends stdClass {
    use CallableProperty;
}

이제 익명 함수를 통해 속성을 정의하고 직접 호출할 수 있습니다.

$foo = new CallableStdClass();
$foo->add = function ($a, $b) { return $a + $b; };
$foo->add(2, 2); // 4

변수에 클로징을 저장하고 변수 호출이 실제로 더 빠르다는 것을 강조해야 합니다.콜량에 따라 상당히 많은 양이 됩니다.xdebug(매우 정확한 측정)에서는 __debug를 직접 호출하지 않고 변수를 사용하여 1.5에 대해 이야기하고 있습니다.대신 마감을 변수 안에 저장하고 호출합니다.

다음은 수용된 답변을 기반으로 하지만 stdClass를 직접 확장하는 다른 대안입니다.

class stdClassExt extends stdClass {
    public function __call($method, $args)
    {
        if (isset($this->$method)) {
            $func = $this->$method;
            return call_user_func_array($func, $args);
        }
    }
}

사용 예:

$foo = new stdClassExt;
$foo->blub = 42;
$foo->whooho = function () { return 1; };
echo $foo->whooho();

당신은 아마 그것을 사용하는 것이 더 나을 것이다.call_user_func또는__invoke그래도.

갱신일 :

$obj = new stdClass();
$obj->callback = function() {
     print "HelloWorld!";
};

PHP > = 7 :

($obj->callback)();

PHP > = 5.4 :

$callback = $obj->callback;  
$callback();

PHP 5.4 이상을 사용하는 경우, 를 오브젝트 범위에 바인드하여 커스텀 동작을 호출할 수 있습니다.예를 들어 다음과 같은 설정이 있을 경우,

function run_method($object, Closure $method)
{
    $prop = uniqid();
    $object->$prop = \Closure::bind($method, $object, $object);
    $object->$prop->__invoke();
    unset($object->$prop);
}

그리고 넌 그런 수업에서 수술을 했어

class Foo
{
    private $value;
    public function getValue()
    {
        return $this->value;
    }
}

오브젝트 범위 내에서 동작하는 것처럼 독자적인 로직을 실행할 수 있습니다.

$foo = new Foo();
run_method($foo, function(){
    $this->value = 'something else';
});

echo $foo->getValue(); // prints "something else"

이것은 PHP5.5에서 동작하는 것에 주의합니다.

$a = array();
$a['callback'] = function() {
    print "HelloWorld!";
};
$a['callback']();

폐쇄의 psuedo 객체 컬렉션을 작성할 수 있습니다.

언급URL : https://stackoverflow.com/questions/4535330/calling-closure-assigned-to-object-property-directly

반응형