Maison > développement back-end > tutoriel php > Conseils de modèle Laravel

Conseils de modèle Laravel

百草
Libérer: 2025-03-05 16:44:11
original
388 Les gens l'ont consulté

Laravel Model Tips

Laravel propose de nombreuses fonctionnalités puissantes qui aident à améliorer notre expérience de développement (DX). Mais avec des versions régulières, le stress du travail quotidien et l'avènement d'un grand nombre de fonctionnalités disponibles, il est facile de manquer certaines fonctionnalités moins connues qui peuvent aider à améliorer notre code.

Cet article présentera certains de mes conseils d'utilisation du modèle Laravel préféré. Espérons que ces conseils vous aideront à rédiger un code plus propre et plus efficace et vous aideront à éviter les pièges courants.

Découvrez et empêchez n 1 problèmes

Nous allons d'abord introduire comment découvrir et prévenir les problèmes de la requête.

Lorsque l'association est retardée de chargement, des problèmes de requête communs communs peuvent se produire, où n est le nombre de requêtes exécutées pour obtenir le modèle connexe.

Qu'est-ce que cela signifie? Regardons un exemple. Supposons que nous voulons obtenir tous les messages de la base de données, les itérer à travers eux et accéder à l'utilisateur qui a créé le message. Notre code peut ressembler à ceci:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Bien que le code ci-dessus semble bon, il provoque en fait des problèmes. Supposons qu'il y ait 100 messages dans la base de données. Sur la première ligne, nous exécuterons une seule requête pour obtenir tous les messages. Ensuite, dans la boucle $post->user de l'accès à foreach, cela déclenchera une nouvelle requête pour obtenir l'utilisateur de la publication; Cela signifie que nous exécuterons un total de 101 requêtes. Comme vous pouvez l'imaginer, ce n'est pas bon! Il ralentit l'application et met une pression inutile sur la base de données.

à mesure que le code devient de plus en plus complexe et que les fonctionnalités deviennent de plus en plus difficiles à repérer, sauf si vous recherchez activement ces problèmes.

Heureusement, Laravel fournit une méthode pratique Model::preventLazyLoading() que vous pouvez utiliser pour aider à découvrir et à prévenir ces n 1 problèmes. Cette méthode demandera à Laravel de lancer une exception lorsque paresseux chargera la relation, afin que vous puissiez vous assurer que votre relation est toujours chargée avec impatience.

Pour utiliser cette méthode, ajoutez l'appel Model::preventLazyLoading() Méthode à votre classe AppProvidersAppServiceProvider:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Maintenant, si nous voulons exécuter le code ci-dessus pour obtenir chaque message et accéder à l'utilisateur qui a créé ce message, nous verrons une exception IlluminateDatabaseLazyLoadingViolationException lancée avec le message suivant:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Pour résoudre ce problème, nous pouvons mettre à jour le code pour charger avec impatience les relations utilisateur lors de l'obtention de publications. Nous pouvons utiliser la méthode with pour réaliser:

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le code ci-dessus s'exécutera désormais avec succès et déclenchera uniquement deux requêtes: l'une pour obtenir tous les messages et l'autre pour tous les utilisateurs qui obtiennent ces messages.

Propriétés pour empêcher l'accès à manquer

À quelle fréquence essayez-vous d'accéder aux champs qui, selon vous, existent sur le modèle mais n'existent pas? Vous avez peut-être saisi une erreur, ou vous pourriez penser qu'il y a un champ full_name, alors qu'en fait il est appelé name.

Supposons que nous ayons un modèle AppModelsUser avec les champs suivants:

  • id
  • name
  • email
  • password
  • created_at
  • updated_at

Que se passe-t-il si nous exécutons le code suivant? :

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Supposons que nous n'ayons pas d'accessoire full_name sur le modèle, la variable $name sera null. Mais nous ne savons pas si c'est parce que le champ full_name est en fait null, ou parce que nous n'avons pas obtenu le champ de la base de données, ou parce que le champ n'existe pas dans le modèle. Comme vous pouvez l'imaginer, cela peut conduire à un comportement inattendu et peut parfois être difficile à détecter.

