Warum wird beim Aufrufen einer Methode in einem eloquenten Modell die Meldung "Nicht statische Methode sollte nicht statisch aufgerufen werden" angezeigt?

81

Ich versuche mein Modell in meinen Controller zu laden und habe Folgendes versucht:

return Post::getAll();

habe den Fehler bekommen Non-static method Post::getAll() should not be called statically, assuming $this from incompatible context

Die Funktion im Modell sieht folgendermaßen aus:

public function getAll()
{

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

}

Wie lade ich das Modell richtig in einen Controller und gebe dann seinen Inhalt zurück?

Sam Pettersson
quelle
2 Wege. Erstellen Sie zunächst eine Instanz des Modells und verwenden $obj->getAll()oder machen Sie die Funktion statisch.
Itachi
5
Wenn Sie Folgendes verwenden: ::Sie versuchen, statisch auf eine Methode zuzugreifen, sodass Ihre Funktionssignatur wie folgt deklariert werden sollte : public static function getAll().
Rubens Mariuzzo
@ Sam, ich empfehle Ihnen eine fünfminütige Lektüre über OOP und statische Methoden in PHP: php.net/manual/en/language.oop5.static.php
Rubens Mariuzzo

Antworten:

107

Sie haben Ihre Methode als nicht statisch definiert und versuchen, sie als statisch aufzurufen. Das gesagt...

1.Wenn Sie eine statische Methode aufrufen möchten, sollten Sie die verwenden ::und Ihre Methode als statisch definieren.

// Defining a static method in a Foo class.
public static function getAll() { /* code */ }

// Invoking that static method
Foo::getAll();

2. Wenn Sie andernfalls eine Instanzmethode aufrufen möchten, sollten Sie Ihre Klasse instanziieren ->.

// Defining a non-static method in a Foo class.
public function getAll() { /* code */ }

// Invoking that non-static method.
$foo = new Foo();
$foo->getAll();

Hinweis : In Laravel geben fast alle eloquenten Methoden eine Instanz Ihres Modells zurück, sodass Sie Methoden wie unten gezeigt verketten können:

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

In diesem Code rufen wir die Methode statischall über Facade auf. Danach werden alle anderen Methoden als Instanzmethoden aufgerufen .

Rubens Mariuzzo
quelle
Wie ist getAll () in der 2. Option nicht statisch?
Versuchen Sie Tobemyself
1
Vielen Dank an @TryingTobemyself, mich darüber zu informieren. Ich habe meine Antwort mit Ihrem Vorschlag aktualisiert.
Rubens Mariuzzo
9
In Laravel, almost all Eloquent methods are defined as static.... das ist ein Missverständnis. KEINE sind statisch.
Itachi
@itachi, bitte, können Sie das Missverständnis erklären?
Rubens Mariuzzo
4
Ja, in Laravel, keine Eloquent Verfahren sind als statisch definiert , können wir verwenden sie , da sie als statisch definiert wurden, aber das ist eine Fassade, mehr dazu: laravel.com/docs/facades
Rubens Mariuzzo
36

Warum nicht versuchen, Scope hinzuzufügen? Der Umfang ist ein sehr gutes Merkmal von 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();

Eloquente #scopes in Laravel Docs

Keithics
quelle
2
IMO sollte dies die akzeptierte Antwort sein, da sie spezifisch für Laravel ist und Rubens Antwort korrekt, aber nicht spezifisch genug ist.
Jacob RossDev
8

TL; DR . Sie können dies umgehen, indem Sie Ihre Abfragen als MyModel::query()->find(10);statt ausdrücken MyModel::find(10);.

Um das Beste aus meinem Wissen, beginnend PhpStorm 2.017,2 Code - Inspektion nicht für Methoden wie MyModel::where(), MyModel::find()usw. (lesen Sie in diesem Thread ). Dies kann ziemlich ärgerlich werden, wenn Sie versuchen, die Git-Integration von PhpStorm zu verwenden, bevor Sie Ihren Code festschreiben. PhpStorm wird nicht aufhören, sich über diese statischen Warnungen vor Methodenaufrufen zu beschweren.

Eine elegante Möglichkeit (IMOO), dies zu umgehen, besteht darin, explizit anzurufen,::query() wo immer es sinnvoll ist. Auf diese Weise profitieren Sie von einer kostenlosen automatischen Vervollständigung und einer netten Abfrageformatierung.

Beispiele

