ChatGPT解决这个技术问题 Extra ChatGPT

为什么在 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();

}

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

2种方式。 1st,创建模型实例并使用$obj->getAll()或将函数设为静态。
当您使用::: 时,您正尝试静态地 访问方法,因此您的函数签名应声明为:public static function getAll()
@Sam,我会推荐你花五分钟阅读 OOP & PHP 中的静态方法:php.net/manual/en/language.oop5.static.php

s
segFault

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

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 方法。之后,所有其他方法都被称为实例方法


getAll() 如何在第二个选项中是非静态的?
感谢@TryingTobemyself 通知我这一点。我用你的建议更新了我的答案。
In Laravel, almost all Eloquent methods are defined as static....这是一种误解。 NONE 是静态的。
是的,在 Laravel 中,没有 Eloquent 方法被定义为静态的,我们可以使用它们,因为它被定义为静态,但那是一个门面,更多关于这个:laravel.com/docs/facades
尽管响应是真实的,但在 Laravel 的上下文中,这不太可能是该线程上的用户正在寻找的修复程序。应删除此答案,并将 keithics 答案标记为正确。
k
kamal pal

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


IMO 这应该是公认的答案,因为它特定于 Laravel,而 Rubens 的答案是正确的,但不够具体。
@JacobRossDev我正在使用范围,我第一次使用本地范围并正常工作然后我创建了全局范围,当不满足我的需要时我回到本地范围我遵循所有命名约定但是在调用它时得到错误BadMethodCallException 调用未定义的方法 App\Models\Share::popular()
我有 scope 并收到此错误(因为同时定义了 published()scopePublished())。 解决方案 是:Post::query()->published(); 而不是 Post::published();
A
Anis LOUNIS aka AnixPasBesoin

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

更改代码只是为了删除不正确的 IDE 警告听起来是个坏主意。如果你知道它是正确的,那就保持这种状态。
@zundi 是的先生,我完全同意为了取悦 IDE 而更改代码并不总是一个好习惯,但是在这种情况下,我们只是添加一个静态方法调用,它可以被称为任一方式,(我们'只是在这里明确)。否则你将不得不:要么禁用此检查,要么在其他地方注释另一个类......(忙碌!你不同意吗?)
同样,我真的很喜欢这个答案。我一开始就不是 Facades 的忠实粉丝,而且 PhpStorm 不支持开箱即用的事实让我不那么喜欢它们。 MyModel::query() 非常清楚底层发生了什么,同时也让 IDE 满意。
d
dotNET

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

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

你应该这样称呼它:

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

请注意,调用中不存在前缀 scope


D
Darren Murphy

原始问题的解决方案

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

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。


K
Karthiga

你可以这样给

public static function getAll()
{

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

}

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


你不能在静态方法中使用 $this
i
idro2k

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

希望有帮助?


J
Julio Gonzalez Rios

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


S
SpinyMan

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

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

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

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