Почему я получаю "Нестатический метод не следует называть статически" при вызове метода в модели 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();

}

Какой правильный способ загрузить модель в контроллер, а затем вернуть ее?

Ответ 1

Вы определили свой метод как нестатический, и вы пытаетесь вызвать его как статический. Тем не менее...

  • ... если вы хотите вызвать статический метод, вы должны использовать :: и определить свой метод как статический.

    // Defining a static method in a Foo class.
    public static function getAll() { /* code */ }
    
    // Invoking that static method
    Foo::getAll();
    
  • ... в противном случае, если вы хотите вызвать метод экземпляра, вы должны указать свой класс, используйте ->.

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

В этом коде мы статически вызываем метод all через Facade. После этого все другие методы называются методами экземпляра.

Ответ 2

Почему бы не попробовать добавить область? Область применения - очень хорошая особенность 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 Docs

Ответ 3

TL; DR. Вы можете обойти это, выразив свои запросы как 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_not_smart', false)
    ->get();

Хорошо отформатированный код без жалоб

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

// a nicely formatted query with no complaints
$myFilteredModels = MyModel::query()
    ->where('is_beautiful', true)
    ->where('is_not_smart', false)
    ->get();

Ответ 4

На всякий случай, если это кому-то поможет, я получил эту ошибку, потому что я полностью пропустил указанный факт, что префикс области не должен использоваться при вызове локальной области. Так что, если вы определили локальную область в своей модели следующим образом:

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

Вы должны назвать это как:

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

Обратите внимание, что префикс scope отсутствует в вызове.

Ответ 5

Вы можете дать как это

public static function getAll()
{

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

}

И когда вы вызываете статически внутри своей функции контроллера также.

Ответ 6

Я буквально только что пришел к ответу в моем случае. Я создаю систему, которая реализовала метод create, поэтому я получил эту фактическую ошибку, потому что я обращался к переопределенной версии, а не к Eloquent.

Надеюсь, что поможет?

Ответ 7

Проверьте, не объявили ли вы метод getAll() в модели. Это заставляет диспетчера думать, что вы вызываете нестатический метод.

Ответ 8

Для использования такого синтаксиса, как return Post::getAll();, в вашем классе должна быть магическая функция __callStatic, где обрабатываются все статические вызовы:

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