Laravel | LP MIM

Découverte du Framework Laravel

David Annebicque | @DavidAnnebicque

Un peu d'histoire

Laravel a été créé par Taylor Otwell en juin 2011.

Il alterne avec Symfony la première place du framework le mieux (et le plus) noté sur GitHub.

Même si avec le temps Laravel suit sa route, il dépend, encore aujourd'hui de nombreuses ressources issues de Symfony.

Un peu d'histoire

Laravel est composé d'une très grande communauté, et, est le framework le plus utilisé en amérique du nord.

D'ailleurs de nombreux comparatifs existent : Un comparatif (Laravel vs Symfony 3)

Laravel ?

Framework open-source, MVC, PHP et POO comme Symfony, CakePHP, ...

Laravel fournit des fonctionnalités en termes de routage de requête, de mapping objet-relationnel (un système baptisé Eloquent implémentant Active Record), d'authentification, de vue (avec Blade), de migration de base de données, de gestion des exceptions et de test unitaire.

Site officiel

Une documentation en français

Installation

Configuration requise :

  • PHP >= 7.1.3
  • OpenSSL PHP Extension
  • PDO PHP Extension
  • Mbstring PHP Extension
  • Tokenizer PHP Extension
  • XML PHP Extension
  • Ctype PHP Extension
  • JSON PHP Extension

Installation

Laravel propose plusieurs méthodes pour l'installation :

  • Laravel Installer
  • Composer
  • Machine virtuelle (Homestead)

Installation

Avec Composer :


                composer create-project --prefer-dist laravel/laravel blog
                

Configuration

Quelques étapes de configuration sont nécessaires

  • Faire pointer votre domaine/serveur sur le répertoire Public pour accéder au contrôleur frontal index.php
  • Modifier les informations de configuration dans le dossier config. Modifier aussi le fichier ".env" à la racine de votre projet.
  • Donner les droits en écriture sur le répertoire storage/ et sur le répertoire bootstrap/cache/

Structure globale

  • app/ : c'est le coeur de votre application. Toutes les classes seront dans ce répertoire.
  • bootstrap/ : contient le bootstrap du framework, ainsi que les fichiers de cache.
  • config/ : contient tous les fichiers de configuration de votre application
  • database/ : contient les fichiers de migration de votre base de données
  • public/ : c'est le point d'entrée de votre projet. Il contient le contrôleur frontal "index.php", ainsi que tous les fichiers css/js/images/...

Structure globale

  • resources/ : contient les vues, les traductions et les fichiers less/sass ou javascripts non compilés.
  • routes : contient les routes de votre application. 4 fichiers sont présents par défaut : web.php, api.php, console.php, channels.php
  • storage/ : contient les vues compilées, les fichiers de logs, de cache de votre application
  • tests/ : contient vos fichiers de tests
  • vendor : contient les librairies tierces

Stucture du dossier App/

C'est le répertoire essentiel de votre application

  • Console/ : toutes les commandes personnalisées pour la console Artisan
  • Exceptions/ : le code pour gérer les exceptions de votre application
  • Http/ : pour les controllers, middleware et les formulaires
  • Providers : pour la gestion des fournisseurs de service (serice provider)

Les routes

Les routes sont le point d'entrée de votre application. Vous devez définir vos routes dans les fichiers du répertoire "routes". Généralement vous définissez vos routes dans le fichier web.php pour une application web classique.

Laravel propose de nombreuses façons de manipuler vos routes, vous trouverez tous les détails Dans la documentation officielle.

Ci-après vous trouverez les syntaxes les plus courantes.

Les routes

La version la plus simple d'une route est :


                    Route::get('/', function () {
                        return 'Hello World';
                    });
                

Cette route associe le pattern "/" (la racine du site) à un message texte "Hello World". Il n'y a pas d'appel à un contrôleur.

Les routes

Dans la même logique de simplicité, on peut directement associer une route à une vue


                    Route::get('/welcome', function () {
                            return view('welcome');
                    });
                

Cette route associe le pattern "/welcome" à une vue appellée "welcome". Laravel doit donc trouver un fichier nommé "welcome.blade.php" dans le répertoire "Resources/views".

Les routes

