Maison >cadre php >Laravel >Un article expliquant les raisons et les solutions à l'échec de la liaison du modèle Laravel

Un article expliquant les raisons et les solutions à l'échec de la liaison du modèle Laravel

PHPz
PHPzoriginal
2023-04-08 23:30:021023parcourir

La liaison de modèle Laravel est une fonctionnalité importante du framework Laravel. Elle fournit une fonction permettant d'injecter automatiquement des paramètres d'URL dans le modèle spécifié dans la méthode du contrôleur, évitant ainsi le processus fastidieux d'interrogation manuelle de la base de données par les développeurs. Cependant, dans la pratique, les développeurs rencontrent parfois des échecs de liaison de modèle, provoquant des exceptions au programme. Cet article commencera par des cas réels pour expliquer les problèmes possibles et les solutions à la liaison du modèle Laravel.

Exemple :

Supposons que nous ayons une page de liste de produits. L'URL accepte un paramètre de catégorie pour représenter la catégorie de produit. Le contrôleur utilise la liaison de modèle pour interroger les produits dans la catégorie spécifiée et renvoie la vue. Nous l'implémentons via le code suivant :

public function index(Category $category)
{
    $products = $category->products;
    return view('products.index', ['products' => $products]);
}

Comme vous pouvez le voir, nous lions le modèle Category via le paramètre $category du index() code> méthode, puis récupérez tous les produits de cette catégorie. Cependant, lorsque nous entrons dans une catégorie inexistante dans la barre d'adresse du navigateur, le programme lèvera une exception, comme indiqué ci-dessous : <code>index() 方法的参数 $category 来绑定 Category 模型,然后获取该分类下的所有产品。然而,当我们在浏览器地址栏中输入一个不存在的分类时,程序就会抛出异常,如下所示:

Illuminate\Database\Eloquent\ModelNotFoundException

No query results for model [App\Category].

我们发现,程序抛出的异常信息是 ModelNotFoundException,也就是说 Laravel 框架无法找到对应的模型。那么,出现这种问题的原因是什么呢?

问题原因:

模型绑定能够正常工作的前提是,URL 参数必须与数据库中对应的模型匹配。如果 URL 参数无法匹配,则会出现模型绑定失败的情况。在上面的示例中,我们在地址栏中输入了一个不存在的分类 ID,这就导致了程序无法找到对应的模型。

另外,如果我们在控制器方法中手动注入了模型,例如:

public function show(Product $product)
{
    return view('products.show', ['product' => $product]);
}

则还需要注意以下问题:

  1. 参数名必须与路由中的占位符名称相同。
  2. 参数类型必须是一个 Eloquent 模型类。
  3. 如果无法找到对应的模型,则会抛出 ModelNotFoundException 异常。

解决方案:

那么,我们该如何解决模型绑定失败的问题呢?下面是两种解决方案。

  1. 定义全局范围的解析器

我们可以在 boot() 方法中定义全局范围的解析器,以捕获所有的 ModelNotFoundException 异常,然后将其转换为自定义的异常。以下是实现方式:

(1)定义自定义异常:

namespace App\Exceptions;

use Exception;

class NotFoundException extends Exception
{
    public function render($request)
    {
        return response()->view('errors.404');
    }
}

该异常类在抛出异常时,将返回 resources/views/errors/404.blade.php 视图。

(2)在 AppServiceProvider.php 中注册解析器:

use App\Exceptions\NotFoundException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $this->app->bind(ModelNotFoundException::class, function ($e) {
            throw new NotFoundException;
        });
    }
}

boot() 方法中,我们绑定了 ModelNotFoundException 异常到自定义异常 NotFoundException,以便程序能够正确渲染 404 页面。

  1. 手动抛出异常

在控制器方法中,我们可以手动抛出自定义异常,例如:

public function show($id)
{
    $product = Product::findOrFail($id);

    if ($product->category->id !== $this->category->id) {
        throw new NotFoundException;
    }

    return view('products.show', ['product' => $product]);
}

在该方法中,我们手动查询产品模型,然后根据分类 ID 判断产品是否属于当前分类,如果不属于,则手动抛出自定义异常 NotFoundExceptionrrreee

Nous avons constaté que les informations d'exception renvoyées par le programme sont ModelNotFoundException , ce qui signifie que le framework Laravel ne trouve pas le modèle correspondant. Alors, quelle est la raison de ce problème ?

Cause du problème :

Pour que la liaison de modèle fonctionne correctement, les paramètres d'URL doivent correspondre au modèle correspondant dans la base de données. Si les paramètres d'URL ne peuvent pas correspondre, la liaison du modèle échouera. Dans l'exemple ci-dessus, nous avons entré un identifiant de catégorie inexistant dans la barre d'adresse, ce qui a empêché le programme de trouver le modèle correspondant. 🎜🎜De plus, si nous injectons manuellement le modèle dans la méthode du contrôleur, par exemple : 🎜rrreee🎜, nous devons également faire attention aux problèmes suivants : 🎜
  1. Le nom du paramètre doit être le même que celui du nom d'espace réservé dans l'itinéraire.
  2. Le type de paramètre doit être une classe de modèle Eloquent.
  3. Si le modèle correspondant est introuvable, une exception ModelNotFoundException sera levée.
🎜Solution :🎜🎜Alors, comment pouvons-nous résoudre le problème de l'échec de la liaison du modèle ? Voici deux solutions. 🎜
  1. Définir un analyseur de portée globale
🎜Nous pouvons définir un analyseur de portée globale dans la méthode boot() pour capturer tous les ModelNotFoundException code> exception, puis convertissez-la en une exception personnalisée. Voici la méthode d'implémentation : 🎜🎜(1) Définir une exception personnalisée : 🎜rrreee🎜Lorsqu'une exception est levée par cette classe d'exception, elle renverra le <code>resources/views/errors/404.blade.php code> vue. 🎜🎜(2) Enregistrez l'analyseur dans <code>AppServiceProvider.php : 🎜rrreee🎜Dans la méthode boot(), nous lions l'exception ModelNotFoundException à une exception personnalisée NotFoundException afin que le programme puisse restituer correctement la page 404. 🎜
  1. Lancer manuellement des exceptions
🎜Dans la méthode du contrôleur, nous pouvons lancer manuellement une exception personnalisée, par exemple : 🎜rrreee🎜Dans cette méthode, nous interrogeons manuellement le modèle de produit, puis déterminons si le produit appartient à la catégorie actuelle en fonction de l'ID de catégorie. Si ce n'est pas le cas, nous lançons manuellement une exception personnalisée NotFoundException. 🎜🎜Conclusion :🎜🎜La liaison de modèle Laravel est une fonctionnalité importante du framework Laravel, qui peut grandement simplifier les requêtes de base de données et le code du contrôleur. Cependant, en pratique, il faut également faire attention à certains détails, comme éviter d'injecter manuellement des modèles inexistants, définir des analyseurs globaux pour gérer les exceptions, etc. J'espère qu'à travers cet article, tout le monde pourra mieux comprendre la liaison du modèle Laravel et éviter des problèmes inutiles. 🎜

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:
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