为什么我在Eloquent模型中调用方法时会得到'非静态方法不应该被静态调用'?

时间:2013-08-20 15:56:57

标签: php laravel eloquent

我试图在我的控制器中加载我的模型并尝试了这个:

return Post::getAll();

收到错误Non-static method Post::getAll() should not be called statically, assuming $this from incompatible context

模型中的函数如下所示:

public function getAll()
{

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

}

在控制器中加载模型然后返回其内容的正确方法是什么?

9 个答案:

答案 0 :(得分:70)

您将方法定义为非静态方法,并且您尝试将其作为静态方式调用。那说......

  1. ...如果要调用静态方法,则应使用::并将方法定义为静态。

    // Defining a static method in a Foo class.
    public static function getAll() { /* code */ }
    
    // Invoking that static method
    Foo::getAll();
    
  2. ...否则,如果要调用实例方法,则应该使用->实例化。

    // Defining a non-static method in a Foo class.
    public function getAll() { /* code */ }
    
    // Invoking that non-static method.
    $foo = new Foo();
    $foo->getAll();
    
  3. 注意:在Laravel中,几乎所有Eloquent方法都返回模型的实例,允许您链接方法,如下所示:

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

    在该代码中,我们静态地通过Facade调用all方法。之后,所有其他方法都被称为实例方法

答案 1 :(得分:27)

为什么不尝试添加Scope?范围是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

答案 2 :(得分:4)

TL; DR 。您可以通过将查询表示为MyModel::query()->find(10);而不是MyModel::find(10);来解决此问题。

据我所知,对于诸如MyModel::where()MyModel::find()等方法(请选中此thread), PhpStorm 2017.2 代码检查失败。当您尝试在提交代码之前尝试使用 PhpStorm的Git集成时,这可能会很烦人, PhpStorm 不会停止抱怨这些静态方法调用警告。

解决此问题的一种简便方法(IMOO)是在适当的地方明确呼叫::query() 。这将使您受益于免费的自动完成功能和良好的查询格式。

示例

检查抱怨静态方法调用的代码段

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

// another poorly formatted query with code inspection complaints
$myFilteredModels = MyModel::where('is', 'beautiful')
    ->where('is_not', 'smart')
    ->get();

格式无误的代码

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

// a nicely formatted query with no complaints
$myFilteredModels = MyModel::query()
    ->where('is', 'beautiful')
    ->where('is_not', 'smart')
    ->get();

答案 3 :(得分:3)

以防万一,这对我有所帮助,因为我完全错过了stated fact,即在调用本地作用域时不得使用作用域前缀,所以我会收到此错误。因此,如果您在模型中这样定义本地范围:

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

您应该这样称呼它:

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

请注意,呼叫中不存在前缀scope

答案 4 :(得分:0)

你可以这样给出

public static function getAll()
{

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

}

当您在控制器功能中静态调用时..

答案 5 :(得分:0)

在我的情况下,我确实得到了答案。 我正在创建一个已实现create方法的系统,因此我收到了这个实际错误,因为我正在访问被重写的版本,而不是来自Eloquent的版本。

希望有帮助吗?

答案 6 :(得分:0)

检查您是否在模型中声明了方法getAll()。这会导致控制器认为您正在调用非静态方法。

答案 7 :(得分:0)

要使用像return Post::getAll();这样的语法,你的类中应该有一个魔术函数__callStatic来处理所有静态调用:

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

答案 8 :(得分:0)

原始问题的解决方案

您静态调用了一个非静态方法。要使公共函数在模型中静态化,将如下所示:

public static function {
  
}

一般:

Post::get()

在这种情况下:

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

在定义关系和范围时要注意的一件事是我遇到了一个问题,该问题导致“非静态方法不应被静态调用”错误,例如它们的名称相同:

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

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

执行以下操作时,出现非静态错误:

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

问题在于Laravel使用的是我的关系方法,即类别,而不是类别范围(scopeCategory)。这可以通过重命名作用域或关系来解决。我选择重命名该关系:

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

请注意,我定义了外键(category_id),因为否则Laravel会查找cat_id,而不会找到它,因为我在数据库中将其定义为category_id。