Très bien, parlons des étendues de requête. Ils sont géniaux, ils rendent les requêtes beaucoup plus faciles à lire, cela ne fait aucun doute. Mais il y a une chose que je déteste chez eux : la magie. Et lorsque vous travaillez avec une équipe où tout le monde n’est pas développeur back-end, cela peut leur rendre la vie misérable. Bien sûr, vous pouvez ajouter des PHPDocs, mais il y a toujours un peu de magie à l'œuvre. Si vous n'avez jamais utilisé de lunettes auparavant, ne vous inquiétez pas, accrochez-vous bien.
Considérez ce code :
use App\Models\User; $users = User::query() ->where('votes', '>', 100); ->where('active', 1); ->orderBy('created_at') ->get();
C'est ainsi que vous écrivez généralement des requêtes. Mais lorsque les requêtes deviennent trop complexes ou difficiles à lire, vous pouvez les résumer dans des étendues :
<?php namespace App\Models; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class User extends Model { public function scopePopular(Builder $query): void { $query->where('votes', '>', 100); } public function scopeActive(Builder $query): void { $query->where('active', 1); } }
Maintenant, vous pouvez faire ceci :
$users = User::query() ->popular() ->active() ->orderBy('created_at') ->get();
Ça se lit beaucoup mieux, non ? Je sais. Mais le problème est que vous n’obtenez aucune saisie semi-automatique. C'est de la magie noire pour l'IDE. Étant donné que les étendues sont résolues au moment de l'exécution et préfixées par scope, votre IDE ne peut en aucun cas les connaître à moins que vous ne l'aidiez.
Une solution consiste à utiliser PHPDocs, comme ceci :
/** * @method static Builder popular() * @method static Builder active() */ class User extends Model
Un autre inconvénient des oscilloscopes ? Les modèles les plus fréquemment utilisés finissent par en être remplis de tonnes, pour rien. J'aime parcourir mes modèles et voir immédiatement les relations et la logique de base, pas un tas d'abstractions de requêtes.
Alors ? Devons-nous simplement abandonner les lunettes et passer à autre chose ? Eh bien, c'est une option, ou vous pouvez utiliser des générateurs de requêtes personnalisés.
Comme son nom l'indique, un générateur de requêtes personnalisé vous permet de déplacer toutes vos abstractions de requêtes dans une classe dédiée. Le code sera plus organisé d'une certaine manière.
Créons une nouvelle classe UserQueryBuilder :
<?php namespace App\Eloquent\QueryBuilders; use App\Models\User; use Illuminate\Database\Eloquent\Builder; class UserQueryBuilder extends Builder { public function popular(): self { return $this->where('votes', '>', 100); } public function active(): self { return $this->where('active', 1); } }
Où placer les constructeurs ? Il n'y a pas de ligne directrice, mais personnellement, j'aime les placer dans app/Eloquent/QueryBuilders.
Utilisons maintenant ce générateur dans le modèle utilisateur :
<?php namespace App\Models; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class User extends Model { public function newEloquentBuilder($query): UserQueryBuilder { return new UserQueryBuilder($query); } // for type hints public static function query(): UserQueryBuilder { return parent::query(); } }
Et juste comme ça, vous pouvez désormais faire :
$users = User::query() ->popular() ->active() ->orderBy('created_at') ->get();
Fonctionne exactement de la même manière et vous bénéficiez d'une saisie semi-automatique complète. De plus, la navigation par code fonctionne parfaitement, elle vous emmène là où vous devez être ?
Une autre chose intéressante est que vous pouvez résoudre dynamiquement les générateurs de requêtes si nécessaire.
public function newEloquentBuilder($query): UserQueryBuilder { if ($this->status === State::Pending) { return new PendingUserQueryBuilder($query); // extends UserQueryBuilder } return new UserQueryBuilder($query); }
De cette façon, vous évitez d'avoir un seul gros générateur de requêtes lorsque vous pouvez regrouper les requêtes par contexte (comme un état).
Les scopes sont cool, et si je n'en ai que 2-3, je m'en tiendrai à eux. Mais lorsque les choses commencent à devenir incontrôlables, les générateurs de requêtes personnalisées sont la solution. Ils valent l'effort supplémentaire, en gardant votre code propre, organisé et plus facile à maintenir ?
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!