D'une manière plus classique, vous allez définir des routes dans le fichier routes/web.php associant des URL (pattern) à des méthodes de vos contrôleurs


                    Route::get('/user', 'UserController@index');
                

Cette route associe le pattern "/user" à la méthode "index" de votre contrôleur "UserController".

A noter que les routes définies jusque là, utilise la méthode "route::get", c'est à dire que les routes ne sont accessibles qu'en GET.

Les routes / Méthodes

Les méthodes possibles sont :


                    Route::get($uri, $callback);
                    Route::post($uri, $callback);
                    Route::put($uri, $callback);
                    Route::patch($uri, $callback);
                    Route::delete($uri, $callback);
                    Route::options($uri, $callback);
                

Les routes / Méthodes

Il est possible d'associer plusieurs méthodes d'accès pour une route en utilisant l'instruction "match" (qui permet de filtrer) ou "any" qui autorise tout.


                    Route::match(['get', 'post'], '/', function () {
                        //
                    });

                    Route::any('foo', function () {
                        //
                    });
                

Les routes / Paramètres

Les routes peuvent bien-sûr accepter des paramètres :


                    Route::get('user/{id}', function ($id) {
                        return 'User '.$id;
                    });

                    Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
                        //
                    });
                

A noter que dans les exemples ci-dessus, le traitement se fait directement dans la route et n'implique pas de passer par un contrôleur pour des traitements simples.

Les routes / Paramètres

Les paramètres peuvent être optionnels :


                   Route::get('user/{name?}', function ($name = null) {
                        return $name;
                    });

                    Route::get('user/{name?}', function ($name = 'John') {
                        return $name;
                    });
                

Les routes / Paramètres

Il est possible de définir des contraintes sur les paramètres en utilisant les expressions régulières :


                   Route::get('user/{name}', function ($name) {
                        //
                    })->where('name', '[A-Za-z]+');

                    Route::get('user/{id}', function ($id) {
                        //
                    })->where('id', '[0-9]+');

                    Route::get('user/{id}/{name}', function ($id, $name) {
                        //
                    })->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
                

Les routes / Paramètres

Enfin pour plus d'aisance il est possible de nommer les routes :


                   Route::get('user/profile', function () {
                        //
                    })->name('profile');
                    Route::get('user/profile', 'UserController@showProfile')->name('profile');
                

Les routes / Accéder à des routes nommées

Pour accéder aux routes nommées il faut utiliser la méthode "route()"


                    // Generating URLs...
                    $url = route('profile');

                    // Generating Redirects...
                    return redirect()->route('profile');
                

Les routes / Accéder à des routes nommées

Pour accéder aux routes nommées avec des paramètres il faut utiliser la méthode "route()" et passer un tableau avec les paramètres.


                    Route::get('user/{id}/profile', function ($id) {
                        //
                    })->name('profile');

                    $url = route('profile', ['id' => 1]);
                

Les routes / Préfixe, sous-domaine

Laravel permet de gérer des sous-domaines, des préfixes (par exemple administration/). Il est également possible de préfixer le nom des routes, ... Vous trouverez les détails dans la documentation officielle de Laravel.


                    //exemple de routes préfixées
                    Route::prefix('admin')->group(function () {
                        Route::get('users', function () {
                            // Matches The "/admin/users" URL
                        });
                    });
                

Les controllers

Votre premier contrôleur


                    <?php

                    namespace App\Http\Controllers;

                    use App\User;
                    use App\Http\Controllers\Controller;

                    class UserController extends Controller
                    {
                        /**
                         * Show the profile for the given user.
                         *
                         * @param  int  $id
                         * @return Response
                         */
                        public function show($id)
                        {
                            return view('user.profile', ['user' => User::findOrFail($id)]);
                        }
                    }
                

Les controllers

Cette méthode de votre contrôleur est accessible via la route ci-dessous


                    Route::get('user/{id}', 'UserController@show');
                

Création d'un contrôleur avec Artisan


                    php artisan make:controller PhotoController --resource
                

Cette commande va générer un contrôleur (PhotoController) ainsi que toutes les méthodes (grâce à --resource) pour le gérer (Create, store, show, edit, update, destroy).

Création d'un contrôleur avec Artisan

