Make static out of non-static (Magic Method)

Hello so basically in Laravel you can do something like this

User::get();

And I know that behind the scene laravel does this by calling a magic method called __callStatic() and returning a new static out of it.

BUT __callStatic only works on inaccessible or non-existing methods.

So my question is that how you can do that User::get() when get() actually is a public function?

Edit
Given I have this simple code here

class First
{
    public function callThis()
    {
        return 'Yo';
    }

    public static function __callStatic($name, $arguments)
    {
        dd('This is not working');
    }
}

First::callThis();

And I get

Non-static method First::callThis() should not be called statically

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

It will not work because you cannot call non static methods statically.
The reason why it works with methods like get() is because these calls are being delegated to the query instance – they don’t actually exist on the model itself.

If you check __call method, it should all become a bit more clear:

public function __call($method, $parameters)
{
    if (in_array($method, ['increment', 'decrement'])) {
        return $this->$method(...$parameters);
    }

    return $this->newQuery()->$method(...$parameters);
}

So even though the default __callStatic method implementation calls the non static method on itself:

public static function __callStatic($method, $parameters)
{
    return (new static)->$method(...$parameters);
}

Your code would fail straight away, because your model would actually contain the public non-static method with the same name.

You’ll see that the __call method checks whether the name of the method is within the array of increment and decrement – and if it is – it calls them.

protected function increment($column, $amount = 1, array $extra = [])
{
    return $this->incrementOrDecrement($column, $amount, $extra, 'increment');
}

protected function decrement($column, $amount = 1, array $extra = [])
{
    return $this->incrementOrDecrement($column, $amount, $extra, 'decrement');
}

Both of these methods are actually non-static on the instance of the model, but their visibility is set to protected so you wouldn’t be able to call them on the instance of the model anyway – the only way to access them is using magic methods – in this case static call will work just fine.

In other words, if you change visibility of your method to protected and overwrite the __call method to also include your method name in the array, then your code should work

protected function callThis()
{
    return 'Yo';
}

public function __call($method, $parameters)
{
    if (in_array($method, ['increment', 'decrement', 'callThis'])) {
        return $this->$method(...$parameters);
    }

    return $this->newQuery()->$method(...$parameters);
}

Hope this helps.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x