106

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?

Rubens Mariuzzo
  • 28,358
  • 27
  • 121
  • 148
Sam Pettersson
  • 3,049
  • 6
  • 23
  • 37
  • 2 ways. 1st, create an instance of the model and use `$obj->getAll()` or make the function static. – itachi Aug 20 '13 at 16:14
  • 6
    When you use : `::` you are trying to access a method *statically* so your function signature should be declared as: `public static function getAll()`. – Rubens Mariuzzo Aug 20 '13 at 18:12
  • @Sam, I will recommend you a five minutes reading about OOP & static methods in PHP: http://php.net/manual/en/language.oop5.static.php – Rubens Mariuzzo Aug 20 '13 at 18:30

11 Answers11

146

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.

segFault
  • 3,887
  • 1
  • 19
  • 31
Rubens Mariuzzo
  • 28,358
  • 27
  • 121
  • 148
48

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

kamal pal
  • 4,187
  • 5
  • 25
  • 40
keithics
  • 8,576
  • 2
  • 48
  • 35
  • 3
    IMO this should be the accepted answer because it is specific to Laravel and Rubens answer is correct but not specific enough. – JacobRossDev Mar 13 '15 at 18:15
  • @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() – MANSOOR KOCHY Mar 02 '22 at 06:43
  • **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();` – Top-Master Apr 01 '22 at 14:14
12

This answer is about building queries.

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), and this could get quite annoying.

One (elegant) way 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 indentation for your queries.

Examples

BAD

Snippet where inspection complains about static method calls

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

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

GOOD

Nicely indented query code with NO complaints

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

// a nicely formatted and indented query with no complaints
$myFilteredModels = MyModel::query()
    ->where('is_foo', true)
    ->where('is_bar', false)
    ->get();
  • 1
    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 Jul 19 '18 at 23:08
  • @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?) – Anis LOUNIS aka AnixPasBesoin Jul 20 '18 at 23:56
  • 2
    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. – michasaurus Jul 23 '19 at 19:22
3

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.

dotNET
  • 33,414
  • 24
  • 162
  • 251
2

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.

Darren Murphy
  • 1,076
  • 14
  • 12
0

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..

Karthiga
  • 859
  • 2
  • 17
  • 33
0

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?

idro2k
  • 90
  • 4
  • This is not the answer. Class, object and Static are the basic concept of oops. Static function called without object and public function called with object. As function is declared as public so need an object to call it – Yogendra Jun 28 '23 at 09:42
  • OOPs concepts are same for everyone. No matter it's your case, my case or anyone case – Yogendra Jun 28 '23 at 09:45
0

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.

0

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);
}
SpinyMan
  • 436
  • 5
  • 9
0

Static methods can be called directly - without creating an instance of the class.

ClassName::staticMethod(); 

And you defined your method getAll() public but not static. So you can't call it statically. You need to create an object of class to call it.

$object = new Post();
$object->getAll();
Yogendra
  • 1,208
  • 5
  • 18
  • 38
-3
public static function getAll() {
    return $posts = $this->all()->take(2)->get();
}

Just add static method.

Codemaker2015
  • 12,190
  • 6
  • 97
  • 81