Immer wenn ich Eloquent-Modellen zusätzliche Logik hinzufüge, muss ich am Ende daraus eine machen static Methode (dh weniger als ideal), um sie von der Fassade des Modells aufzurufen. Ich habe versucht, viel zu suchen, wie man das richtig macht, und so ziemlich alle Ergebnisse sprechen über das Erstellen von Methoden, die Teile einer Query Builder-Schnittstelle zurückgeben. Ich versuche herauszufinden, wie man Methoden hinzufügt, die alles zurückgeben und mithilfe der Fassade des Modells aufgerufen werden können.
Sagen wir zum Beispiel, ich habe ein Modell namens Car und will sie alle haben:
$cars = Car::all();
Großartig, außer jetzt, sagen wir, ich möchte das Ergebnis per make in ein mehrdimensionales Array sortieren, damit mein Ergebnis so aussehen könnte:
Anhand dieses theoretischen Beispiels bin ich versucht, eine Methode zu erstellen, die wie folgt aufgerufen werden kann:
$cars = Car::getAllSortedByMake();
Vergessen wir für einen Moment den schrecklichen Methodennamen und die Tatsache, dass er eng an die Datenstruktur gekoppelt ist. Wenn ich im Modell eine Methode wie diese mache:
public function getAllSortedByMake()
{
// Process and return resulting array
return array('...');
}
Und schließlich rufe ich es in meinem Controller auf, ich bekomme diese Ausnahme ausgelöst:
Die nichtstatische Methode Car::getAllSortedByMake() sollte nicht statisch aufgerufen werden, da $this von einem inkompatiblen Kontext ausgeht
TL;DR: Wie kann ich benutzerdefinierte Funktionen hinzufügen, die im Modell sinnvoll sind, ohne sie zu einer statischen Methode zu machen, und sie mithilfe der Fassade des Modells aufrufen?
Bearbeiten:
Dies ist ein theoretisches Beispiel. Vielleicht wäre eine Umformulierung der Frage sinnvoller. Warum sind bestimmte nicht statische Methoden wie z all() oder which() an der Fassade eines Eloquent-Modells verfügbar, aber keine zusätzlichen Methoden, die dem Modell hinzugefügt wurden? Dies bedeutet, dass die __call Magic-Methode wird verwendet, aber wie kann ich meine eigenen Funktionen im Modell erkennen lassen?
Wahrscheinlich ist ein besseres Beispiel für das “Sortieren”, wenn ich eine Berechnung oder einen Algorithmus für ein Datenelement ausführen musste:
Für mich ist es sinnvoll, dass so etwas im Modell enthalten ist, da es domänenspezifisch ist.
Beginnen Sie mit zwei Datentabellen: manufacturers und modelsAlso manufacturers enthält “Ford”, “Honda”, etc und models mit einer manufacturer_id Verknüpfung der model zum manufacturer und enthält “F-150”, “Escape”, “Accord”, “Civic” usw
– Markus Bäcker
14. Mai 2014 um 15:09 Uhr
@MarkBaker Dies war ein theoretisches Beispiel. Meine Frage ist eher auf einer grundlegenden Ebene, wie z. B. warum all() über die Fassade zugänglich? Es ist keine statische Methode, was bedeutet, dass die __call magische Methode verwendet wird. Aus diesem Grund, warum ist arbitraryMethodICreate() nicht zugänglich?
– Jeremy Harris
14. Mai 2014 um 15:30 Uhr
sehen Illuminate\Database\Eloquent\Model, all ist eine statische Methode
– Jeff Lambert
14. Mai 2014 um 15:34 Uhr
cillose: Der Grund dafür ist einfach: all() ist in der Tat eine statische Methode auf der Modelund __call wird in dieser Situation nicht aufgerufen. Es gibt mehr statische Methoden auf der Model Klasse und andere, die Sie übrigens verwenden können Model::method() werden verarbeitet von __callStatic dann __call magische Methoden und an die weitergegeben Eloquent Builder Klasse.
Meine Frage ist eher auf einer grundlegenden Ebene, z. B. warum ist all () über die Fassade zugänglich?
Wenn Sie sich den Laravel Core ansehen, ist all() eigentlich eine statische Funktion
public static function all($columns = array('*'))
Sie haben zwei Möglichkeiten:
public static function getAllSortedByMake()
{
return Car::where('....')->get();
}
oder
public function scopeGetAllSortedByMake($query)
{
return $query->where('...')->get();
}
Beides wird Ihnen dies ermöglichen
Car::getAllSortedByMake();
Ahh, ich hatte in Eloquent von Bereichen gehört, sie aber noch nicht benutzt. Vielen Dank! Ich sehe das all() ist jetzt statisch (das bekomme ich, wenn ich es nicht verifiziere). Ich hatte immer gehört, dass diese Methoden nicht und nur Designmuster verwendet wurden erscheinen auf diese Weise für die Benutzerfreundlichkeit bei gleichzeitiger Aufrechterhaltung der Testbarkeit.
– Jeremy Harris
14. Mai 2014 um 15:40 Uhr
Ja – die meisten Funktionen sind nicht statisch – aus irgendeinem Grund nur einige der Modellfunktionen – wofür Taylor sicher einen guten Grund hat – aber das liegt über meinem Wissen.
– Laurenz
14. Mai 2014 um 15:43 Uhr
Beachten Sie, dass “Bereiche sollten immer eine Abfrage-Generator-Instanz zurückgeben”. Also, wenn Sie verwenden ->get() Sie sollten eine statische Methode und nicht die Scope-Variante verwenden. Beachten Sie auch, dass Bereiche verkettet werden können: Car::GetAllSortedByMake()->GetAllSortedByMake()->otherScopeYouHaveDefined()->where(...)->get().
– Sawny
3. Januar 2016 um 12:36 Uhr
Verwenden Sie keine Bereiche, da die Abfrage nicht identisch ist, da die Bereiche isoliert sind
– fico7489
7. August 2018 um 6:00 Uhr
Tatsächlich können Sie Eloquent Builder erweitern und dort benutzerdefinierte Methoden einfügen.
Schritte zum Erweitern des Builders:
1. Erstellen Sie einen benutzerdefinierten Builder
<?php
namespace App;
class CustomBuilder extends \Illuminate\Database\Eloquent\Builder
{
public function test()
{
$this->where(['id' => 1]);
return $this;
}
}
2.Fügen Sie diese Methode zu Ihrem Basismodell hinzu:
public function newEloquentBuilder($query)
{
return new CustomBuilder($query);
}
3. Führen Sie eine Abfrage mit Methoden in Ihrem benutzerdefinierten Builder aus:
für den obigen Code generierte MySQL-Abfrage lautet:
select * from `users` where `first_name` like ? and (`id` = ?) and `users`.`deleted_at` is null
PS:
Erster Laurenz Beispiel ist Code, der besser für Ihr Repository geeignet ist, nicht für das Modell, aber Sie können mit diesem Ansatz auch keine weiteren Methoden leiten:
public static function getAllSortedByMake()
{
return Car::where('....')->get();
}
Zweiter Laurenz Beispiel ist das schlimmste Ereignis.
public function scopeGetAllSortedByMake($query)
{
return $query->where('...')->get();
}
Viele Leute schlagen vor, Bereiche zum Erweitern des Laravel-Builders zu verwenden, aber das ist eigentlich eine schlechte Lösung, da Bereiche vom eloquenten Builder isoliert werden und Sie nicht dieselbe Abfrage mit denselben Befehlen innerhalb und außerhalb des Bereichs erhalten. Ich schlug PR vor, um zu ändern, ob Bereiche isoliert werden sollten, aber Taylor ignorierte mich.
Weitere Erklärung: Zum Beispiel, wenn Sie Bereiche wie diesen haben:
public function scopeWhereTest($builder, $column, $operator = null, $value = null, $boolean = 'and')
{
$builder->where($column, $operator, $value, $boolean);
}
select * from `users` where (`first_name` like ? and `first_name` like ?) and `users`.`deleted_at` is null
vs
select * from `users` where (`first_name` like ? and (`id` = ?)) and `users`.`deleted_at` is null
Auf den ersten Blick sehen Abfragen gleich aus, sind es aber nicht. Für diese einfache Abfrage spielt es vielleicht keine Rolle, aber für komplizierte Abfragen schon, also verwenden Sie bitte keine Bereiche zum Erweitern des Builders 🙂
für besseren dynamischen Code, anstatt den Modellklassennamen “Car” zu verwenden,
Verwenden Sie einfach “statisch” oder “selbst”.
public static function getAllSortedByMake()
{
//to return "Illuminate\Database\Query\Builder" class object you can add another where as you want
return static::where('...');
//or return already as collection object
return static::where('...')->get();
}
Benutzerdefinierte Methoden des Laravel-Modells -> Der beste Weg ist die Verwendung von Traits
Schritt Nr. 1: Erstellen Sie eine Eigenschaft
Schritt #2: Fügen Sie dem Modell die Eigenschaft hinzu
Schritt #3: Verwenden Sie die Methode
User::first()->confirmEmailNow()
app/Model/User.php
use App\Traits\EmailConfirmation;
class User extends Authenticatable
{
use EmailConfirmation;
//...
}
app/Traits/EmailConfirmation.php
<?php
namespace App\Traits;
trait EmailConfirmation
{
/**
* Set email_verified_at to now and save.
*
*/
public function confirmEmailNow()
{
$this->email_verified_at = now();
$this->save();
return $this;
}
}
14126000cookie-checkMethoden für benutzerdefinierte Laravel-Modelleyes
Beginnen Sie mit zwei Datentabellen:
manufacturers
undmodels
Alsomanufacturers
enthält “Ford”, “Honda”, etc undmodels
mit einermanufacturer_id
Verknüpfung dermodel
zummanufacturer
und enthält “F-150”, “Escape”, “Accord”, “Civic” usw– Markus Bäcker
14. Mai 2014 um 15:09 Uhr
@MarkBaker Dies war ein theoretisches Beispiel. Meine Frage ist eher auf einer grundlegenden Ebene, wie z. B. warum
all()
über die Fassade zugänglich? Es ist keine statische Methode, was bedeutet, dass die__call
magische Methode verwendet wird. Aus diesem Grund, warum istarbitraryMethodICreate()
nicht zugänglich?– Jeremy Harris
14. Mai 2014 um 15:30 Uhr
sehen
Illuminate\Database\Eloquent\Model
,all
ist eine statische Methode– Jeff Lambert
14. Mai 2014 um 15:34 Uhr
cillose: Der Grund dafür ist einfach:
all()
ist in der Tat eine statische Methode auf derModel
und__call
wird in dieser Situation nicht aufgerufen. Es gibt mehr statische Methoden auf derModel
Klasse und andere, die Sie übrigens verwenden könnenModel::method()
werden verarbeitet von__callStatic
dann__call
magische Methoden und an die weitergegebenEloquent Builder
Klasse.– Jarek Tkaczyk
14. Mai 2014 um 15:34 Uhr
Das könnte dir helfen codezen.io/most-useful-laravel-collection-methods
– Sapnesh Naik
8. Mai 2020 um 6:07 Uhr