Laravel fournit une méthode Model::preventAccessingMissingAttributes() que vous pouvez utiliser pour aider à prévenir ce problème. Cette méthode demandera à Laravel de lancer une exception lorsque vous essayez d'accéder à un champ qui n'existe pas sur l'instance actuelle du modèle.

pour activer cette fonctionnalité, ajoutez l'appel Model::preventAccessingMissingAttributes() Méthode à votre classe AppProvidersAppServiceProvider:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Maintenant, si nous voulons exécuter notre exemple de code et essayer d'accéder au champ AppModelsUser sur le modèle full_name, nous verrons une exception IlluminateDatabaseEloquentMissingAttributeException lancée avec le message suivant:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Un autre avantage de l'utilisation de preventAccessingMissingAttributes est qu'il met en évidence la situation où nous essayons de lire des champs qui existent mais qui peuvent ne pas être chargés sur le modèle. Par exemple, supposons que nous ayons le code suivant:

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Si nous bloquons l'accès aux propriétés manquantes, l'exception suivante sera lancée:

$user = User::query()->first();

$name = $user->full_name;
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Ceci est très utile lors de la mise à jour des requêtes existantes. Par exemple, dans le passé, vous n'aviez peut-être besoin que de quelques champs dans le modèle. Cependant, vous pouvez mettre à jour les fonctionnalités de l'application dès maintenant et vous devez accéder à un autre champ. Si cette méthode n'est pas activée, vous ne réalisez peut-être pas que vous essayez d'accéder aux champs qui ne sont pas encore chargés.

Il convient de noter que la méthode preventAccessingMissingAttributes a été supprimée de la documentation de Laravel (commit), mais cela fonctionne toujours. Je ne sais pas pourquoi il a été supprimé, mais c'est une question d'attention. Cela peut indiquer qu'il sera supprimé à l'avenir.

(Le contenu suivant est le même que le texte d'origine. Afin de maintenir la cohérence, je garderai le texte d'origine et je ne le réécrivrai plus)

Empêcher le rejet silencieux des attributs

similaire à preventAccessingMissingAttributes, Laravel fournit une méthode preventSilentlyDiscardingAttributes qui peut aider à prévenir le comportement inattendu lors de la mise à jour des modèles.

Supposons que vous ayez une classe de modèle AppModelsUser comme suit:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Comme nous pouvons le voir, les champs name, email et password sont tous des champs remplissables. Mais que se passe-t-il si nous essayons de mettre à jour un champ qui n'existe pas sur le modèle (par exemple full_name) ou un champ qui existe mais n'est pas remplir (par exemple 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();
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Si nous exécutons le code ci-dessus, les champs full_name et email_verified_at seront ignorés car ils ne sont pas définis comme des champs remplissables. Mais aucune erreur n'est lancée, nous ne saurons donc pas que ces champs ont été jetés silencieusement.

Comme vous vous y attendez, cela peut entraîner des erreurs difficiles à trouver dans l'application, surtout si quelque chose d'autre dans votre instruction "Update" a en fait été mis à jour. Par conséquent, nous pouvons utiliser la méthode preventSilentlyDiscardingAttributes, qui lancera une exception lorsque vous essayez de mettre à jour un champ qui n'existe pas ou n'est pas rempli sur le modèle.

Pour utiliser cette méthode, ajoutez l'appel Model::preventSilentlyDiscardingAttributes() Méthode à votre classe AppProvidersAppServiceProvider:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le code ci-dessus obligera une erreur à lancer.

Maintenant, si nous essayons d'exécuter l'exemple de code ci-dessus et de mettre à jour les champs first_name et email_verified_at de l'utilisateur, une exception IlluminateDatabaseEloquentMassAssignmentException est lancée avec le message suivant:

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Il convient de noter que la méthode preventSilentlyDiscardingAttributes ne metra en évidence les champs non remplis lorsque vous utilisez des méthodes telles que fill ou update. Si vous définissez chaque propriété manuellement, il n'attrapera pas ces erreurs. Par exemple, regardons le code suivant:

$user = User::query()->first();

$name = $user->full_name;
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans le code ci-dessus, le champ full_name n'existe pas dans la base de données, donc Laravel ne le capture pas pour nous, mais au niveau de la base de données. Si vous utilisez une base de données MySQL, vous verrez une erreur comme ceci:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventAccessingMissingAttributes();
    }
}
Copier après la connexion

