Why I'm getting 'Non-static method should not be called statically' when invoking a method in a Eloquent model?

Im trying to load my model in my controller and tried this:

return Post::getAll();

got the error Non-static method Post::getAll() should not be called statically, assuming $this from incompatible context

The function in the model looks like this:

public function getAll()
{

    return $posts = $this->all()->take(2)->get();

}

What's the correct way to load the model in a controller and then return it's contents?


You defined your method as non-static and you are trying to invoke it as static. That said...

1.if you want to invoke a static method, you should use the :: and define your method as static.

// Defining a static method in a Foo class.
public static function getAll() { /* code */ }

// Invoking that static method
Foo::getAll();

2.otherwise, if you want to invoke an instance method you should instance your class, use ->.

// Defining a non-static method in a Foo class.
public function getAll() { /* code */ }

// Invoking that non-static method.
$foo = new Foo();
$foo->getAll();

Note: In Laravel, almost all Eloquent methods return an instance of your model, allowing you to chain methods as shown below:

$foos = Foo::all()->take(10)->get();

In that code we are statically calling the all method via Facade. After that, all other methods are being called as instance methods.


Why not try adding Scope? Scope is a very good feature of Eloquent.

class User extends Eloquent {

    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }

    public function scopeWomen($query)
    {
        return $query->whereGender('W');
    }

}

$users = User::popular()->women()->orderBy('created_at')->get();

Eloquent #scopes in Laravel Docs


TL;DR. You can get around this by expressing your queries as MyModel::query()->find(10); instead of MyModel::find(10);.

To the best of my knowledge, starting PhpStorm 2017.2 code inspection fails for methods such as MyModel::where(), MyModel::find(), etc (check this thread). This could get quite annoying, when you try (let's say) to use PhpStorm's Git integration before committing your code, PhpStorm won't stop complaining about these static method call warnings.

One elegant way (IMOO) to get around this is to explicitly call ::query() wherever it makes sense to. This will let you benefit from free auto-completion and a nice formatting for your queries.

Examples

BAD

Snippet where inspection complains about static method calls

$myModel = MyModel::find(10); // static call complaint

// another poorly formatted query with code inspection complaints
$myFilteredModels = MyModel::where('is_beautiful', true)
    ->where('is_smart', false)
    ->get();

GOOD

Well formatted code with no complaints

$myModel = MyModel::query()->find(10);

// a nicely formatted query with no complaints
$myFilteredModels = MyModel::query()
    ->where('is_beautiful', true)
    ->where('is_smart', false)
    ->get();

Just in case this helps someone, I was getting this error because I completely missed the stated fact that the scope prefix must not be used when calling a local scope. So if you defined a local scope in your model like this:

public function scopeRecentFirst($query)
{
    return $query->orderBy('updated_at', 'desc');
}

You should call it like:

$CurrentUsers = \App\Models\Users::recentFirst()->get();

Note that the prefix scope is not present in the call.