Vous pouvez ensuite enregistrer de manière globale toutes les routes pour ce contrôleur


                    Route::resource('photos', 'PhotoController');

                    //ou si vous avez plusieurs resources
                    Route::resources([
                        'photos' => 'PhotoController',
                        'posts' => 'PostController'
                    ]);
                

Création d'un contrôleur avec Artisan

Verb URI Action Route Name
GET /photos index photos.index
GET /photos/create create photos.create
POST /photos store photos.store
GET /photos/{photo} show photos.show
GET /photos/{photo}/edit edit photos.edit
PUT/PATCH /photos/{photo} update photos.update
DELETE /photos/{photo} destroy photos.destroy

Requests

Laravel propose d'accéder aux Requests (les données envoyées par le client) très simplement.

Pour cela il suffit de passer l'objet de type Request comme paramètre de vos méthodes.


                    use Illuminate\Http\Request;

                    //...
                    public function store(Request $request)
                    {
                        $name = $request->input('name');
                        //
                    }
                

Requests

Grâce à l'objet Request vous pouvez accéder aux données d'un formulaire, des cookies, ...

Toutes les informations dans la documentation officielle

Responses

Les réponses sont ce que Laravel renvoie à l'utilisateur. Cela peut être du texte, une vue, un fichier, un cookie, des sessions, des données json...

Les réponses peuvent être émisent depuis les routes directement, ou depuis une méthode d'un contrôleur. La syntaxe est identique.

Ci-après quelques exemples de réponses.

Responses / Texte avec Header


                    return response('Hello World', 200)
                            ->header('Content-Type', 'text/plain');
                

Cet exemple retourne, en utilisant l'objet "response", du texte, et un header pour informer le navigateur du type de réponse.

Responses / Redirection


                    return redirect('home/dashboard');
                

Cet exemple effectue une redirection vers l'URL "home/dashboard".

Responses / Redirection vers une route nommée


                    return redirect()->route('login');

                    //ou
                    return redirect()->route('profile', ['id' => 1]);
                

Responses / Redirection vers un contrôleur


                    return redirect()->action('HomeController@index');
                

Responses / Redirection avec un message flash


                    return redirect('dashboard')->with('status', 'Profile updated!');
                

Que l'on affichera avec le code suivant dans la vue


                @if (session('status'))
                
{{ session('status') }}
@endif

Responses / Une vue


                    return response()
                        ->view('hello', $data, 200)
                        ->header('Content-Type', $type);
                

Affichera la vue "hello". La partie header est optionnelle.

Responses / Une vue

Ou, plus directement :


                    return view('article.index', ['name' => 'James']);
                

Affichera la vue "index" qui se trouve dans le répertoire article du répertoire views.

Responses / JSON


                    return response()->json([
                        'name' => 'Abigail',
                        'state' => 'CA'
                    ]);
                

Les views

Toutes vos vues doivent se trouver dans le répertoire "Resources/views". Vous pouvez, bien-sûr créer des sous-répertoires.

Laravel propose des mécanismes interessants pour la création de vos vues :

Blade (template)

Blade est le moteur de template de Laravel.

Les fichiers de template se trouvent dans le répertoire "Resources/views" et portent l'extension ".blade.php".

Vous pouvez avoir tous les détails de ses fonctionnalités la documentation officielle

La partie ci-après présente les fonctionnalités les plus importantes.

Blade / Héritage de template

Il est classique de définir un layout, et ensuite d'en faire hériter les autres vues. Cela permet de définir la structure de votre site. Blade dispose de ce mécanisme.

Blade / Héritage de template


                    
                    <html>
                        <head>
                            <title>App Name - @yield('title')</title>
                        </head>
                        <body>
                            @section('sidebar')
                                This is the master sidebar.
                            @show

                            <div class="container">
                                @yield('content')
                            </div>
                        </body>
                    </html>
                

Blade / Héritage de template

Quelques explications :

  • @section directive : est une section de contenu, qui peut contenir du contenu par défaut
  • @yield directive : affiche le contenu d'une section.

Blade / Héritage de template

Il faut maintenant définir des vues enfants


                    

                    @extends('layouts.app')

                    @section('title', 'Page Title')

                    @section('sidebar')
                    @parent

                    

This is appended to the master sidebar.

@endsection @section('content')

This is my body content.

@endsection

Blade / Slots-Components

Il existe un mécanisme un peu similaire à l'héritage mais pour une partie d'une page HTML : Slot / Components

Le principe consiste à définir une partie d'un "composant" accessible (avec slot) et d'en une page d'incluce ce "composant" en définissant les valeurs (components)

Ci-après une exemple avec une div pour un message d'alert

Blade / Slots-Components

Le "composant"


                    

                    <div class="alert alert-danger">
                        <div class="alert-title">{{ $title }}</div>

                        {{ $slot }}
                    </div>
                

Blade / Slots-Components

L'utilisation du "composant" précédent


                    @component('alert')
                        @slot('title')
                            Forbidden
                        @endslot

                        You are not allowed to access this resource!
                    @endcomponent
                

Blade / Afficher des données

L'affichage des données dans la vue se fait avec les {{ - }}


                    Hello, {{ $name }}.
                

Si name est un paramètre envoyée à la vue.

Blade / Structures de contrôle


                    @if (count($records) === 1)
                        I have one record!
                    @elseif (count($records) > 1)
                        I have multiple records!
                    @else
                        I don't have any records!
                    @endif
                

Blade / Structures de contrôle


                    @switch($i)
                        @case(1)
                            First case...
                            @break

                        @case(2)
                            Second case...
                            @break

                        @default
                            Default case...
                    @endswitch
                

Blade / Structures de contrôle


                    @unless (Auth::check())
                        You are not signed in.
                    @endunless
                

Permet de faire le test "A moins que vous ne soyez authentifié".

Blade / Structures de contrôle


                   @isset($records)
                        // $records is defined and is not null...
                    @endisset

                    @empty($records)
                        // $records is "empty"...
                    @endempty
                

Vérifier si les données existent

Blade / Tests de sécurité


                @auth
                // The user is authenticated...
                @endauth

                @guest
                // The user is not authenticated...
                @endguest
                

Blade / Boucles


                    @for ($i = 0; $i < 10; $i++)
                        The current value is {{ $i }}
                    @endfor

                    @foreach ($users as $user)
                        

This is user {{ $user->id }}

@endforeach @forelse ($users as $user)
  • {{ $user->name }}
  • @empty

    No users

    @endforelse @while (true)

    I'm looping forever.

    @endwhile

    Blade / Boucles

    Laravel propose une variable de boucle pour vos vues

    Property Description
    $loop->index The index of the current loop iteration (starts at 0).
    $loop->iteration The current loop iteration (starts at 1).
    $loop->remaining The iteration remaining in the loop.
    $loop->count The total number of items in the array being iterated.
    $loop->first Whether this is the first iteration through the loop.
    $loop->last Whether this is the last iteration through the loop.
    $loop->depth The nesting level of the current loop.
    $loop->parent When in a nested loop, the parent's loop variable.

    Blade / Commentaires

    
                        {{-- This comment will not be present in the rendered HTML --}}
                    

    Blade / Code PHP

    Vous pouvez directement mettre du code PHP dans vos templates Blade

    
                        @php
                            //
                        @endphp
                    

    Blade / Assets

    Blade propose de nombreux outils pour compiler vos assets (css, js, less, ...).

    Blade gère bien sûr la possibilité de localiser vos applications.

    Vous pouvez également facilement utiliser npm et les scripts associés pour vos développements front.

    Laravel s'intègre également très bien avec le framework JS : VueJS (un exemple est d'ailleurs disponible par défait), mais peut aussi travailler avec ReactJS

    Base de données

    Laravel permet de se connecter à des base de données MySQL, SQL Server, SQLLite et Postgre.

    Vous trouverez tous les détails dans la documentation officielle

    Mais Larvel dispose d'un ORM (Object Relationnal Mapping) pour faciliter la manipulation des données au travers de modèles.

    Eloquent

    Quelques règles sont à respecter pour que tout fonctionne

    • Présence d'une clé primaire nommée id
    • Présence de deux champs created_at updated_at de type timestamp.
    • La table dans MySQL doit être au pluriel et le model au singulier.

    Eloquent

    Il faut créer la table associée. Pour cela Laravel propose le mécanisme de migration.

    
                        php artisan make:migration create_flights_table
                    

    Cette commande va créer un fichier dans le répertoire database/migrations

    
                    class CreateFlightsTable extends Migration
                    {
                        /**
                        * Run the migrations.
                        *
                        * @return void
                        */
                        public function up()
                        {
                            Schema::create('flights', function (Blueprint $table) {
                                $table->increments('id');
                                $table->string('name');
                                $table->string('airline');
                                $table->timestamps();
                            });
                        }
    
                        /**
                        * Reverse the migrations.
                        *
                        * @return void
                        */
                        public function down()
                        {
                            Schema::drop('flights');
                        }
                    }
                    

    Eloquent

    On peut ensuite executer les migrations pour mettre à jour la base de données.

    
                        php artisan migrate
                    

    Toutes les possibilités offertes par les migrations sur la documentation officielle.

    Eloquent

    Laravel propose Eloquent pour gérer les échanges avec la base de données. Pour cela vous devez configurer le fichier config/database.php.

    Vous pouvez ensuite utiliser Artisan pour créer vos modèles

    
                    php artisan make:model Flight
                    

    Eloquent

    Il faut ensuite indiquer dans le fichier généré la table.

    
                        namespace App;
    
                        use Illuminate\Database\Eloquent\Model;
    
                        class Flight extends Model
                        {
                            protected $table = 'flights';
                        }
                    

    Eloquent

    Eloquent propose quelques méthodes pour effectuer les requêtes de selection classique.

    La méthode "all" permet de récupérer toutes les données d'une table.

    Eloquent

    Exemple d'affichage de toutes les données de la table fligths.

    
                        use App\Flight;
    
                        $flights = App\Flight::all();
    
                        foreach ($flights as $flight) {
                            echo $flight->name;
                        }
                    

    Eloquent / Select

    La méthode "find" permet de récupérer un élément précis de la table par son id.

    
                        // Retrieve a model by its primary key...
                        $flight = App\Flight::find(1);
    
                        // Retrieve the first model matching the query constraints...
                        $flight = App\Flight::where('active', 1)->first();
    
                        $flights = App\Flight::find([1, 2, 3]);
                    

    Eloquent / Insert

    Pour créer un nouvel enregistrement, il faut définir un objet du type "Model", et utiliser la méthode save()

    
                        public function store(Request $request)
                        {
                            // Validate the request...
    
                            $flight = new Flight;
    
                            $flight->name = $request->name;
    
                            $flight->save();
                        }
                    

    Eloquent / Update

    Pour mettre à jour un enregistrement, il faut récupérer un objet du type "Model", et utiliser la méthode save()

    
                        $flight = App\Flight::find(1);
    
                        $flight->name = 'New Flight Name';
    
                        $flight->save();
                    

    Eloquent / Delete

    Pour supprimer à jour un enregistrement, il faut récupérer un objet du type "Model", et utiliser la méthode delete()

    
                        $flight = App\Flight::find(1);
    
                        $flight->delete();
                    

    Eloquent / Controller / Resources

    Créer les Resources en lien avec un modèle

    
                        php artisan make:controller FlightController --resource --model=Flight
                    

    Va créer toutes les resources en lien avec le modèle.

    Eloquent / Relations

    La déclaration d'une relation entre deux modèles se fait en ajoutant des méthodes dans les modèles pour expliciter les liens.

    Laravel propose les relations suivantes : One To One, One To Many, One To Many (Inverse), Many To Many

    Eloquent / Relations

    Par exemple pour définir une relation OneToMany, ici un post à plusieurs comments

    
                        class Post extends Model
                        {
                            /**
                             * Get the comments for the blog post.
                             */
                            public function comments()
                            {
                                return $this->hasMany('App\Comment');
                            }
                        }
                    

    Eloquent / Relations

    Il faut définir en amont les relations dans les migrations. Attention l'ordre est important.

    
                       Schema::table('comments', function($table) {
                            $table->foreign('post_id')->references('id')->on('posts');
                        });
                    

    Vous devez avoir définit le champs "post_id" comme un champe de votre table.

    
                        $table->unsignedInteger('post_id')->nullable();
                    

    Securité

    Laravel propose de gérer l'authentification. Pour cela executez la ligne ci-dessous

    
                        php artisan make:auth
                    

    Cette instruction va générer la gestion de l'authentification, en plus des modèles déjà définies. Des vues sont ajoutées, ainsi qu'un layout. Toute la connexion/inscription/deconnexion est maintenant activée.

    Securité

    Pour récuperer l'utilisateur connecté

    
                        use Illuminate\Support\Facades\Auth;
    
                        // Get the currently authenticated user...
                        $user = Auth::user();
    
                        // Get the currently authenticated user's ID...
                        $id = Auth::id();
                    

    Securité

    Pour sécuriser vos routes

    
                        Route::get('profile', function () {
                            // Only authenticated users may enter...
                        })->middleware('auth');
                    

    Premier projet pas-à-pas

    Etape pour la conception d'un projet

    1. Installer Laravel
    2. Configurer la database et les droits
    3. Créer les migrations pour les tables nécessaires
    4. Créer les modèles (Eloquent)
    5. Créer les resources (controller) et définir les routes
    6. Définir les vues

    Premier projet pas-à-pas

    Installer Laravel

    
                    composer create-project --prefer-dist laravel/laravel blog
                    

    Premier projet pas-à-pas

    Configurer les fichiers dans le répertoire config, et notamment le fichier database.php, ainsi que le fichier .env à la racine de votre projet.

    Premier projet pas-à-pas

    On va utiliser deux tables (article et user). On va donc définir le fichier de migration pour gérer cela.

    
                        php artisan make:migration create_table_article
                    

    La partie User est existante par défaut dans laravel, car permet de gérer la sécurité. Nous ne devons pas la créer.

    Premier projet pas-à-pas

    Ajouter les champs dans le fichier pour votre table Article.

    • Titre
    • Texte

    Par défaut Laravel intégre un champs created_at et updated_at, ainsi qu'un champ id.

    Premier projet pas-à-pas

    Définir les relations entre user et articles. Ajouter dans le fichier de migration d'Article, dans la méthode "up()"

    
                        Schema::table('articles', function($table) {
                            $table->foreign('user_id')->references('id')->on('users');
                        });
                    

    N'oubliez pas de définir le champ "user_id" dans votre table article.

    Premier projet pas-à-pas

    Créer les tables dans la base de données.

    
                        php artisan migrate
                    

    Si vous rencontrez un message d'erreur sur la table "users", Veuillez suivre le correctif de ce lien.

    Premier projet pas-à-pas

    Créer les modèles associés. Le modèle de User est déjà présent.

    
                    php artisan make:model Article
                    

    Premier projet pas-à-pas

    Modifiez ces deux fichiers pour faire le lien avec vos tables et définir les relations.

    Premier projet pas-à-pas

    Créer les ressources (contrôleurs).

    
                        php artisan make:controller ArticleController --resource --model=Article
                    

    Premier projet pas-à-pas

    Ajouter les routes en fonction de ces resources

    Premier projet pas-à-pas

    Laravel propose de gérer l'authentification. Pour cela executez la ligne ci-dessous

    
                        php make:auth
                    

    Cette instruction va générer la gestion de l'authentification, en plus des modèles déjà définies. Des vues sont ajoutées, ainsi qu'un layout. Toute la connexion/inscription/deconnexion est maintenant activée.

    Premier projet pas-à-pas

    Définir les méthodes (index et show) et les vues associées pour la partie Article.

    Projet

    En binôme.

    Réaliser un forum, en vous basant sur Laravel, votre forum doit intégrer les fonctionnalités suivantes :

    • Inscription, connexion, déconnexion
    • Création de message dans les catégories du forum
    • Possibilité de répondre à un message
    • Administration : Création des catégories et sous-catégories

    Projet

    • Il y aura 3 niveaux d'accès : Administrateur, modérateur (possibilité de supprimer ou déplacer un message), membre (possibilité de créer un message)
    • Un message pourra intégrer des fichiers

    Projet

    L'esthétique du forum n'est pas prise en compte. L'usage d'une librairie CSS ou d'un template est suffisant.

    Vous veillerez à l'ergonomie et à la lisibilité.

    David Annebicque | IUT De Troyes | DUT MMI | 2018