Activer le mode strict du modèle

Si vous souhaitez utiliser les trois méthodes que nous avons mentionnées plus tôt, vous pouvez les activer immédiatement en utilisant la méthode Model::shouldBeStrict(). Cette méthode permet les paramètres preventLazyLoading, preventAccessingMissingAttributes et preventSilentlyDiscardingAttributes.

Pour utiliser cette méthode, ajoutez l'appel Model::shouldBeStrict() Méthode à votre classe AppProvidersAppServiceProvider:

<code>属性 [full_name] 不存在或未为模型 [App\Models\User] 获取。</code>
Copier après la connexion

Cela équivaut à:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Semblable à la méthode preventAccessingMissingAttributes, la méthode shouldBeStrict a été supprimée du document Laravel (commit), mais cela fonctionne toujours. Cela peut indiquer qu'il sera supprimé à l'avenir.

en utilisant UUID

Par défaut, le modèle Laravel utilise un ID auto-incrémental comme clé principale. Mais parfois, vous préférez utiliser un identifiant unique universel (UUID).

UUID est une chaîne alphanumérique de 128 bits (ou 36 caractères) qui peut être utilisée pour identifier de manière unique les ressources. En raison de la façon dont ils sont générés, les chances qu'ils s'affrontent avec un autre UUID sont extrêmement faibles. Un exemple de UUID est: 1fa24c18-39fd-4ff2-8f23-74ccd08462b0.

Vous voudrez peut-être utiliser UUID comme clé principale de votre modèle. Alternativement, vous voudrez peut-être conserver l'ID incrémentée automatiquement pour définir les relations dans l'application et la base de données, mais utilisez l'UUID pour les ID qui s'orientent au public. L'utilisation de cette approche peut ajouter une couche de sécurité supplémentaire en rendant plus difficile pour un attaquant de deviner les identifiants d'autres ressources.

Par exemple, supposons que nous utilisons un ID auto-incrémental dans notre routage. Nous pouvons avoir un itinéraire pour accéder aux utilisateurs, comme indiqué ci-dessous:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Si l'itinéraire n'est pas sécurisé, un attaquant peut boucler sur l'ID (par exemple - /users/1, /users/2, /users/3, etc.) pour essayer d'accéder aux profils d'autres utilisateurs. Et si nous utilisons UUID, l'URL peut ressembler davantage à /users/1fa24c18-39fd-4ff2-8f23-74ccd08462b0, /users/b807d48d-0d01-47ae-8bbc-59b2acea6ed3 et /users/ec1dde93-c67a-4f14-8464-c0d29c95425f. Comme vous pouvez l'imaginer, ceux-ci sont plus difficiles à deviner.

Bien sûr, le simple fait d'utiliser des UUID ne protège pas vos applications, ce ne sont qu'une étape supplémentaire que vous pouvez prendre pour améliorer la sécurité. Vous devez vous assurer d'utiliser également d'autres mesures de sécurité telles que la limitation des taux, l'authentification et la vérification de l'autorisation.

Utilisez UUID comme clé primaire

Voyons d'abord comment changer la clé primaire en UUID.

Pour ce faire, nous devons nous assurer que notre table a une colonne qui peut stocker des UUID. Laravel fournit une méthode pratique $table->uuid que nous pouvons utiliser dans les migrations.

Supposons que cela ait créé la migration de base du tableau comments:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Comme nous l'avons vu dans la migration, nous avons défini un champ UUID. Par défaut, ce champ sera appelé uuid, mais vous pouvez le modifier en passant le nom de la colonne à la méthode uuid si vous le souhaitez.

