Formation PUB030 : Laravel, 2019 Les requêtes avec Eloquent ORM

18.2 Retrouver les données à l'aide d'un identifiant : find() ou findOrFail()


La méthode find() est toute indiquée pour rechercher un enregistrement par son identifiant.

Cette méthode retourne une instance du modèle recherché (ex : un objet de type Produit) ou null si l'enregistrement n'a pas été trouvé.

Ex :

Contrôleur Laravel (PHP)

$produit = Produit::find(2);

 

// toujours vérifier si l'enregistrement a été trouvé

if (isset($produit)) {

    ...

}

Si on omet de vérifier si find() a instancié un objet et que l'objet est nul, le programme plantera lorsqu'on tentera d'accéder aux propriétés de l'objet et vous obtiendrez le message « Trying to get property of non-object ».

Trying to get property of non-object

findOrFail()

Il est également possible de travailler avec la méthode findOrFail(). Avec cette méthode, si aucun enregistrement ne correspond à l'identifiant demandé, une exception de type ModelNotFoundException sera levée.

Il est fortement suggéré de placer l'appel à findOrFail() dans un try...catch. De cette façon, il sera possible de réagir de façon appropriée lorsque l'enregistrement n'est pas trouvé (ex : poursuivre la recherche, afficher un message d'avertissement, etc.).

Pour que l'instruction catch fonctionne, il faut prendre soin de fournir l'espace de nom de la classe d'erreur dans le catch, incluant tout son chemin. En effet, puisque la classe ModelNotFoundException n'est pas définie dans le même espace de nom que le contrôleur, Laravel ne saurait pas où rechercher la définition de cette classe et le catch serait complètement ignoré.

Puisqu'une instruction pourrait échouer pour d'autres raisons qu'un enregistrement non trouvé, on fera suivre par un second catch qui attrapera toute autre exception. La classe Throwable est celle qui permet un tel comportement.

Contrôleur Laravel (PHP)

class ProduitsController extends Controller

{

     /**

     * Affiche les détails d'un produit.

     *

     * @param  int  $id

     * @return @return IlluminateViewView

     */

    public function show(int $id) : View

    {

        try {

            $produit = Produit::findOrFail(2);

            ...

        } 

        catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {

            ...

        }

        catch (\Throwable $e) {

            \Log::error('Erreur inattendue : ', [$e]);

        }

        ...

    }

    ...

}

Une autre alternative consiste à ajouter une instruction use.

Ex :

Contrôleur Laravel (PHP)

use Illuminate\Database\Eloquent\ModelNotFoundException;

use Throwable;

 

...

class ProduitsController extends Controller

{

     /**

     * Affiche les détails d'un produit.

     *

     * @param  int  $id

     * @return @return IlluminateViewView

     */

    public function show(int $id) : View

    {

        try {

            $produit = Produit::findOrFail(2);

            ...

        } 

        catch (ModelNotFoundException $e) {

            ...

        }

        catch (Throwable $e) {

            \Log::error('Erreur inattendue : ', [$e]);

        }

        ...

    }

    ...

}

Si on omet le try...catch et que l'enregistrement recherché n'est pas trouvé, ou encore si on omet de préciser l'espace de nom de la classe ModelNotFoundException (par un use ou en l'écrivant au long dans le catch), c'est Laravel qui récupérera l'exception. Par défaut, les configurations de Laravel font en sorte que le ModelNotFoundException génère une erreur 404.

En fait, un findOrFail() sans le try...catch est l'équivalent de :

Contrôleur Laravel (PHP)

$produit = Produit::find(2);

if (!$produit) {

    abord(404);

}

Rechercher plusieurs enregistrements d'un seul coup

La méthode find() permet de rechercher d'un seul coup plusieurs enregistrements, toujours à partir de leur identifiant. Pour y arriver, on fournira en paramètre un tableau d'identifiants et find() retournera une collection d'objets.

Le résultat sera une collection des instances trouvées.

Dans l'exemple suivant, $produits sera une collection contenant deux instances de Produit puisque le produit 36 n'existe pas.

Contrôleur Laravel (PHP)

$produits = Produit::find([1, 2, 36]);

L'utilisation de findOrFail() est moins intéressante ici puisqu'elle lèvera une exception dès qu'un des enregistrements demandés n'est pas trouvé.

Pour plus d'information

« Eloquent: Getting Started - Retrieving Single Models / Aggregates ». Laravel. https://laravel.com/docs/master/eloquent#retrieving-single-models

▼Publicité

Veuillez noter que le contenu de cette fiche vous est partagé à titre gracieux, au meilleur de mes connaissances et sans aucune garantie.
Merci de partager !
Soumettre