Laravel 8

Créer un blog – contacts et liens sociaux

Nous avons dans le précédent article codé tout ce qui concerne les commentaires. On a dû ajouter un peu de Javascript à notre vue partagée dans le tableau pour l’approbation et la désapprobation des utilisateurs. Pour les contacts et les liens sociaux ça va être bien plus simple.

Vous pouvez télécharger le code final de cet article ici.

Les contacts

Les routes

Pour les routes c’est simple, on a une ressource et va utiliser seulement index, et destroy. D’autre part on a besoin d’une route supplémentaire pour les nouveaux contacts :

Route::prefix('admin')->group(function () {

    ...

    Route::middleware('admin')->group(function () {
        
        ...

        // Contacts
        Route::resource('contacts', BackResourceController::class)->only(['index', 'destroy']);
        Route::name('contacts.indexnew')->get('newcontacts', [BackResourceController::class, 'index']);
    });

Ces routes sont réservées à l’administrateur.

Le tableau

On crée la Datatable :

php artisan datatables:make Contacts

<?php

namespace App\DataTables;

use App\Models\{ Contact, User };
use Yajra\DataTables\Html\Column;
use Yajra\DataTables\Services\DataTable;
use Illuminate\Support\Facades\Route;

class ContactsDataTable extends DataTable
{
    use DataTableTrait;

    public function dataTable($query)
    {
        return datatables()
            ->eloquent($query)
            ->editColumn('created_at', function ($contact) {
                return formatDate($contact->created_at) . __(' at ') . formatHour($contact->created_at);
            })
            ->editColumn('name', function ($contact) {
                return $contact->name . ($contact->user_id ? $this->badge('User', 'primary', 2) : '');
            })
            ->editColumn('email', function ($contact) {
                return '<a href = "mailto: ' . $contact->email . '">' . $contact->email . '</a>';
            })
            ->editColumn('action', function ($contact) {
                return $this->button(
                          'contacts.destroy', 
                          $contact->id, 
                          'danger', 
                          __('Delete'), 
                          'trash-alt', 
                          __('Really delete this contact?')
                      );
            })
            ->rawColumns(['name', 'email', 'action']);
    }

    public function query(Contact $contact)
    {
        $query = $contact->newQuery();

        if(Route::currentRouteNamed('contacts.indexnew')) {
            $query->has('unreadNotifications');
        }
        return $query;
    }

    public function html()
    {
        return $this->builder()
                    ->setTableId('contacts-table')
                    ->columns($this->getColumns())
                    ->minifiedAjax()
                    ->dom('Blfrtip')
                    ->lengthMenu();
    }

    protected function getColumns()
    {
        return [
            Column::make('name')->title(__('Name')),
            Column::make('email')->title(__('Email')),
            Column::make('message')->title(__('Message')),
            Column::make('created_at')->title(__('Date')),
            Column::computed('action')->title(__('Action'))->addClass('align-middle text-center'),
        ];
    }

    protected function filename()
    {
        return 'Contacts_' . date('YmdHis');
    }
}

La configuration

Les titres

Dans app/config/titles on ajoute les titres pour les contacts :

'contacts' => [
    'index'  => 'Contacts',
    'indexnew' => 'New Contacts',
],

Le menu

Dans app/config/menu on ajoute les items pour les contacts :

'Contacts' => [
    'icon' => 'envelope',
    'role'   => 'admin',
    'children' => [
        [
            'name'  => 'All contacts',
            'role'  => 'admin',
            'route' => 'contacts.index',
        ],
        [
            'name'  => 'New contacts',
            'role'  => 'admin',
            'route' => 'contacts.indexnew',
        ],
    ],
],

On doit avoir du nouveau dans le menu :

L’aspect

On a tout en place pour afficher le tableau dans l’administration :

Le bouton de suppression fonctionne puisqu’on avait prévu du code générique. Les emails sont en lien pour pouvoir répondre d’un simple clic.

Ça doit aussi fonctionner pour les nouveaux contacts.

Les liens sociaux

Les routes

Pour les routes on a une ressource et va utiliser toutes les actions sauf show :

Route::prefix('admin')->group(function () {

    ...

    Route::middleware('admin')->group(function () {
        
        ...

        // Follows
        Route::resource('follows', BackResourceController::class)->except(['show']);
    });

Ces routes sont évidemment réservées à l’administrateur.

Le tableau

On crée la Datatable :

php artisan datatables:make Follows

<?php

namespace App\DataTables;

use App\Models\Follow;
use Yajra\DataTables\Html\Column;
use Yajra\DataTables\Services\DataTable;

class FollowsDataTable extends DataTable
{
    use DataTableTrait;

    public function dataTable($query)
    {
        return datatables()
            ->eloquent($query)
            ->editColumn('action', function ($follow) {
                return $this->button(
                          'follows.edit', 
                          $follow->id, 
                          'warning', 
                          __('Edit'), 
                          'edit'
                      ). $this->button(
                          'follows.destroy', 
                          $follow->id, 
                          'danger', 
                          __('Delete'), 
                          'trash-alt', 
                          __('Really delete this link?')
                      );
            })
            ->rawColumns(['action']);
    }

    public function query(Follow $model)
    {
        return $model->newQuery();
    }

    /**
     * Optional method if you want to use html builder.
     *
     * @return \Yajra\DataTables\Html\Builder
     */
    public function html()
    {
        return $this->builder()
                    ->setTableId('follows-table')
                    ->columns($this->getColumns())
                    ->minifiedAjax()
                    ->dom('Blfrtip')
                    ->lengthMenu();
    }

    protected function getColumns()
    {
        return [
            Column::make('title')->title(__('Title')),
            Column::make('href')->title('Link'),
            Column::computed('action')->title(__('Action'))->addClass('align-middle text-center'),
        ];
    }

    protected function filename()
    {
        return 'Follows_' . date('YmdHis');
    }
}

La configuration

Les titres

Dans app/config/titles on ajoute les titres pour les liens sociaux :

'follows' => [
    'index'  => 'Follows',
    'create' => 'Follow Creation',
    'edit'   => 'Follow Edit',
],

Le menu

Dans app/config/menu on ajoute les items pour les liens sociaux :

'Follows' => [
    'icon' => 'share-alt',
    'role'   => 'admin',
    'children' => [
        [
            'name'  => 'All follows',
            'role'  => 'admin',
            'route' => 'follows.index',
        ],
        [
            'name'  => 'Add',
            'role'  => 'admin',
            'route' => 'follows.create',
        ],
        [
            'name'  => 'fake',
            'role'  => 'admin',
            'route' => 'follows.edit',
        ],
    ],
],

On doit avoir du nouveau dans le menu :

L’aspect

On a tout en place pour afficher le tableau dans l’administration :

Là aussi la suppression doit fonctionner.

Ajouter ou modifier un lien social

La validation

On crée un form request pour la validation :

php artisan make:request Back\FollowRequest

On n’a que deux champs à traiter :

<?php

namespace App\Http\Requests\Back;

use Illuminate\Foundation\Http\FormRequest;

class FollowRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return $rules = [
            'title' => 'required|max:255',
            'href' => 'required|url|max:255',
        ];
    }
}

La vue

On crée une vue pour le formulaire :

On utilise encore nos composants :

@extends('back.layout')

@section('main')

    <form 
        method="post" 
        action="{{ Route::currentRouteName() === 'follows.edit' ? route('follows.update', $follow->id) : route('follows.store') }}">

        @if(Route::currentRouteName() === 'follows.edit')
            @method('PUT')
        @endif
        
        @csrf

        <div class="row">
          <div class="col-md-12">
                
                <x-back.validation-errors :errors="$errors" />

                @if(session('ok'))
                    <x-back.alert 
                        type='success'
                        title="{!! session('ok') !!}">
                    </x-back.alert>
                @endif

                <x-back.card
                    type='info'
                    :outline="true"
                    title=''>
                    <x-back.input
                        title='Title'
                        name='title'
                        :value="isset($follow) ? $follow->title : ''"
                        input='text'
                        :required="true">
                    </x-back.input>
                    <x-back.input
                        title='Lien'
                        name='href'
                        :value="isset($follow) ? $follow->href : ''"
                        input='text'
                        :required="true">
                    </x-back.input>
                </x-back.card>

                <button type="submit" class="btn btn-primary">@lang('Submit')</button>

              </div>
        </div>


    </form>

@endsection

On fait la différentiation entre la création et la modification pour rendre le formulaire utilisable pour les deux actions.

Pour la création le formulaire est vierge :

Au passage il faut ajouter une traduction dans resources/lang/fr.json :

"Follow Edit": "Modification d'un lien social",

Pour la modification le formulaire est renseigné avec les valeurs du lien sélectionné :

Vérifiez la validation :

Et que tout se passe bien :

Conclusion

On a encore bien avancé ! La prochaine fois on s’occupera de la partie CMS du blog avec les pages.

 

Print Friendly, PDF & Email

14 commentaires

  • webwatson

    Bonjour à tous !
    Moi j’ai cette erreur qui est survenu, je ne sais ce que j’ai touché car depuis je tourne en round essayé de trouver le problème.

    voici l’erreur :

    Call to undefined method App\Models\User::isAdmin() (View: C:\Users\watso\laravelForm\GesSouklous\resources\views\back\layout.blade.php)

  • Michel

    Bonjour,

    Suivre ce tuto est un grand plaisir riche de nombreux enseignements, encore merci Mr BESTMOMO.

    Une remarque: J’ai toujours mon problème d’image qui n’apparaissent que si je relance le storage link sur ma console !!! Je me demande si cela ne viendrait pas de mon Laragon. Une idée de votre côté ?

    Suggestions : N’est il pas dommage à la suppression d’un commentaire de supprimer tous les commentaires de l’utilisateur concerné ?
    Ne pourrait on pas estimer qu’un commentaire d’un utilisateur sur un article précis est à supprimer alors que les autres commentaires de cet utilisateur sur d’autres articles peuvent être conservés ?

    – Je trouve l’idée d’Oksam d’ajouter un fil d’actualité et un espace pour un caroussel de publicité ou d’images, trés interressante.

    Merci encore.

    • bestmomo

      Bonjour,

      Concernant la validation des commentaires comme on a prévu dans la base de faire ça au niveau de l’utilisateur on a forcément ce fonctionnement. Mais il me semble que dans un processus normal on a : premier commentaire d’un utilisateur qui ne s’affiche pas parce qu’on peut avoir un spam, on vérifie et c’est bon, on valide l’utilisateur. Ensuite logiquement les commentaires devraient relever de la marche normale du blog, si jamais ce n’est pas le cas le rédacteur ou l’administrateur peut aussi censurer directement tout ou partie d’un commentaire.

      Pour l’instabilité du storage link je n’avais encore jamais vu ça et je n’ai pas d’idée quant à la cause. Normalement une fois que c’est créé ça ne bouge plus…

Laisser un commentaire