Я пытался загрузить мою модель в контроллере и попробовал это:
return Post::getAll();
И я все еще получаю ошибку
Нестатический метод Post::getAll() не должен вызываться статически, предполагая $this из несовместимого контекста
Функция в модели выглядит так:
public function getAll() {
return $posts = $this->all()->take(2)->get();
}
Какой правильный способ загрузить модель в контроллер и затем вернуть ее содержимое?
Вы определили свой метод как нестатический и пытаетесь вызвать его статически. Это сказано…
1. Если вы хотите вызвать статический метод, вы должны использовать ::
и определить свой метод как статический.
// Определение статического метода в классе Foo.
public static function getAll() { /* код */ }
// Вызов этого статического метода
Foo::getAll();
2. В противном случае, если вы хотите вызвать метод экземпляра, вы должны создать экземпляр вашего класса и использовать ->
.
// Определение нестатического метода в классе Foo.
public function getAll() { /* код */ }
// Вызов этого нестатического метода.
$foo = new Foo();
$foo->getAll();
Примечание: В Laravel почти все методы Eloquent возвращают экземпляр вашей модели, что позволяет вам связывать методы, как показано ниже:
$foos = Foo::all()->take(10)->get();
В этом коде мы статически вызываем метод all
через Facade. После этого все другие методы вызываются как методы экземпляра.
Почему бы не попробовать добавить Scope? 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();
Этот ответ касается построения запросов.
TL;DR. Вы можете обойти это, выразив свои запросы как MyModel::query()->find(10);
вместо MyModel::find(10);
.
Насколько я знаю, начиная с PhpStorm 2017.2, инспекция кода не работает для методов, таких как MyModel::where()
, MyModel::find()
и т. д. (проверьте этот тред), и это может быть очень неприятно.
Один (элегантный) способ обойти это — явно вызывать ::query()
там, где это имеет смысл. Это даст вам бесплатное автозаполнение и красивую индентацию для ваших запросов.
Примеры
ПЛОХО
Фрагмент, где инспекция жалуется на вызовы статических методов
// жалоба на вызов статического метода
$myModel = MyModel::find(10);
// еще один плохо отформатированный запрос с жалобами инспекции кода
$myFilteredModels = MyModel::where('is_foo', true)
->where('is_bar', false)
->get();
ХОРОШО
Хорошо отформатированный и отступленный код запроса БЕЗ жалоб
// нет жалоб
$myModel = MyModel::query()->find(10);
// красиво отформатированный и отступленный запрос без жалоб
$myFilteredModels = MyModel::query()
->where('is_foo', true)
->where('is_bar', false)
->get();
На случай, если это поможет кому-то, я получал эту ошибку, потому что полностью пропустил указанный факт, что префикс scope не должен использоваться при вызове локального scope. Так что если вы определили локальный scope в своей модели вот так:
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()
Нужно быть осторожным при определении отношений и scope, у меня была проблема, из-за которой возникла ошибка ‘нестатический метод не должен вызываться статически’, когда они назывались одинаково, например:
public function category(){
return $this->belongsTo('App\Category');
}
public function scopeCategory(){
return $query->where('category', 1);
}
Когда я делаю следующее, у меня возникает ошибка нестатического метода:
Event::category()->get();
Проблема в том, что Laravel использует мой метод отношения, который называется category, вместо моего scope category (scopeCategory). Это можно решить, переименовав scope или отношение. Я выбрал переименовать отношение:
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();
}
И когда вы вызываете статически внутри функции вашего контроллера тоже..
Я буквально пришел к ответу в моем случае.
Я создаю систему, которая реализовала метод создания, поэтому я получал эту реальную ошибку, потому что я обращался к переопределенной версии, а не к той, что из Eloquent.
Надеюсь, это поможет?
Проверьте, не объявлен ли у вас метод getAll() в модели. Это заставляет контроллер думать, что вы вызываете нестатический метод.
Чтобы использовать синтаксис вроде return Post::getAll();
, у вас должен быть магический метод __callStatic
в вашем классе, который обрабатывает все статические вызовы:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
public static function getAll() {
return $posts = $this->all()->take(2)->get();
}
Просто добавьте статический метод.
Ответ
Ошибка "Non-static method should not be called statically" возникает, когда в вашем коде вы вызываете не статический метод класса как если бы он был статическим. В вашем случае вы определили метод getAll()
как не статический:
public function getAll() {
return $this->all()->take(2)->get();
}
Однако вы вызываете его статически в контроллере:
return Post::getAll();
Решение проблемы
Чтобы устранить эту ошибку, у вас есть два варианта:
- Измените метод на статический. Если вы хотите вызывать метод
getAll()
статически, то нужно добавить ключевое словоstatic
к определению метода. Это будет выглядеть так:
public static function getAll() {
return self::all()->take(2);
}
Затем вы сможете вызывать его как:
return Post::getAll();
- Создайте экземпляр модели и вызовите метод как не статический. Если вы не хотите изменять метод на статический, вы можете создать экземпляр модели и затем вызвать метод:
$post = new Post();
return $post->getAll();
Дополнительные советы
- Если ваш метод
getAll()
должен работать с базой данных, то лучше использовать статические методы Eloquent, так как они предназначены для этого. Например:
public static function getAll() {
return Post::take(2)->get();
}
-
Обратите внимание, что в Eloquent основным подходом является статическое использование методов для работы с моделями и их записями. Так что использование статических методов будет более идиоматичным для Laravel.
- Если у вас есть локальные скоупы, помните, что вы должны вызывать их без префикса
scope
, чтобы избежать путаницы:
public function scopeRecent($query) {
return $query->orderBy('created_at', 'desc');
}
// Использование скоупа
$posts = Post::recent()->get();
Заключение
В заключение, ошибка возникает из-за некорректного вызова метода. Для ее устранения измените метод на статический или создайте экземпляр модели перед вызовом метода. Надеюсь, это поможет вам решить вашу проблему!