1

I wanna make a syntax like jquery in php, I wrote that class:

class events{

    public function auth($user, $pass, $callback){
        $status = 0;
        if($user and $pass){
            $status = 1;
        }
        call_user_func($callback, $status);
    }

    public function login(){
        echo "Welcome!";
    }

}

$events = new events;
$user = "u";
$pass = "p";

And that's Jquery like syntax:

/**
 * Jquery type callback function
 */
$events->auth($user, $pass, function($status){
    if($status){
        $this->login();
    }else{
        echo "Fail";
    }
});

Everything is OK except $this variable I used outer that class methods, I cannot use the callback function as a internal function for using $this into that function codes. Can I correct that error by changing something in my class ?

3
  • 1
    You can only use $this in classes. Commented Oct 8, 2014 at 10:05
  • I know that but I'm looking for a way to use $this in foreign functions which are calling by that class methods. Commented Oct 8, 2014 at 10:10
  • 3
    Why not call $events->login() instead of trying $this->login() ? Commented Oct 8, 2014 at 10:14

3 Answers 3

4

You need to bind your anonymous function to the object with Closure::bind.


Example:

class events{

    public function auth($user, $pass, $callback){
        $status = 0;
        if($user and $pass){
            $status = 1;
        }
        call_user_func(Closure::bind($callback, $this), $status);
    }

    public function login(){
        echo "Welcome!";
    }

}

$events = new events;
$user = "u";
$pass = "p";

$events->auth($user, $pass, function($status){
    if($status){
        $this->login();
    }else{
        echo "Fail";
    }
});

Output:

Welcome!

Also note that it's not necessary to use call_user_func(), you can replace that line with something like this if you prefer:

$callback = $callback->bindTo($this);
$callback($status);
Sign up to request clarification or add additional context in comments.

3 Comments

can I use Closure::bind in auth function? for example: Closure::bind($callback($status));
Yes, but not like that, because you are actually calling the closure before creating the bound copy. You can do this: $callback = Closure::bind($callback, $this); $callback($status); @Paul: please correct me if I'm wrong.
very very thanks @PaulCrovella and others for your great answers.
1

You can pass the instance of the class to the callback:

<?php
class events{

    public function auth($user, $pass, $callback){
        $status = 0;
        if($user and $pass){
            $status = 1;
        }
        $callback($status, $this);
    }

    public function login(){
        echo "Welcome!";
    }

}

$events = new events;
$user = "u";
$pass = "p";


/**
 * Jquery type callback function
 */
$events->auth($user, $pass, function($status, $self){
    if($status){
        $self->login();
    }else{
        echo "Fail";
    }
});

1 Comment

Yeah, I would be interested in an explanation too. This should work just fine.
1

There's no way to "bind" closures to specific objects like in JavaScript. The $this keyword cannot therefore be used outside of a class. However, since $events is the instance which $this would reference, you can do this:

$events->auth($user, $pass, function($status){
    if($status){
        $events->login();
    }else{
        echo "Fail";
    }
});

Edit: Apparently I was wrong, there is a way to bind closures to specific instances. See Paul's answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.