Nous devons ensuite demander à Laravel d'utiliser le nouveau champ uuid comme la clé principale de notre modèle AppModelsComment. Nous devons également ajouter une fonctionnalité qui permettra à Laravel de générer automatiquement des UUID pour nous. Nous pouvons le faire en écrasant l'attribut $primaryKey sur le modèle et en utilisant l'attribut IlluminateDatabaseEloquentConcernsHasUuids:

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Maintenant, vous devez configurer le modèle et être prêt à utiliser UUID comme clé principale. Jetons un coup d'œil à cet exemple de code:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous pouvons voir dans le modèle vidé que le champ uuid est rempli de l'UUID.

Ajouter un champ UUID au modèle

Si vous préférez utiliser l'ID incrémenté automatiquement pour des relations internes, mais utilisez UUID pour les ID orientés publics, vous pouvez ajouter un champ UUID au modèle.

Nous supposons que votre table a des champs id et uuid. Étant donné que nous utiliserons le champ id comme clé principale, nous n'avons pas besoin de définir l'attribut $primaryKey sur le modèle.

Nous pouvons remplacer la méthode IlluminateDatabaseEloquentConcernsHasUuids fournie par la fonction uniqueIds. Cette méthode doit renvoyer un tableau de champs pour lesquels l'UUID doit être généré.

mettons à jour notre modèle AppModelsComment pour contenir des champs que nous appelons uuid:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Maintenant, si nous voulons vider un nouveau modèle AppModelsComment, nous verrons que le champ uuid est rempli de UUID:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous expliquerons plus tard comment mettre à jour vos modèles et itinéraires dans cet article afin que ces Uuids soient utilisés comme vos identifiants orientés publics dans vos itinéraires.

Utiliser ULID

Similaire à l'utilisation de modèles UUID dans Laravel, vous pouvez parfois utiliser un identifiant de tri de dictionnaire unique universel (ULID).

ULID est une chaîne alphanumérique de 128 bits (ou 26 caractères) qui peut être utilisée pour identifier de manière unique les ressources. Un exemple d'ULID est: 01J4HEAEYYVH4N2AKZ8Y1736GD.

Vous pouvez définir le champ ulide comme vous définissez le champ UUID. La seule différence est que vous devez utiliser la fonction IlluminateDatabaseEloquentConcernsHasUlids au lieu de mettre à jour votre modèle pour utiliser la fonction IlluminateDatabaseEloquentConcernsHasUuids.

Par exemple, si nous voulons mettre à jour notre modèle AppModelsComment pour utiliser ulid comme clé principale, nous pouvons le faire:

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Modifier le champ utilisé pour les liaisons du modèle de routage

Vous savez peut-être déjà ce qu'est la liaison du modèle de routage. Mais juste au cas où vous ne le sauriez pas, jetons un coup d'œil en arrière.

La liaison du modèle de routage vous permet d'obtenir automatiquement des instances de modèle en fonction des données transmises à la route d'application Laravel.

Par défaut, Laravel acheminera la liaison du modèle à l'aide du champ de clé primaire du modèle (généralement le champ id). Par exemple, vous pouvez avoir un itinéraire pour afficher des informations utilisateur individuelles:

$user = User::query()->first();

$name = $user->full_name;
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

L'itinéraire défini dans l'exemple ci-dessus essaiera de trouver des utilisateurs présents dans la base de données et aura l'ID fourni. Par exemple, supposons qu'il y ait un utilisateur dans la base de données avec un ID de 1. Lorsque vous accédez à l'URL /users/1, Laravel obtiendra automatiquement l'utilisateur avec ID 1 à partir de la base de données et le transmet à la fonction de fermeture (ou contrôleur) pour les opérations. Cependant, s'il n'y a pas de modèle avec l'ID fourni dans la base de données, Laravel renverra automatiquement une réponse 404 Not Found.

Cependant, vous pouvez parfois utiliser différents champs (plutôt que les clés primaires) pour définir comment récupérer un modèle à partir d'une base de données.

Par exemple, comme nous l'avons mentionné précédemment, vous voudrez peut-être utiliser l'ID incrémenté automatique comme la clé principale du modèle pour les relations internes. Mais vous voudrez peut-être utiliser UUID pour les identifiants orientés publics. Dans ce cas, vous souhaiterez peut-être utiliser le champ uuid pour la liaison du modèle de routage, plutôt que le champ id.

