Etant donné que les requêtes HTTP sont fugitives et ne laissent aucune trace il est important de disposer d'un système qui permet de mémoriser des informations entre deux requêtes. C'est justement l'objet des sessions.
Il est souvent utile (ça sera le cas pour notre exemple) de savoir si une certaine clé est présente en session :
Ces informations demeurent pour le même client à travers ses requêtes. Laravel s'occupe de ces informations, on se contente de lui indiquer un couple clé-valeur et il s'occupe de tout.
Ce ne sont là que les méthodes de base pour les sessions, vous trouverez tous les renseignements complémentaires dans la documentation .
La gestion des fichiers
Laravel utilise Flysystem comme composant de gestion de fichiers. Il en propose une API bien pensée et facile à utiliser. On peut ainsi manipuler fichiers et dossiers de la même manière en local ou à distance, que ce soit en FTP ou sur le cloud.
La configuration du système se trouve dans le fichier config/filesystem.php . Par défaut on est en local :
'default' => 'local',
Mais on peut aussi choisir ftp, s3 ou rackspace (pour ces deux derniers il faut installer les composants correspondants). On peut aussi mettre en place un accès à d'autres possibilités et il existe des composants à ajouter, comme par exemple celui-ci pour Dropbox .
On peut définir des "disques" (disks ) qui sont des cibles combinant un driver, un dossier racine et différents éléments de configuration :
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => 'your-key',
'secret' => 'your-secret',
'region' => 'your-region',
'bucket' => 'your-bucket',
],
],
Donc par défaut c'est le disque local qui est actif et le dossier racine est storage/app .
Autrement dit si j'utilise ce code :
Storage::disk('local')->put('recettes.txt', 'Contenu du fichier');
Je vais envoyer le fichier recettes.txt dans le dossier storage/app .
Et si j'utilise ce code :
Storage::disk('public')->put('recettes.txt', 'Contenu du fichier');
Cette fois j'envoie le fichier dans le dossier storage/app/public . Par convention ce dossier doit être accessible depuis le web.
Mais je vous ai dit précédemment que seul le dossier public à la racine doit être accessible. Alors ?
Alors pour que ce soit possible il faut créer un lien symbolique public/storage qui pointe sur storage/app/public . Il y a d'ailleurs une commande d'Artisan pour ça :
php artisan storage:link
Mais franchement je préfère créer directement un dossier dans public . Les motivations avancées (ne pas perdre de fichiers au déploiement) me paraissent trop minces.
Donc rien n'empêche de changer la configuration :
'public' => [
'driver' => 'local',
'root' => public_path(),
'visibility' => 'public',
],
Ainsi le disque "public" pointe sur le dossier public . C'est d'ailleurs ce qu'on va faire pour l'exemple de ce chapitre.
Il y a de nombreuses méthodes pour manipuler dossiers et fichiers, je ne vais pas développer tout ça pour le moment, vous avez le détail dans la documentation . On va surtout utiliser les possibilités de téléchargement des fichiers dans ce chapitre.
La requête de formulaire
Nous allons encore avoir besoin d'une requête de formulaire pour la validation. Comme nous l'avons déjà vu nous utilisons la commande d'Artisan pour la créer :
php artisan make:request ImagesRequest
Vous devez trouver le fichier ici :
Changez le code pour celui-ci :
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ImagesRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return ['image' => 'required|image|dimensions:min_width=100,min_height=100'];
}
}
On a seulement 3 règles pour le champ image :
le champ est obligatoire (required ),
ce doit être une image (image ),
l'image doit faire au minimum 100 * 100 pixels (dimensions ).
Maintenant notre validation est prête.
Les routes et le contrôleur
On va avoir besoin de deux routes :
Route::get('photo', 'PhotoController@create');
Route::post('photo', 'PhotoController@store');
On utilise Artisan pour créer le contrôleur :
php artisan make:controller PhotoController
Vous devez trouver le fichier ici :
Changez le code pour celui-ci :
<?php
namespace App\Http\Controllers;
use App\Http\Requests\ImagesRequest;
class PhotoController extends Controller
{
public function create()
{
return view('photo');
}
public function store(ImagesRequest $request)
{
$request->image->store(config('images.path'), 'public');
return view('photo_ok');
}
}
Donc au niveau des urls :
En ce qui concerne le traitement de la soumission, vous remarquez qu'on récupère le chemin du dossier d'enregistrement qu'on a prévu dans la configuration :
config('images.path')
La partie intéressante se situe avec ce code :
$request->image->store(config('images.path'), 'public')
On récupère l'image avec $request->image . Ce qu'on obtient là est une instance de la classe Illuminate/Http/UploadedFile .
Laravel dispose d'une documentation complète de ses classes, par exemple vous trouvez cette classe ici avec la méthode store documentée .
La méthode store génère automatiquement un nom de fichier basé sur son contenu (hashage MD5) et elle retourne le chemin complet.
Les vues
On va utiliser le template des chapitres précédents (resources/views/template.blade.php ) :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mon joli site</title>
{!! Html::style('https://netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css') !!}
</head>
<body>
@yield('contenu')
</body>
</html>
Voici la vue pour le formulaire (resources/views/photo.blade.php ) :
@extends('template')
@section('contenu')
<br>
<div class="col-sm-offset-4 col-sm-4">
<div class="panel panel-info">
<div class="panel-heading">Envoi d'une photo</div>
<div class="panel-body">
{!! Form::open(['url' => 'photo', 'files' => true]) !!}
<div class="form-group {!! $errors->has('image') ? 'has-error' : '' !!}">
{!! Form::file('image', ['class' => 'form-control']) !!}
{!! $errors->first('image', '<small class="help-block">:message</small>') !!}
</div>
{!! Form::submit('Envoyer !', ['class' => 'btn btn-info pull-right']) !!}
{!! Form::close() !!}
</div>
</div>
</div>
@endsection
Avec cet aspect :
Remarquez comment est créé le formulaire :
{!! Form::open(['url' => 'photo', 'files' => true]) !!}
Le fait d'ajouter l'attribut files avec la valeur true va avoir pour effet de faire apparaître le type mime nécessaire pour associer un fichier lors de la soumission :
enctype="multipart/form-data"
En cas d'erreur de validation le message est affiché et la bordure du champ devient rouge :
Et voici la vue pour la confirmation en retour (app/views/photo_ok.blade.php ) :
@extends('template')
@section('contenu')
<br>
<div class="col-sm-offset-3 col-sm-6">
<div class="panel panel-info">
<div class="panel-heading">Envoi d'une photo</div>
<div class="panel-body">
Merci. Votre photo à bien été reçue et enregistrée.
</div>
</div>
</div>
@endsection
Avec cet aspect :
On retrouve normalement le fichier bien rangé dans le dossier prévu :
Voici le schéma de fonctionnement :
En résumé
Les fichiers de configuration permettent de mémoriser facilement des ensembles clé-valeur et sont gérés par l'helper config .
Les sessions permettent de mémoriser des informations concernant un client et sont facilement manipulables avec l'helper session .
Laravel comporte un système complet de gestion de fichiers en local, à distance ou sur le cloud avec une API commune.
Il est facile de créer un système de téléchargement de fichier.