Reputation: 31948
This code does not work:
class A {
public function b() {
(new B)->d([$this, 'c']); // Error is here
}
private function c() {
echo 'test';
}
}
class B {
public function d($e) {
call_user_func($e);
}
}
(new A)->b();
Running this code gives:
call_user_func() [...] cannot access private method A::c()
I can understand why it does not work. But I don't know the real reason. In A::b()
, I'm in A
context, that's why I thought c()
can be called ($this
is well known and do refers to A
, so I'm in A
context).
What is really weird for me is that it works if I replace:
(new B)->d([$this, 'c']);
By:
(new B)->d(function() { $this->c(); });
So it's not a problem to call a private function now. I can't understand why. And I did not found anything in doc about this.
Why (new B)->d(function() { $this->c(); });
works but not (new B)->d([$this, 'c']);
when I call (new A)->b();
?
Upvotes: 4
Views: 4054
Reputation: 1275
When you use [$this, 'c']
an array is passed with index [0]
as reference of object of class A and index [1]
as a string c, so it tries to call the function from method d
using string stored in array index [1]
.
When you pass the function directly a closure is passed which is binded to class A
so it can be used to call function c
as it is binded to class A
.
However you can use the first method too and not get any error by a little trick like this :
class A {
public function b() {
(new B)->d([$this, 'c']);// NO ERROR NOW!
}
private function c() {
echo 'test';
}
}
class B {
public function d($e) {
// Here is the trick :
$f = function() { $this->c(); };
$f = Closure::bind($f, $e[0], 'A');
$f();
}
}
(new A)->b();
What I did was create a closure and then bind using ::bind it to class A using the object reference received in $e[0]
.
Upvotes: 1
Reputation: 156
I'd say if you use:
$this->c();
it gets executed right there, so from the class A, which has this function. if you do it like:
[$this, 'c']
you pass the class and the function that should be executed by class B, and it will also be executed by class B, but class B cannot access the private function of class A.
Regards
Upvotes: 0