Snippet, bei dem sich die Inspektion über statische Methodenaufrufe beschwert

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

Gut formatierter Code ohne Beschwerden

$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();
Anis LOUNIS
quelle
Das Ändern des Codes, um eine falsche IDE-Warnung zu entfernen, klingt nach einer schlechten Idee. Wenn Sie wissen, dass es richtig ist, halten Sie es so.
Zundi
@zundi Ja, Sir, ich stimme voll und ganz zu, dass das Ändern von Code zum Zwecke der Zufriedenheit der IDE nicht immer eine gute Praxis ist, ABER in diesem Fall fügen wir nur einen statischen Methodenaufruf hinzu, der so oder so aufgerufen worden wäre (wir sind hier nur explizit). Andernfalls müssten Sie: entweder diese Inspektion deaktivieren oder eine andere Klasse an einer anderen Stelle mit Anmerkungen versehen ... (eine Hektik!
Stimmen
1
Ebenso gefällt mir diese Antwort sehr gut. Ich bin zunächst kein großer Fan von Fassaden, und die Tatsache, dass PhpStorm sie nicht sofort unterstützt, lässt mich sie weniger mögen. MyModel::query()macht sehr deutlich, was unter der Haube passiert und gefällt gleichzeitig der IDE.
Michasaurus
3

Nur für den Fall, dass dies jemandem hilft, wurde dieser Fehler angezeigt, da ich die angegebene Tatsache, dass das Bereichspräfix beim Aufrufen eines lokalen Bereichs nicht verwendet werden darf, völlig übersehen habe . Wenn Sie also in Ihrem Modell einen lokalen Bereich wie folgt definiert haben:

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

Sie sollten es so nennen:

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

Beachten Sie, dass das Präfix scopeim Aufruf nicht vorhanden ist.

Punkt net
quelle
0

Sie können so geben

public static function getAll()
{

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

}

Und wenn Sie statisch innerhalb Ihrer Controller-Funktion auch aufrufen ..

Karthiga
quelle
4
Sie können dies nicht innerhalb einer statischen Methode
tun
0

Ich bin buchstäblich gerade bei der Antwort in meinem Fall angekommen. Ich erstelle ein System, das eine Erstellungsmethode implementiert hat, daher wurde dieser tatsächliche Fehler angezeigt, da ich auf die überschriebene Version zugegriffen habe, nicht auf die von Eloquent.

Hoffe das hilft?

idro2k
quelle
0

Überprüfen Sie, ob Sie die Methode getAll () im Modell nicht deklariert haben. Dies führt dazu, dass der Controller denkt, dass Sie eine nicht statische Methode aufrufen.

Julio Gonzalez Rios
quelle
0

Um die Syntax so zu verwenden return Post::getAll();, sollten Sie eine magische Funktion __callStaticin Ihrer Klasse haben, die alle statischen Aufrufe verarbeitet:

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

Lösung der ursprünglichen Frage

Sie haben eine nicht statische Methode statisch aufgerufen. Um eine öffentliche Funktion im Modell statisch zu machen, würde dies folgendermaßen aussehen:

public static function {
  
}

Im Allgemeinen:

Post::get()

In diesem speziellen Fall:

Post::take(2)->get()

Eine Sache, auf die ich beim Definieren von Beziehungen und Umfang achten muss, dass ich ein Problem hatte, das dazu führte, dass ein Fehler "Nicht statische Methode sollte nicht statisch aufgerufen werden" ist, ist, wenn sie den gleichen Namen haben, zum Beispiel:

public function category(){
    return $this->belongsTo('App\Category');
}

public function scopeCategory(){
    return $query->where('category', 1);
}

Wenn ich Folgendes mache, erhalte ich den nicht statischen Fehler:

Event::category()->get();

Das Problem ist, dass Laravel meine Beziehungsmethode "Kategorie" anstelle meines Kategoriebereichs (scopeCategory) verwendet. Dies kann durch Umbenennen des Bereichs oder der Beziehung behoben werden. Ich habe beschlossen, die Beziehung umzubenennen:

public function cat(){
    return $this->belongsTo('App\Category', 'category_id');
}

Bitte beachten Sie, dass ich den Fremdschlüssel (category_id) definiert habe, da Laravel sonst stattdessen nach cat_id gesucht hätte und ihn nicht gefunden hätte, da ich ihn in der Datenbank als category_id definiert hatte.

Darren Murphy
quelle