dev7
dev7

Reputation: 6369

Laravel error when using dynamic class names returned by method

In Laravel (4 & 5), I am trying to use dynamic class names and then call them directly, but receiving a fatal error if not first storing them in a local string variable.

Assuming I have a basic class:

class SimpleModel {
     private $modelName;

     function __construct($id) {

        $this->modelName = AnotherModel::getName($id);

    }
}

Within the methods, I can easily do

$modelName = $this->modelName;
$modelName::find(1);

But I get a fatal error when trying the following:

$this->modelName::find(1);

This triggers a Symfony\Component\Debug\Exception\FatalErrorException with a message of

syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)

Basically the T_PAAMAYIM_NEKUDOTAYIM is a syntax error generated from the :: symbol.

Can't wrap my head around why Laravel (or PHP in general) allows dynamic class names when using a local variable (within a method) but not a class variable.

I also tried putting it in a seprate method getModelName() method but getting the same error.

$this->getModelName()::find(1);

Instanciating a new class every time (new $this->modelName) is not a good solution.

I was looking into using PHP's Reflection but not sure how to do it without instanciating a new class every time. Since it is working when using a local string, it seems as Reflection might be an over kill.

Upvotes: 1

Views: 2367

Answers (2)

Fabian Schmengler
Fabian Schmengler

Reputation: 24551

This is due to how the PHP parser works (up to PHP 5). The T_PAAMAYIM_NEKUDOTAYIM token (::) is only allowed after T_STRING (that represents a class name, not a string within quotes) or, since PHP 5.3, T_VARIABLE.

But your code will work in PHP 7, where the parser has been fundamentally reworked (see: https://wiki.php.net/rfc/abstract_syntax_tree)

Demo: https://3v4l.org/sdBss

Upvotes: 2

jedrzej.kurylo
jedrzej.kurylo

Reputation: 40909

You can use call_user_func or call_user_func_array to call method of a class, the name of which is stored in object's attribute:

call_user_func(array($this->modelName, 'find'), 1)

OR

call_user_func_array(array($this->modelName, 'find'), array(1))

Upvotes: 1

Related Questions