93

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

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

}

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

4

9 回答 9

125

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

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

注意:在 Laravel 中,几乎所有 Eloquent 方法都会返回模型的一个实例,允许您将方法链接起来,如下所示:

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

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

于 2013-08-20T18:16:44.237 回答
41

为什么不尝试添加范围?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();

Laravel 文档中雄辩的 #scopes

于 2014-01-02T09:11:23.037 回答
8

TL;博士。您可以通过将查询表示为MyModel::query()->find(10);而不是MyModel::find(10);.

据我所知,启动PhpStorm 2017.2代码检查对于诸如 、 等方法会失败MyModel::where()MyModel::find()检查此线程)。这可能会很烦人,当您在提交代码之前尝试(比方说)使用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', true)
    ->where('is_smart', false)
    ->get();

好的

格式良好的代码,没有任何抱怨

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

// a nicely formatted query with no complaints
$myFilteredModels = MyModel::query()
    ->where('is_beautiful', true)
    ->where('is_smart', false)
    ->get();
于 2018-07-12T10:07:07.347 回答
3

以防万一这对某人有所帮助,我收到了这个错误,因为我完全错过了在调用本地范围时不能使用范围前缀的声明事实。因此,如果您在模型中定义了一个本地范围,如下所示:

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

你应该这样称呼它:

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

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

于 2018-09-27T07:53:51.140 回答
1

原始问题的解决方案

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

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。

于 2020-10-21T12:44:30.957 回答
0

你可以这样给

public static function getAll()
{

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

}

当你在你的控制器函数中静态调用时..

于 2017-05-23T12:33:30.070 回答
0

在我的案例中,我确实刚刚得到了答案。我正在创建一个实现了 create 方法的系统,所以我收到了这个实际错误,因为我访问的是被覆盖的版本,而不是来自 Eloquent 的版本。

希望有帮助?

于 2017-08-04T03:39:28.697 回答
0

为了使用语法,return Post::getAll();你应该__callStatic在你的类中有一个神奇的函数来处理所有的静态调用:

public static function __callStatic($method, $parameters)
{
    return (new static)->$method(...$parameters);
}
于 2018-05-02T17:03:51.327 回答
0

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

于 2017-09-02T16:08:41.207 回答