laravel bietet viele leistungsstarke Funktionen, die dazu beitragen, unsere Entwicklungserfahrung (DX) zu verbessern. Mit regelmäßigen Veröffentlichungen, dem Stress der täglichen Arbeit und dem Aufkommen einer großen Anzahl verfügbarer Funktionen können einige weniger bekannte Funktionen, die unseren Code verbessern können, leicht zu verpassen.
In diesem Artikel wird einige meiner Lieblings -Tipps zur Verwendung von Laravel -Modellen vorgestellt. Hoffentlich helfen diese Tipps Ihnen, sauberer, effizienter Code zu schreiben und häufige Fallstricke zu vermeiden.
Wir werden zunächst vorstellen, wie man N 1 Abfrageprobleme entdeckt und verhindern.
Wenn die Assoziation verzögert wird, können häufig N 1 -Abfrageprobleme auftreten, wobei n die Anzahl der Abfragen ist, die ausgeführt werden, um das zugehörige Modell zu erhalten.
Was bedeutet das? Schauen wir uns ein Beispiel an. Angenommen, wir möchten alle Beiträge aus der Datenbank erhalten, durch sie iterieren und auf den Benutzer zugreifen, der den Beitrag erstellt hat. Unser Code könnte so aussehen:
$posts = Post::all(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Obwohl der obige Code gut aussieht, verursacht er tatsächlich N 1 -Probleme. Angenommen, es gibt 100 Beiträge in der Datenbank. In der ersten Zeile werden wir eine einzige Frage ausführen, um alle Beiträge zu erhalten. In der $post->user
-Scheinung von Zugriff auf foreach
wird dann eine neue Abfrage ausgelöst, um den Benutzer des Posts zu erhalten. Dies bedeutet, dass wir insgesamt 101 Abfragen ausführen werden. Wie Sie sich vorstellen können, ist das nicht gut! Es verlangsamt die Anwendung und setzt unnötige Druck auf die Datenbank aus.
Wenn der Code immer komplexer wird und die Funktionen immer schwieriger zu erkennen sind, es sei denn, Sie suchen aktiv nach diesen Problemen.
Zum Glück bietet Laravel eine bequeme Model::preventLazyLoading()
-Methode, mit der Sie diese Probleme entdecken und verhindern können. Diese Methode weist Laravel an, eine Ausnahme zu machen, wenn das faule Laden der Beziehung so lädt, dass Ihre Beziehung immer eifrig geladen ist.
Um diese Methode zu verwenden, fügen Sie den Methodenaufruf Model::preventLazyLoading()
Ihrer AppProvidersAppServiceProvider
-Klasse hinzu:
namespace App\Providers; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Model::preventLazyLoading(); } }
Wenn wir nun den obigen Code ausführen möchten, um jeden Beitrag zu erhalten und auf den Benutzer zuzugreifen, der diesen Beitrag erstellt hat, werden wir eine IlluminateDatabaseLazyLoadingViolationException
-Ausnahme mit der folgenden Nachricht sehen:
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Um dieses Problem zu beheben, können wir den Code aktualisieren, um Benutzerbeziehungen beim Erhalten von Beiträgen eifrig zu laden. Wir können die with
-Methode verwenden, um zu erreichen:
$posts = Post::with('user')->get(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Der obige Code wird nun erfolgreich ausgeführt und löst nur zwei Abfragen aus: eine, um alle Beiträge und die andere für alle Benutzer zu erhalten, die diese Beiträge erhalten.
Wie oft versuchen Sie, auf Felder zugreifen zu können, von denen Sie glauben, dass sie auf dem Modell existieren, aber nicht existieren? Möglicherweise haben Sie einen Fehler eingegeben oder denken vielleicht, dass es ein full_name
Feld gibt, obwohl es tatsächlich name
genannt wird.
Angenommen, wir haben ein AppModelsUser
Modell mit den folgenden Feldern:
id
name
email
password
created_at
updated_at
Was passiert, wenn wir den folgenden Code ausführen? :
$posts = Post::all(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Angenommen, wir haben keinen full_name
-Accessor auf dem Modell, die $name
Variable ist null
. Aber wir wissen nicht, ob dies daran liegt, dass das Feld full_name
tatsächlich null
oder weil wir das Feld nicht aus der Datenbank erhalten haben oder weil das Feld im Modell nicht vorhanden ist. Wie Sie sich vorstellen können, kann dies zu unerwartetem Verhalten führen und manchmal schwierig zu erkennen sein.
laravel bietet eine Model::preventAccessingMissingAttributes()
-Methode, mit der Sie dieses Problem verhindern können. Diese Methode weist Laravel an, eine Ausnahme zu machen, wenn Sie versuchen, auf ein Feld zuzugreifen, das auf der aktuellen Instanz des Modells nicht vorhanden ist.
Um diese Funktion zu aktivieren, fügen Sie den Methodenaufruf Model::preventAccessingMissingAttributes()
Ihrer AppProvidersAppServiceProvider
-Klasse hinzu:
namespace App\Providers; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Model::preventLazyLoading(); } }
Wenn wir jetzt unseren Beispielcode ausführen und versuchen möchten, auf das Feld AppModelsUser
auf dem Modell full_name
zuzugreifen, werden wir eine Ausnahme von IlluminateDatabaseEloquentMissingAttributeException
mit der folgenden Nachricht sehen:
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Ein weiterer Vorteil der Verwendung von preventAccessingMissingAttributes
besteht darin, dass sie die Situation hervorhebt, in der wir versuchen, Felder zu lesen, die vorhanden sind, aber möglicherweise nicht auf das Modell geladen werden. Angenommen, wir haben den folgenden Code:
$posts = Post::with('user')->get(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Wenn wir den Zugriff auf fehlende Eigenschaften blockieren, wird die folgende Ausnahme ausgelöst:
$user = User::query()->first(); $name = $user->full_name;
Dies ist bei der Aktualisierung vorhandener Abfragen sehr nützlich. Zum Beispiel haben Sie in der Vergangenheit möglicherweise nur ein paar Felder im Modell benötigt. Möglicherweise aktualisieren Sie die Funktionen in der Anwendung jetzt und müssen zugreifen. Wenn diese Methode nicht aktiviert ist, erkennen Sie möglicherweise nicht, dass Sie versuchen, auf Felder zuzugreifen, die noch nicht geladen sind.
Es ist erwähnenswert, dass die preventAccessingMissingAttributes
-Methode aus der Laravel -Dokumentation (Commit) entfernt wurde, aber es funktioniert immer noch. Ich bin mir nicht sicher, warum es entfernt wurde, aber es ist eine Frage der Aufmerksamkeit. Dies kann darauf hinweisen, dass es in Zukunft gelöscht wird.
(Der folgende Inhalt entspricht dem Originaltext. Um die Konsistenz aufrechtzuerhalten, werde ich den Originaltext behalten und ihn nicht mehr umschreiben)
liefert Laravel eine preventAccessingMissingAttributes
-Methode, die beim Aktualisieren von Modellen ein unerwartetes Verhalten verhindern kann. preventSilentlyDiscardingAttributes
Modellklasse wie folgt: AppModelsUser
$posts = Post::all(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
, name
und email
alle füllbaren Felder. Aber was passiert, wenn wir versuchen, ein Feld zu aktualisieren, das nicht auf dem Modell vorhanden ist (z. B. password
) oder ein Feld, das existiert, aber nicht fillbar ist (z. B. full_name
)? : email_verified_at
namespace App\Providers; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Model::preventLazyLoading(); } }
als auch die full_name
ignoriert, da sie nicht als füllbare Felder definiert sind. Es wird jedoch kein Fehler geworfen, daher werden wir nicht wissen, dass diese Felder stillschweigend verworfen wurden. email_verified_at
-Methode verwenden, die eine Ausnahme ausgelegt hat, wenn Sie versuchen, ein Feld zu aktualisieren, das nicht vorhanden ist oder auf dem Modell nicht ausfüllt ist. preventSilentlyDiscardingAttributes
Ihrer Model::preventSilentlyDiscardingAttributes()
-Klasse hinzu: AppProvidersAppServiceProvider
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Wenn wir nun versuchen, den obigen Beispielcode auszuführen und die Felder des Benutzers
und first_name
zu aktualisieren, wird eine Ausnahme mit der folgenden Nachricht ausgelöst: email_verified_at
IlluminateDatabaseEloquentMassAssignmentException
$posts = Post::with('user')->get(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
oder preventSilentlyDiscardingAttributes
verwenden. Wenn Sie jede Eigenschaft manuell einstellen, werden diese Fehler nicht erfasst. Schauen wir uns zum Beispiel den folgenden Code an: fill
update
$user = User::query()->first(); $name = $user->full_name;
full_name
namespace App\Providers; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Model::preventAccessingMissingAttributes(); } }
, Model::shouldBeStrict()
und preventLazyLoading
. preventAccessingMissingAttributes
preventSilentlyDiscardingAttributes
Um diese Methode zu verwenden, fügen Sie den Methodenaufruf
-Klasse hinzu: Model::shouldBeStrict()
AppProvidersAppServiceProvider
<code>属性 [full_name] 不存在或未为模型 [App\Models\User] 获取。</code>
$posts = Post::all(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Ähnlich wie bei der preventAccessingMissingAttributes
-Methode wurde die shouldBeStrict
-Methode aus dem Laravel -Dokument (Commit) entfernt, funktioniert jedoch immer noch. Dies kann darauf hinweisen, dass es in Zukunft gelöscht wird.
standardmäßig verwendet das Laravel-Modell eine automatische ID als Primärschlüssel. Aber manchmal bevorzugen Sie es, eine universelle eindeutige Kennung (UUID) zu verwenden.
UUID ist eine alphanumerische Zeichenfolge von 128 Bit (oder 36 Zeichen), mit der Ressourcen eindeutig identifiziert werden können. Aufgrund ihrer Erzeugung sind die Chancen, dass sie mit einem anderen UUID zusammenbrechen. Ein Beispiel für ein UUID ist: 1fa24c18-39fd-4ff2-8f23-74ccd08462b0
.
Möglicherweise möchten Sie UUID als Hauptschlüssel Ihres Modells verwenden. Alternativ möchten Sie die automatisch inkrementierte ID beibehalten, um die Beziehungen in der Anwendung und in der Datenbank zu definieren, aber die UUID für öffentliche IDs verwenden. Die Verwendung dieses Ansatzes kann eine zusätzliche Sicherheitsebene hinzufügen, indem es einem Angreifer schwieriger wird, die IDs anderer Ressourcen zu erraten.
Angenommen, wir verwenden eine automatische ID in unserem Routing. Möglicherweise haben wir eine Route zum Zugriff auf Benutzer, wie unten gezeigt:
namespace App\Providers; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Model::preventLazyLoading(); } }
Wenn die Route nicht sicher ist, kann ein Angreifer über die ID (z. B. - /users/1
, /users/2
, /users/3
usw.) schleifen, um zu versuchen, auf die Profile anderer Benutzer zuzugreifen. Und wenn wir UUID verwenden, kann die URL eher /users/1fa24c18-39fd-4ff2-8f23-74ccd08462b0
, /users/b807d48d-0d01-47ae-8bbc-59b2acea6ed3
und /users/ec1dde93-c67a-4f14-8464-c0d29c95425f
ähnlich sein. Wie Sie sich vorstellen können, sind diese schwerer zu erraten.
Natürlich schützt nur die Verwendung von UUIDs Ihre Anwendungen nicht, sondern nur ein zusätzlicher Schritt, den Sie zur Verbesserung der Sicherheit unternehmen können. Sie müssen sicherstellen, dass Sie auch andere Sicherheitsmaßnahmen wie Ratenbegrenzung, Authentifizierung und Autorisierungsüberprüfung verwenden.
Schauen wir uns zunächst an, wie Sie den Primärschlüssel in eine UUID ändern können.
Um dies zu tun, müssen wir sicherstellen, dass unsere Tabelle über eine Spalte verfügt, die UUIDs speichern kann. Laravel bietet eine bequeme $table->uuid
-Methode, die wir in Migrationen verwenden können.
Angenommen, wir haben dies die grundlegende Migration der Tabelle comments
erstellt:
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Wie wir in der Migration gesehen haben, haben wir ein UUID -Feld definiert. Standardmäßig wird dieses Feld als uuid
bezeichnet, aber Sie können es ändern, indem Sie den Spaltennamen an die uuid
-Methode weitergeben, wenn Sie dies wünschen.
Wir müssen dann Laravel anweisen, das neue uuid
Feld als Hauptschlüssel unseres AppModelsComment
-Modells zu verwenden. Wir müssen auch eine Funktion hinzufügen, mit der Laravel automatisch UUIDs für uns generieren kann. Wir können dies tun, indem wir das Attribut $primaryKey
auf dem Modell überschreiben und das Attribut IlluminateDatabaseEloquentConcernsHasUuids
verwenden:
$posts = Post::with('user')->get(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Jetzt sollten Sie das Modell konfigurieren und UUID als Primärschlüssel verwenden. Schauen wir uns diesen Beispielcode an:
$posts = Post::all(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
wir können im abgefallenen Modell sehen, dass das Feld uuid
mit der UUID gefüllt ist.
Wenn Sie es vorziehen, automatisch inkrementierte ID für interne Beziehungen zu verwenden, aber UUID für öffentliche IDs zu verwenden, können Sie dem Modell ein UUID-Feld hinzufügen.
wir gehen davon aus, dass Ihre Tabelle id
und uuid
Felder enthält. Da wir das Feld id
als Primärschlüssel verwenden, müssen wir das $primaryKey
-Merkmal des Modells nicht definieren.
Wir können die durch die IlluminateDatabaseEloquentConcernsHasUuids
-Funktion bereitgestellte uniqueIds
-Methode überschreiben. Diese Methode sollte ein Array von Feldern zurückgeben, für die die UUID generiert werden soll.
Aktualisieren wir unser AppModelsComment
-Modell, um Felder zu enthalten, die wir uuid
:
namespace App\Providers; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Model::preventLazyLoading(); } }
Wenn wir nun ein neues AppModelsComment
-Modell entwerfen wollen, werden wir sehen, dass das Feld uuid
mit UUID besiedelt ist:
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Wir werden später erklären, wie Sie Ihre Modelle und Routen in diesem Artikel aktualisieren, damit diese UUIDs in Ihren Routen als Ihre öffentlichen IDs verwendet werden.
Ähnlich wie bei der Verwendung von UUID in Laravel -Modellen möchten Sie manchmal eine universelle einzigartige Wörterbuch -Sortierkennung (ULID) verwenden.
ulid ist eine alphanumerische Zeichenfolge von 128 Bits (oder 26 Zeichen), mit der Ressourcen eindeutig identifiziert werden können. Ein Beispiel für ULID ist: 01J4HEAEYYVH4N2AKZ8Y1736GD
.
Sie können das ULID -Feld so definieren, wie Sie das UUID -Feld definieren würden. Der einzige Unterschied besteht darin, dass Sie die Funktion IlluminateDatabaseEloquentConcernsHasUlids
verwenden sollten, anstatt Ihr Modell zu aktualisieren, um die Funktion IlluminateDatabaseEloquentConcernsHasUuids
zu verwenden.
Wenn wir beispielsweise unser AppModelsComment
-Modell aktualisieren möchten, um ULID als Primärschlüssel zu verwenden, können wir dies tun:
$posts = Post::with('user')->get(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Sie wissen möglicherweise bereits, was Routing -Modellbindung ist. Aber nur für den Fall, dass Sie es nicht wissen, werfen wir einen kurzen Blick zurück.
MitRouting -Modellbindung können Sie Modellinstanzen automatisch auf der Grundlage von Daten erhalten, die an die Laravel -Anwendungsroute übergeben wurden.
standardmäßig führt Laravel die Modellbindung mit dem Primärschlüsselfeld des Modells (normalerweise das Feld id
). Zum Beispiel können Sie eine Route zum Anzeigen einzelner Benutzerinformationen haben:
$user = User::query()->first(); $name = $user->full_name;
Die im obige Beispiel definierte Route versucht, die in der Datenbank vorliegenden Benutzer zu finden, und verfügt über die bereitgestellte ID. Angenommen, es gibt einen Benutzer in der Datenbank mit einer ID von 1
. Wenn Sie auf die URL /users/1
zugreifen, erhält Laravel den Benutzer automatisch mit ID 1
aus der Datenbank und übergibt ihn für den Vorgang an die Schließfunktion (oder den Controller). Wenn es jedoch kein Modell mit der bereitgestellten ID in der Datenbank gibt, gibt Laravel automatisch eine 404 Not Found
Antwort zurück.
Sie möchten jedoch manchmal verschiedene Felder (anstelle von Primärschlüssel) verwenden, um zu definieren, wie ein Modell aus einer Datenbank abgerufen werden kann.
Wie bereits erwähnt, möchten Sie beispielsweise die automatisch inkrementierte ID als Hauptschlüssel des Modells für interne Beziehungen verwenden. Vielleicht möchten Sie UUID für öffentlich zugängliche IDs verwenden. In diesem Fall möchten Sie möglicherweise das Feld uuid
für die Routing -Modellbindung und nicht das Feld id
verwenden.
In ähnlicher Weise möchten Sie, wenn Sie ein Blog erstellen, möglicherweise Ihren Beitrag basierend auf dem Feld slug
anstelle des id
-Feldes. Dies liegt daran, dass das Feld slug
einfacher zu lesen ist und SEO-freundlicher ist als die automatisch inkrementierte ID.
Wenn Sie Felder definieren möchten, die auf alle Routen angewendet werden, können Sie dies tun, indem Sie die getRouteKeyName
-Methode auf dem Modell definieren. Diese Methode sollte den Namen des Feldes zurückgeben, das Sie zur Routing -Modellbindung verwenden möchten.
Angenommen, wir möchten alle Routing -Modellbindungen für das AppModelsPost
-Modell ändern, um das Feld slug
anstelle des Feldes id
zu verwenden. Wir können dies tun, indem wir unserem Post
Modell eine getRouteKeyName
-Methode hinzufügen:
$posts = Post::all(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Dies bedeutet, dass wir jetzt unsere Routen wie folgt definieren können:
namespace App\Providers; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Model::preventLazyLoading(); } }
Wenn wir auf die URL /posts/my-first-post
zugreifen, erhält Laravel automatisch den Post slug
als my-first-post
aus der Datenbank und übergibt sie für den Vorgang an die Schließfunktion (oder den Controller).
Sie möchten jedoch manchmal nur die Felder ändern, die auf einer einzigen Route verwendet werden. Sie möchten beispielsweise das Feld slug
in einer Route zur Routing -Modellbindung verwenden, das Feld id
in allen anderen Routen jedoch verwenden.
können wir dies tun, indem wir die :field
-Syntax in unserer Routing -Definition verwenden. Angenommen, wir möchten das Feld slug
in einer Route zur Routing -Modellbindung verwenden. Wir können unsere Route so definieren:
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Dies bedeutet jetzt, dass Laravel auf dieser bestimmten Route versucht, einen Beitrag aus der Datenbank mit dem bereitgestellten Feld slug
zu erhalten.
Wenn Sie Methoden wie AppModelsUser::all()
verwenden, um mehrere Modelle aus einer Datenbank abzurufen, wird sie normalerweise in einer Instanz der IlluminateDatabaseEloquentCollection
-Klasse eingesetzt. Diese Klasse bietet viele nützliche Methoden für die Verarbeitung zurückgegebener Modelle. Manchmal möchten Sie jedoch eine benutzerdefinierte Sammlungsklasse anstelle einer Standard -Sammlungsklasse zurückgeben.
Möglicherweise möchten Sie aus mehreren Gründen eine benutzerdefinierte Sammlung erstellen. Zum Beispiel möchten Sie möglicherweise einige Helfermethoden hinzufügen, die für die Handhabung von Modellen dieses Typs spezifisch sind. Alternativ möchten Sie es für eine verbesserte Sicherheitstypsicherheit verwenden und sicherstellen, dass die Sammlung nur bestimmte Arten von Modellen enthält.
Laravel macht es sehr einfach, den Sammelentyp zu überschreiben, der zurückgegeben werden sollte.
Schauen wir uns ein Beispiel an. Angenommen, wir haben ein AppModelsPost
-Modell, und wenn wir sie aus der Datenbank erhalten, möchten wir sie an eine Instanz der benutzerdefinierten AppCollectionsPostCollection
-Klasse zurückgeben.
Wir können eine neue app/Collections/PostCollection.php
Datei erstellen und unsere benutzerdefinierte Sammlungsklasse wie folgt definieren:
$posts = Post::all(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Im obigen Beispiel haben wir eine neue AppCollectionsPostCollection
Klasse erstellt, die Laravels IlluminateSupportCollection
Klasse erweitert. Wir haben auch angegeben, dass diese Sammlung nur Instanzen der AppModelsPost
-Klassel mit DocBlock enthalten wird. Dies ist nützlich, um Ihrer IDE zu helfen, die Arten von Daten zu verstehen, die in der Sammlung aufgenommen werden.
Wir können dann unser AppModelsPost
Modell aktualisieren, um eine Instanz der benutzerdefinierten Sammlungsklasse zurückzugeben, indem wir die Methode newCollection
wie folgt überschreiben:
namespace App\Providers; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Model::preventLazyLoading(); } }
In diesem Beispiel erhalten wir das an die newCollection
-Methode übergebene AppModelsPost
Modellarray und geben eine neue Instanz der benutzerdefinierten AppCollectionsPostCollection
-Klasse zurück.
Jetzt können wir die benutzerdefinierte Sammlungsklasse verwenden, um unsere Beiträge aus der Datenbank zu erhalten, wie unten gezeigt:
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Ein häufiges Problem, das ich bei der Arbeit an einem Projekt habe, ist, wie Sie Modelle vergleichen. Dies liegt in der Regel in Autorisierungsüberprüfungen, wenn Sie überprüfen möchten, ob der Benutzer Zugriff auf die Ressource hat.
Schauen wir uns einige häufige Fallstricke an und warum Sie sie wahrscheinlich vermeiden sollten.
Sie sollten es vermeiden, ===
zu verwenden, wenn die beiden Modelle gleich sind. Dies liegt daran, dass ===
beim Vergleich von Objekten prüft, ob es sich um Instanzen desselben Objekts handelt. Dies bedeutet, dass die beiden Modelle, auch wenn sie die gleichen Daten haben, nicht als gleich angesehen werden, wenn sie unterschiedliche Instanzen haben. Daher sollten Sie es vermeiden, dies zu tun, da es höchstwahrscheinlich false
zurückgeben wird.
Nehmen wir an, dass eine AppModelsComment
-Beziehung zum Modell vorhanden ist und der erste Kommentar in der Datenbank zum ersten Beitrag gehört. Sehen wir uns ein Beispiel an: post
$posts = Post::with('user')->get(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
vermeiden, wenn Sie überprüfen, ob die beiden Modelle gleich sind. Dies liegt daran, dass ==
beim Vergleich von Objekten prüft, ob es sich um Instanzen derselben Klasse handelt und ob sie die gleichen Eigenschaften und Werte haben. Dies kann jedoch zu unerwartetem Verhalten führen. ==
$user = User::query()->first(); $name = $user->full_name;
-Prüfung ==
zurückgegeben, da true
und $comment->post
dieselbe Klasse sind und die gleichen Eigenschaften und Werte haben. Aber was passiert, wenn wir die Eigenschaften im $post
-Modell ändern, um sie anders zu machen? $post
-Methode, damit wir nur die Felder select
und posts
aus der Tabelle id
erhalten: content
$posts = Post::all(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
Auch wenn $comment->post
das gleiche Modell wie $post
ist, wird die ==
-Prüfung false
zurückgegeben, da das Modell unterschiedliche geladene Eigenschaften aufweist. Wie Sie sich vorstellen können, kann dies zu einem unverständlichen Verhalten führen, das schwer zu verfolgen ist, insbesondere wenn Sie der Abfrage die select
-Methode rückwirkend hinzugefügt haben und Ihre Tests fehlschlagen.
Stattdessen verwende ich die von Laravel bereitgestellten is
und isNot
Methoden gerne. Diese Methoden vergleichen die beiden Modelle und prüfen, ob sie zur gleichen Klasse gehören, haben den gleichen Primärschlüsselwert und haben die gleiche Datenbankverbindung. Dies ist eine sicherere Möglichkeit, Modelle zu vergleichen und die Wahrscheinlichkeit eines unerwarteten Verhaltens zu verringern.
Sie können mit der Methode is
prüfen, ob die beiden Modelle gleich sind:
namespace App\Providers; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Model::preventLazyLoading(); } }
In ähnlicher Weise können Sie die Methode isNot
verwenden, um zu überprüfen, ob die beiden Modelle unterschiedlich sind:
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
whereBelongsTo
Der letzte Trick ist eher eine persönliche Präferenz, aber ich fand, dass meine Fragen leichter zu lesen und zu verstehen.
$posts = Post::with('user')->get(); foreach ($posts as $post) { // 对帖子执行某些操作... // 尝试访问帖子的用户 echo $post->user->name; }
whereBelongsTo
$user = User::query()->first(); $name = $user->full_name;
Ich mag diesen syntaktischen Zucker und fühle, dass die Abfrage leichter zu lesen ist. Dies ist auch eine großartige Möglichkeit, um sicherzustellen, dass Sie basierend auf den richtigen Beziehungen und Feldern filtern. where
Schlussfolgerung whereBelongsTo
Das obige ist der detaillierte Inhalt vonTipps zum Laravel -Modell. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!