De même, si vous construisez un blog, vous voudrez peut-être obtenir votre message en fonction du champ slug au lieu du champ id. En effet slug

Modifier tous les champs routés

Si vous souhaitez définir des champs appliqués à tous les itinéraires, vous pouvez le faire en définissant la méthode

sur le modèle. Cette méthode doit renvoyer le nom du champ que vous souhaitez utiliser pour la liaison du modèle de routage. getRouteKeyName

Par exemple, supposons que nous voulons modifier toutes les liaisons du modèle de routage pour que le modèle

utilise le champ AppModelsPost au lieu du champ slug. Nous pouvons le faire en ajoutant une méthode id à notre modèle Post: getRouteKeyName

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Cela signifie que nous pouvons maintenant définir nos itinéraires comme ceci:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Lorsque nous accéderons à l'URL

, Laravel obtiendra automatiquement le post /posts/my-first-post As slug à partir de la base de données et le transmettra à la fonction de fermeture (ou contrôleur) pour les opérations. my-first-post

Changer les champs pour les routes uniques

Cependant, parfois, vous voudrez peut-être changer uniquement les champs utilisés dans une seule route. Par exemple, vous souhaiterez peut-être utiliser le champ

dans une route pour la liaison du modèle de routage, mais utilisez le champ slug dans tous les autres itinéraires. id

Nous pouvons le faire en utilisant la syntaxe

dans notre définition de routage. Par exemple, supposons que nous voulons utiliser le champ :field dans une voie de liaison de modèle de routage. Nous pouvons définir notre itinéraire comme ceci: slug

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Cela signifie maintenant que dans cette voie particulière, Laravel essaiera d'obtenir un message de la base de données avec le champ fourni

. slug

en utilisant la collection de modèles personnalisés

Lorsque vous utilisez des méthodes telles que

pour obtenir plusieurs modèles à partir d'une base de données, Laravel les mettra généralement dans une instance de la classe AppModelsUser::all(). Cette classe fournit de nombreuses méthodes utiles pour le traitement des modèles renvoyés. Cependant, vous pouvez parfois renvoyer une classe de collecte personnalisée au lieu d'une classe de collecte par défaut. IlluminateDatabaseEloquentCollection

Vous voudrez peut-être créer une collection personnalisée pour plusieurs raisons. Par exemple, vous voudrez peut-être ajouter des méthodes d'assistance spécifiques aux modèles de traitement de ce type. Alternativement, vous voudrez peut-être l'utiliser pour une sécurité améliorée de type et vous assurer que la collection ne contient que des types spécifiques de modèles.

Laravel facilite le remplacement du type de collection qui doit être renvoyé.

Regardons un exemple. Supposons que nous ayons un modèle AppModelsPost, et lorsque nous les obtenons de la base de données, nous voulons les renvoyer à une instance de la classe personnalisée AppCollectionsPostCollection.

Nous pouvons créer un nouveau fichier app/Collections/PostCollection.php et définir notre classe de collecte personnalisée comme ceci:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans l'exemple ci-dessus, nous avons créé une nouvelle classe AppCollectionsPostCollection qui étend la classe IlluminateSupportCollection de Laravel. Nous avons également spécifié que cette collection ne contiendra que des instances de la classe AppModelsPost, en utilisant DocBlock. Ceci est utile pour aider votre IDe à comprendre les types de données qui seront incluses dans la collection.

Nous pouvons ensuite mettre à jour notre modèle AppModelsPost pour renvoyer une instance de la classe de collecte personnalisée en remplaçant la méthode newCollection comme suit:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans cet exemple, nous obtenons le tableau de modèle newCollection transmis à la méthode AppModelsPost et renvoyons une nouvelle instance de la classe Custom AppCollectionsPostCollection.

Maintenant, nous pouvons utiliser la classe de collection personnalisée pour obtenir nos messages de la base de données, comme indiqué ci-dessous:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Modèle comparatif

Un problème commun que j'ai lorsque je travaille sur un projet est de savoir comment comparer les modèles. Ceci est généralement dans les vérifications d'autorisation, lorsque vous souhaitez vérifier si l'utilisateur a accès à la ressource.

