Besoin d'aide ?

Construction d'une URL avec multiple paramètres

Avatar de AlexGraphicDesign
AlexGraphicDesign

Bonjour à tous,

Je me permets de revenir pour de nouveau solliciter votre aide avec mon projet sur Laravel 8. Je m'explique :

Je souhaite afficher un programme immobilier avec une URL de la forme : monsite.test/programme-immobilier/region/departement/ville/programmex

Pour cela (de mon avis de novice sur Laravel), il faudrait, je pense, que j'ai quelque chose dans ce genre là à peu de choses près dans le composant blade ou se trouve mon lien pour accéder au programme.

<a href="{{ route('programs.display', [$program->departement->urlRegion, $program->departement->urlDepartement, $program->ville->urlVille, $program->urlProgramme]) }}" class="btn btn-primary">En savoir plus</a>

et voici la route :

Route::name('programs.display')->get('{region}/{departement}/{ville}/{programme}', [FrontProgramController::class, 'show']);

PROBLEME ! (il en fallait bien un ! ;) )

Pour l'instant je n'arrive à faire remonter que la ville dans l'URL =( puisqu'il n'existe en fait un lien à partir de la table 'programme' que vers la table 'ville' ! et ce n'est qu'à partir de la ville que l'on peut retrouver le departement ainsi que la région qui sont dans la même table.

J'ai expérimenté certaines pistes comme créer une jointure dans le Model (marche pas), appeler une méthode directement dans la vue (pas propre...), etc .. car j'aimerais en fait (si cela est possible), récupérer les données qui me manque à l'intérieur de '$program' dans mon foreach qui est ensuite passé en paramètre de mon composant.

Page index

@foreach($programs as $program)
    <div class="col-lg-4 col-sm-6 col-12">
        <x-front.program :program="$program" />
    </div>
@endforeach

Composant program

@props(['program'])

<article class="card">
    <svg class="bd-placeholder-img card-img-top" width="100%" height="180" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Image cap" preserveAspectRatio="xMidYMid slice" focusable="false">
        <title>Placeholder</title>
        <rect width="100%" height="100%" fill="#868e96"></rect>
        <text x="50%" y="50%" fill="#dee2e6" dy=".3em">Image cap</text>
    </svg>
    <div class="card-body">
        <h5 class="card-title">{{ $program->nomProgramme }}</h5>
        <p class="card-text">{{ $program->textePortail }}</p>
        <p class="card-text">{{ $program->urlProgramme }}</p>
        <p class="card-text">{{ $program->ville->nomVille }}</p>
        <a href="{{ route('programs.display', $program->urlProgramme) }}" class="btn btn-primary">En savoir plus</a>
    </div>
</article>

Enfin voilà, tout en espérant que j'ai été assez clair, est ce que quelqu'un aurait une idée, voir même un début de solution à me proposer ? parce que là j'avoue que je sèche vraiment =(

Posté il y a 3 mois
Avatar de Nicolus
Nicolus

Alors déjà c'est le moment où commencerais par jouer la carte de la mauvaise foi en demandant au PO / chef de projet "t'es sûr qu'on a vraiment besoin de faire apparaitre le département et la région dans l'URL ? Nan parce que tu vois en base c'est pas foutu comme ça, ça va rajouter du temps de dev alors que ça marcherait tout aussi bien avec l'id du programme, en plus personne regarde les URLs, dans Safari elles sont mêmes plus affichées".

Après en admettant qu'on ait envie de les faire apparaitre, on peut se simplifier la vie en partant du principe que les segments dans la route {region}/{departement}/{ville}/{programme}, seul programme est utilisé, le reste c'est de la déco. Donc on garde la route :

Route::name('programs.display')->get('{region}/{departement}/{ville}/{programme}', [FrontProgramController::class, 'show']);

Et un controller qui accepte les paramètres, dont $programme qu'on type-hint correctement pour bénéficier du "route-model binding" et récupérer directement un programme (et pas son id) :

public function show(string $region, string $departement, string $ville, Programme $program)
{
    dd($program);
}

Pour la construction de l'URL, il ne nous reste plus qu'à insérer les chaines qu'on veut au niveau de region, departement et ville (même si on pourrait très bien mettre "toto", "titi" et "tata", ça fonctionnerait tout pareil). Tu dis que les infos sont contenues dans la table ville, donc en admettant que la table ville ait des colonnes 'nom', 'nom_departement' et 'nom_region' ça donnerait quelque chose de ce genre :

route('programs.display', ['region' => $program->ville->nom_region, 'departement' => $program->ville->nom_departement, 'ville' => $program->ville->nom, 'programme' => $program->id]);

Et voilà, on devrait avoir des URL qui font apparaitre le nom des département, ville et région. Si on veut éviter que l'utilisateur ne puisse rentrer n'importe quoi dans les urls, on pourra dans le controller vérifier la que les variables $region, $departemnet et $ville correspondent bien à ce qu'on a en base et renvoyer une 404 si ce n'est pas le cas.

Posté il y a 3 mois
Avatar de AlexGraphicDesign
AlexGraphicDesign

hello Nicolus,

Merci de ta réponse ça m'aide beaucoup ! Ceci dit je vais peut être te décevoir : le décideur sur ce projet ..... c'est moi ! haha :p Je suis donc seul responsable du fait de vouloir ces URL's "précises" :D

Je vais travailler en effet sur cette solution, encore une fois merci beaucoup ! (vue l'ampleur du projet, je pense qu'on me verra rôder encore un peu dans le coin ;) )

Posté il y a 3 mois

Vous ne pouvez pas répondre à ce sujet.