В PHP нет способа вызвать "извне" метод объекта или класса с модификатором доступа "private". Но есть несколько не очень красивых, но рабочих способа обойти эти ограничения.
Возможные случаи практического применения, на рабочих проектах, этих подходов - единицы.
А также:
Вот эти несколько вариантов использования:
-----------------------
Вариант 1:
source: http://php.net/manual/ru/closure.bindto.php#111379
|
<?php trait DynamicDefinition { public function __call($name, $args) { if(is_callable($this->$name)) { return call_user_func($this->$name, $args); } else { throw new \RuntimeException("Method {$name} does not exist"); } } public function __set($name, $value) { $this->$name = is_callable($value) ? $value->bindTo($this, $this) : $value; } } class Foo { use DynamicDefinition; private $privateValue = 'I am private'; } $foo = new Foo; $foo->bar = function () { return $this->privateValue; }; var_dump($foo->bar()); // 'I am private'
string 'I am private' (length=12)
Вариант 2:
source: http://rmcreative.ru/blog/post/vyzvat-private-metod-klassa-v-php
|
<?php class MyClass { private function privateMethod($args) { return $args; } } function callPrivateMethod($object, $method, $args) { $classReflection = new \ReflectionClass(get_class($object)); $methodReflection = $classReflection->getMethod($method); $methodReflection->setAccessible(true); $result = $methodReflection->invokeArgs($object, $args); $methodReflection->setAccessible(false); return $result; } $t = callPrivateMethod(new MyClass(), 'privateMethod', ['world with ReflectionClass']); var_dump($t);
string 'world with ReflectionClass' (length=26)
Вариант 3:
|
<?php class MyClass { private function privateMethod($args) { return $args; } function callPrivate($object, $method, $args) { $caller = function ($method, $args) { return call_user_func_array([$this, $method], $args); }; $caller->bindTo($object, $object); return $caller($method, $args); } } $privacyViolator = new MyClass(); $t = $privacyViolator->callPrivate(new stdClass(), 'privateMethod', ['world use_Closure_bindTo']); var_dump($t);
string 'world use_Closure_bindTo' (length=24)
Вариант 4:
source: http://rmcreative.ru/blog/post/vyzvat-private-metod-klassa-v-php-bez-reflection#c9851
|
<?php class PrivacyViolator { public function callPrivateMethod($object, $method, array $args = array()) { if(!is_object($object)) { throw new \InvalidArgumentException('The $object param must be object'); } $className = get_class($object); $method = new \ReflectionMethod($className, $method); $method->setAccessible(true); return $method->invokeArgs($object, $args); } } class MyClass { private function hello($name) { return 'Hello '.$name; } } $myObject = new MyClass(); $privacyViolator = new PrivacyViolator(); $result = $privacyViolator->callPrivateMethod($myObject, 'hello', array('World')); echo $result; assert('Hello World' === $result);
Hello World