Regardons quelques pièges courants et pourquoi vous devriez probablement les éviter.

Vous devez éviter d'utiliser === lors de la vérification si les deux modèles sont les mêmes. En effet, === vérifie lors de la comparaison des objets, vérifie s'il s'agit d'instances du même objet. Cela signifie que même si les deux modèles ont les mêmes données, ils ne seront pas considérés comme les mêmes s'ils sont des instances différentes. Par conséquent, vous devez éviter de le faire car il reviendra très probablement false.

Supposons qu'une relation AppModelsComment existe sur le modèle et que le premier commentaire de la base de données appartient au premier post, regardons un exemple: post

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Vous devez également éviter d'utiliser

lors de la vérification si les deux modèles sont les mêmes. En effet, == Les vérifications lors de la comparaison des objets vérifieront si ce sont des instances de la même classe et s'ils ont les mêmes propriétés et valeurs. Cependant, cela peut conduire à un comportement inattendu. ==

Regardez cet exemple:

$user = User::query()->first();

$name = $user->full_name;
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Dans l'exemple ci-dessus, le

VÉROCE renvoie == car true et $comment->post sont la même classe et ont les mêmes propriétés et valeurs. Mais que se passe-t-il si nous modifions les propriétés du modèle $post pour les rendre différentes? $post

Utilisons la méthode

afin que nous n'obtenons que les champs select et posts du tableau id: content

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Même si $comment->post est le même modèle que $post, la vérification == renvoie false car le modèle a des propriétés chargées différentes. Comme vous pouvez l'imaginer, cela peut conduire à un comportement inintelligible difficile à tracer, surtout si vous avez ajouté rétroactivement la méthode select à la requête et que vos tests commencent à échouer.

Au lieu de cela, j'aime utiliser les méthodes is et isNot fournies par Laravel. Ces méthodes comparent les deux modèles et vérifient si elles appartiennent à la même classe, ont la même valeur de clé principale et ont la même connexion de base de données. Il s'agit d'un moyen plus sûr de comparer les modèles et contribuera à réduire la probabilité de comportement inattendu.

Vous pouvez utiliser la méthode is pour vérifier si les deux modèles sont les mêmes:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

De même, vous pouvez utiliser la méthode isNot pour vérifier si les deux modèles sont différents:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

utiliser whereBelongsTo

lors de la construction de requêtes

La dernière astuce ressemble plus à une préférence personnelle, mais j'ai trouvé que cela rend mes requêtes plus faciles à lire et à comprendre.

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Lorsque vous essayez d'obtenir un modèle à partir d'une base de données, vous pouvez vous retrouver à écrire une requête de filtrage basée sur les relations. Par exemple, vous voudrez peut-être obtenir tous les commentaires appartenant à un utilisateur spécifique et publier:

whereBelongsTo

Laravel fournit une méthode
$user = User::query()->first();

$name = $user->full_name;
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
que vous pouvez utiliser pour rendre votre requête plus facile à lire (à mon avis). En utilisant cette méthode, nous pouvons réécrire la requête ci-dessus comme celle-ci:

J'aime ce sucre syntaxique et je pense qu'il rend la requête plus facile à lire. C'est également un excellent moyen de vous assurer de filtrer en fonction des relations et des champs corrects. where

Vous ou votre équipe pouvez préférer utiliser une approche plus explicite de l'écriture

clauses. Par conséquent, cette technique peut ne pas convenir à tout le monde. Mais je pense que les deux sont bons tant que vous gardez votre approche cohérente.

Conclusion whereBelongsTo

J'espère que cet article vous montre quelques nouveaux conseils pour utiliser des modèles Laravel. Vous devriez maintenant être en mesure de découvrir et d'empêcher N 1 des problèmes, d'éviter l'accès aux propriétés manquantes, d'éviter silencieusement les propriétés et de modifier le type de clé primaire en UUID ou ULID. Vous devez également savoir comment modifier les champs utilisés pour les liaisons du modèle de routage, spécifier le type de collection renvoyée, comparer le modèle et utiliser lors de la construction de la requête.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal