3

How can I assign a function to a method in a class in PHP? I tried the following:

class Something{
    public function __construct(){
        $functionNames = array('foo', 'bar')

        $variable = 'blablabla';

        foreach($functionNames as $functionName){
            if(method_exists($this, $functionName))
                continue;

            $this->{$functionName}() = function($params){ //should create the methods "foo" and "bar"
                echo $variable; //should echo 'blablabla' (I know that the variable was declared outside this function, but how can I access it anyway?)
            }; //the error points to here
        }
    }
}

But this code gives me this error:

Fatal error: Can't use method return value in write context

Does anyone know how I can assign the anonymous function to the class method, while also still being able to access variables outside that function?

6
  • 1
    I do not think that is possible in PHP in the way that you are doing it. I think you have to instantiate an object or have a function return something that assigns something to a variable. Not a bad question though. Commented Dec 26, 2014 at 19:52
  • You can't return in a class constructor. It'll throw an error. php.net/manual/en/language.oop5.decon.php Commented Dec 26, 2014 at 19:53
  • @versalle88 yeah, that's true... I actually have a foreach loop and the return; is a continue;, but I decided to simplify the code a bit since (I thought) it wasn't necessary. I'll edit it though Commented Dec 26, 2014 at 19:56
  • Although it still won't work, when you assign an anonymous function, you should not use braces on the variable: $this->{$functionName[0]} = function($params){ Commented Dec 26, 2014 at 20:07
  • I don't see how this can work. Where is the value of $variable going to be stored once the constructor returns? Commented Dec 26, 2014 at 20:09

1 Answer 1

3

You are doing foreach($functionNames as $functionName){ which means that $functionName is a string, not an array. So, don't use $functionName[0].

method_exists takes 2 parameters. One is the object and the other is the method name. It should be:

method_exists($this, $functionName)

As for creating the function, you don't need () on the left side of the =. It should be:

$this->$functionName = function($params) use($variable){
    echo $variable;
};

The use($variable) is needed to tell PHP to use that variable inside the function. That's how closures work in PHP, it's different than other languages.

So, your class should look like:

class Something{
    public function __construct(){
        $functionNames = array('foo', 'bar');

        $variable = 'blablabla';

        foreach($functionNames as $functionName){
            if(method_exists($this, $functionName)){
                continue;
            }

            $this->$functionName = function($params) use($variable){
                echo $variable;
            };
        }
    }
}

Problem here is that in this way of making functions, you are not actually creating a class method, but instead creating a class variable that contains a function.

So, you need to call it like so:

$test = new Something;
$foo = $test->foo;

$foo('abc');

You can't just do $test->foo('abc');.

EDIT: Another thing you can do is use PHP's __call "magic method". This will be ran whenever you do ->funcName(), regardless of whether the method exists or not. Using that method, you can just check to see if the method called was 'foo' or 'bar'. See this example:

class Something{
    private $variable;

    public function __construct(){
        $this->variable = 'blablabla';
    }

    public function __call($name, $params=array()){
        if(method_exists($this, $name)){
            // This makes sure methods that *do* exist continue to work
            return call_user_func(array($this, $name), $params);
        }
        else{
            $functionNames = array('foo', 'bar');

            if(in_array($name, $functionNames)){
                // You called ->foo() or ->bar(), so do something
                // If you'd like you can call another method in the class
                echo $this->variable;
            }
        }
    }
}

With this, now you can do the following:

$test = new Something;
$test->foo('abc');  // Will echo "blablabla"
Sign up to request clarification or add additional context in comments.

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.