我试图在我的控制器中加载我的模型并尝试了这个:
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();
}
在控制器中加载模型然后返回其内容的正确方法是什么?
$obj->getAll()
或将函数设为静态。
::
时,您正尝试静态地 访问方法,因此您的函数签名应声明为:public static function getAll()
。
您将您的方法定义为非静态的,并尝试将其作为静态调用。那就是说...
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
方法。之后,所有其他方法都被称为实例方法。
为什么不尝试添加范围? 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
scope
并收到此错误(因为同时定义了 published()
和 scopePublished()
)。 解决方案 是:Post::query()->published();
而不是 Post::published();
TL;DR。您可以通过将查询表示为 MyModel::query()->find(10);
而不是 MyModel::find(10);
来解决此问题。
据我所知,启动 PhpStorm 2017.2 代码检查对于 MyModel::where()
、MyModel::find()
等方法会失败(检查此 thread)。这可能会很烦人,当您在提交代码之前尝试(比方说)使用 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();
MyModel::query()
非常清楚底层发生了什么,同时也让 IDE 满意。
以防万一这对某人有帮助,我收到了这个错误,因为我完全错过了调用本地范围时不能使用范围前缀的 stated fact。因此,如果您在模型中定义了一个本地范围,如下所示:
public function scopeRecentFirst($query)
{
return $query->orderBy('updated_at', 'desc');
}
你应该这样称呼它:
$CurrentUsers = \App\Models\Users::recentFirst()->get();
请注意,调用中不存在前缀 scope
。
原始问题的解决方案
您静态地调用了非静态方法。要使模型中的公共函数静态化,如下所示:
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。
你可以这样给
public static function getAll()
{
return $posts = $this->all()->take(2)->get();
}
当你在你的控制器函数中静态调用时..
在我的案例中,我确实刚刚得到了答案。我正在创建一个实现了 create 方法的系统,所以我收到了这个实际错误,因为我访问的是被覆盖的版本,而不是来自 Eloquent 的版本。
希望有帮助?
检查您是否没有在模型中声明方法 getAll()。这会导致控制器认为您正在调用非静态方法。
要使用像 return Post::getAll();
这样的语法,你应该在你的类中有一个神奇的函数 __callStatic
来处理所有的静态调用:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
In Laravel, almost all Eloquent methods are defined as static
....这是一种误解。 NONE 是静态的。