Comment améliorer ce controlleur Laravel ?

a marqué ce sujet comme résolu.

Bonsoir ! :)

Je suis en train d’apprendre Laravel en ce moment, un framework qui me plaît beaucoup.

J’ai terminé un petit projet, Tweety (Github), qui est en fait le projet développé dans les tutos Laracasts. Pour ce projet, j’ai décidé de faire les améliorations proposées, histoire de bien m’entraîner.

J’ai pu faire tout ce que je voulais. En revanche, je ne suis pas pleinement satisfait de deux de mes controlleurs. Je trouve le code beaucoup trop long, et le controlleur fait trop de chose à la fois selon moi.

J’aimerais donc avoir votre aide pour savoir ce que je peux améliorer, et comment je peux l’améliorer.

Voici les deux codes en question :

TweetController

public function store()
{
    $validatedRequest = request()->validate([
        'image' => ['file', 'image'],
        'body' => ['required', 'max:200'],
    ]);

    if (empty(request('image'))) {
        unset($validatedRequest['image']);
    } else {
        $validatedRequest['image'] = request('image')->store('tweets');
    }

    $tweet = auth()->user()->tweets()->create($validatedRequest);

    // Mentions (un message qui contient un @chris pour mentionner l'utilisateur chris)
    $mentions = [];
    preg_match_all('/\@[\w._]+/', $tweet->body, $mentions);

    foreach ($mentions as $mention) {
        if (!count($mention)) {
            continue;
        }

        $mention = $mention[0]; // Parce que $mention est un array (je sais pas trop pourquoi)
        $username = substr($mention, 1); // On enlève le @ au début

        $userMention = User::where('username', $username)->first();

        if ($userMention) {
            $userMention->notify(new MentionNotification(auth()->user(), $tweet));
        }
    }

    return back()->with('success', 'Tweet published!');
}

ProfileController

public function update(User $user)
{
    // Validate Request
    $validatedRequest = request()->validate([
        'banner' => ['file', 'image'],
        'avatar' => ['file', 'image'],
        'username' => ['required', 'string', 'max:50', Rule::unique('users')->ignore($user), 'alpha_dash'],
        'name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users')->ignore($user)],
        'password' => ['nullable', 'string', 'min:8', 'confirmed'],
    ]);

    // Banner
    if (empty(request('banner'))) {
        unset($validatedRequest['banner']);
    } else {
        $validatedRequest['banner'] = request('banner')->store('banners');
    }

    // Avatar
    if (empty(request('avatar'))) {
        unset($validatedRequest['avatar']);
    } else {
        $validatedRequest['avatar'] = request('avatar')->store('avatars');
    }

    // Password
    if (empty(request('password'))) {
        unset($validatedRequest['password']);
    } else {
        $validatedRequest['password'] = Hash::make($validatedRequest['password']);
    }

    // Update User
    $user->update($validatedRequest);

    // Redirect Back
    return redirect()->route('profiles.edit', $user);
}

Déjà, parlons du premier code. Le fait de traiter les mentions dans la même méthode que l’ajout d’un Tweet, je trouve pas ça super. Sauf que je ne sais pas trop où mettre ce code ni comment l’organiser.

Ensuite, mon code des mentions et vraiment pas propre. En réalité, ça fait un petit moment que j’ai pas codé en PHP, et je le ressent (voici donc une chose que je dois travailler).

Le deuxième code, lui, est beaucoup mieux. Mais je ne sais pas si c’est une bonne façon de faire des unset pour ne pas remplir ces champs (si ils sont vide par exemple) dans le User. Peut être existe-t-il une autre méthode plus propre ?

Si vous avez des conseils, je suis preneur ! :)

Merci !

+0 -0

Hello,

Le code est pas si long que ça, mais effectivement les mentions pourraient être gérées dans une méthode/fonction séparée si tu veux rendre ton code plus flexible. Tu peux donc créer un helper ou un service pour ce besoin.

Tu peux aussi utiliser les événements pour automatiser ce genre d’appels : à la création d’un tweet tu pourras ainsi détecter les mentions automatiquement par exemple.


Pour la validation j’ai tendance à utiliser des FormRequest pour déléguer le travail et alléger les controllers. Tu peux ainsi construire tes mises à jours et créations d’objets comme tu le souhaites dans le controller.

Merci pour ton retour. :)

J’ai regardé les helpers et les services. Pour les helpers, c’est juste une simple fonction si j’ai bien compris.

Pour les services, je me souviens l’avoir vu. Donc si je comprend bien, j’aurais une classe MentionService que je passerais en paramètre de ma méthode store, et j’aurais juste à faire quelque chose comme $mentionService->perform($tweet->body) ? (dans l’idée où le code traitant les mentions de mon controlleur sera dans une méthode perform de cette nouvelle classe).

Mais, je pense que le mieux, c’est les événements, effectivement. Je l’ai avais aussi vu, mais je n’y ai pas pensé. L’avantage avec ça, c’est que je pourrais y greffer d’autres traitements lors d’un nouveau tweet.

Je vais donc m’orienter vers ces derniers.

Aussi, merci pour l’astuce des FormRequest. Le truc marrant, c’est que j’avais déjà fait du Laravel avant (pas longtemps) et que je les avais utilisés aussi. :lol: Comme quoi, c’est important de pratiquer régulièrement pour rien oublier. Je vais donc modifier tout ça.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte