ChatGPT解决这个技术问题 Extra ChatGPT

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?

2 ways. 1st, create an instance of the model and use $obj->getAll() or make the function static.
When you use : :: you are trying to access a method statically so your function signature should be declared as: public static function getAll().
@Sam, I will recommend you a five minutes reading about OOP & static methods in PHP: php.net/manual/en/language.oop5.static.php

s
segFault

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.


how is getAll() non-static in 2nd option??
Thanks @TryingTobemyself to notify me about this. I updated my answer with your suggestion.
In Laravel, almost all Eloquent methods are defined as static.... that's a misconception. NONE are static.
Yes, in Laravel, none Eloquent methods are defined as static, we can use them as it were defined as static, but that's a Facade, more about this: laravel.com/docs/facades
Although the response is factual, in the context of Laravel it is unlikely that this is the fix users on this thread are looking for. This answer should be removed and keithics answer should be marked as correct.
k
kamal pal

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


IMO this should be the accepted answer because it is specific to Laravel and Rubens answer is correct but not specific enough.
@JacobRossDev I am using the scope, the first time I used local scope and worked correctly then I created global scope when does not satisfy my need I get back to the local scope I am following all naming convention but when calling it get the error of BadMethodCallException Call to undefined method App\Models\Share::popular()
I have scope and was getting this error (because had both published() and scopePublished() defined). Solution was to do: Post::query()->published(); instead of Post::published();
A
Anis LOUNIS aka AnixPasBesoin

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();

Changing code just to remove an incorrect IDE warning sounds like a bad idea. If you know it's correct, then keep it that way.
@zundi yes sir, I totally agree that changing code for the sake of pleasing the IDE is not always a good practice, BUT in this case, we're just adding one static method call that would've been called either ways, (we're just being explicit here). Otherwise you would have to: either disable this inspection, or annotate another class somewhere else... (a hustle! don't u agree?)
Same, I really like this answer. I'm not a big fan of Facades to start with, and the fact that that PhpStorm doesn't support them right out of the box makes me like them less. MyModel::query() makes it very clear what's happening under the hood while also pleasing the IDE.
d
dotNET

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.


D
Darren Murphy

Solution to the original question

You called a non-static method statically. To make a public function static in the model, would look like this:

public static function {
  
}

In General:

Post::get()

In this particular instance:

Post::take(2)->get()

One thing to be careful of, when defining relationships and scope, that I had an issue with that caused a 'non-static method should not be called statically' error is when they are named the same, for example:

public function category(){
    return $this->belongsTo('App\Category');
}

public function scopeCategory(){
    return $query->where('category', 1);
}

When I do the following, I get the non-static error:

Event::category()->get();

The issue, is that Laravel is using my relationship method called category, rather than my category scope (scopeCategory). This can be resolved by renaming the scope or the relationship. I chose to rename the relationship:

public function cat(){
    return $this->belongsTo('App\Category', 'category_id');
}

Please observe that I defined the foreign key (category_id) because otherwise Laravel would have looked for cat_id instead, and it wouldn't have found it, as I had defined it as category_id in the database.


K
Karthiga

You can give like this

public static function getAll()
{

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

}

And when you call statically inside your controller function also..


You can not you $this inside a static method
i
idro2k

I've literally just arrived at the answer in my case. I'm creating a system that has implemented a create method, so I was getting this actual error because I was accessing the overridden version not the one from Eloquent.

Hope that help?


J
Julio Gonzalez Rios

Check if you do not have declared the method getAll() in the model. That causes the controller to think that you are calling a non-static method.


S
SpinyMan

For use the syntax like return Post::getAll(); you should have a magic function __callStatic in your class where handle all static calls:

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

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now