développement web - jordan sablon

127
Séance n°5 EIL Côte d’Opale – CALAIS Jordan SABLON Développement WEB

Upload: khangminh22

Post on 06-May-2023

1 views

Category:

Documents


0 download

TRANSCRIPT

Séance n°5

EIL Côte d’Opale – CALAIS Jordan SABLON

Développement WEB

Évoluer vers une architecture PHP professionnelle

MVC – POO - repositories - exceptions - namespaces

Contextualiser la problématiqueÉtat de l’art du code actuel

Mise en place du contexte pour la séance

Nous allons partir d’un développement tel que nous l’avons vu jusqu’à présent.

Ce développement se base sur un sujet spécifique que nous allons réaliser

ensemble tout au long de la séance.

A chaque étape, nous allons enrichir notre application et aborder une nouvelle

notion.

Mise en place du contexte pour la séance

Présentation du sujet

L’objectif est de réaliser une petite application web qui récupère des pays

depuis une base de données afin de les afficher à l’écran.

Mise en place du contexte pour la séance

Modèle de données

Notre base de données contiendra une table « pays ».

Cette table contiendra deux colonnes :

▪ id : l’identifiant du pays

▪ libelle : le nom du pays

Mise en place du contexte pour la séance

Étapes de réalisation

▪ Créer la base de données

▪ Écrire la requête de récupération des pays depuis la base de données

▪ Afficher les pays

▪ Mettre un peu de style pour la mise en forme

Mise en place du contexte pour la séance

Code réalisé HTML

PHP

SQL

HTML

HTML

PHP

PHP

Cette version complète du code est téléchargeable en cliquant ici.

Mise en place du contexte pour la séance

Points négatifs

▪ Mélange de code PHP, HTML et SQL

▪ Structure monolithique (1 seul bloc de code)

Difficilement maintenable et non réutilisable

Mise en place du contexte pour la séance

Quelles améliorations apporter ?

▪ Isoler l’affichage

▪ Isoler l’accès aux données

On réalise ce que l’on appelle la séparation des responsabilités

Séparer les responsabilitésIsoler l’affichage et l’accès aux données

En quoi cela consiste ?

▪ La séparation des responsabilités consiste à isoler l’accès aux données et

l’affichage.

▪ On va donc réaliser les manipulations de données et l’affichage dans des

fichiers indépendants.

Code obtenu après séparation

▪ modele.php

Code obtenu après séparation

▪ afficherPays.php

Code obtenu après séparation

Modèle

Contrôleur

Vue

Application de l’architecture MVC

(Modèle – Vue – Contrôleur)

▪ index.php

Cette version complète du code est téléchargeable en cliquant ici.

Architecture MVCModèle – Vue – Contrôleur

Présentation

Le modèle MVC décrit une manière

d'architecturer une application informatique en la

décomposant en trois sous-parties :

▪ La partie Modèle

▪ La partie Vue

▪ La partie Contrôleur

Ce patron de conception (design pattern) permet

de bien séparer le code de l'interface graphique

de celui de la logique applicative.

Présentation

La partie Modèle d'une architecture MVC

encapsule la logique métier (business logic) ainsi

que l'accès aux données. Il peut s'agir d'un

ensemble de fonctions (modèle procédural) ou de

classes (modèle orienté objet)

Rôles des composants

La partie Vue s'occupe des interactions avec

l'utilisateur : présentation, saisie et validation des

données.

Rôles des composants

La partie Contrôleur gère la dynamique de

l'application.

Elle fait le lien entre l'utilisateur et le reste de

l'application.

Rôles des composants

Interactions entre les composants

Amélioration du code : acte 1Respect des standards de développement

▪ Langue de développement : anglais

▪ Pas de balise de fermeture PHP dans un fichier contenant

exclusivement du PHP

▪ Commenter son code

▪ Documenter son code

Rappel des standards que nous allons respecter

Traduction de notre code en anglais

La traduction de notre code va se dérouler en 4 étapes :

▪ Les variables

▪ Les fonctions

▪ Les fichiers

▪ La base de données

Traduction de notre code en anglais

Ici, seule la variable « $donnees » devient « $country » dans

afficherPays.php aux lignes 12 et 16.

Renommer les variables

Traduction de notre code en anglais

Actuellement, seul notre fichier modele.php possède une

fonction « getPays() » à renommer en « getCountries() ».

On impactera également notre contrôleur index.php :

Renommer les fonctions

Traduction de notre code en anglais

Nos fichiers « modele.php » et « afficherPays.php » seront

renommés en « model.php » et « countriesView.php ».

On impactera à nouveau notre contrôleur index.php :

Renommer les fichiers

Traduction de notre code en anglais

Renommer les attributs en base de données

Notre table « pays » sera renommée en « countries » .

Elle contiendra désormais deux colonnes :

▪ id : l’identifiant du pays

▪ label : le nom du pays

Traduction de notre code en anglais

Renommer les attributs référencés dans le code

On oubliera pas de renommer également les attributs de base de données

référencés dans le code, notamment notre unique requête SQL pour le

moment :

Elle devient donc :

$req = $bdd->prepare('SELECT * FROM countries');

$req = $bdd->prepare('SELECT * FROM pays');

Supprimer les balises fermantes PHP

Lorsque le fichier « .php » contient uniquement du code PHP, il

est recommandé de ne pas fermer la baslise « ?> ».

Cela permet d’éviter un envoi de code HTML par erreur

notamment en cas d’inclusion de fichiers PHP.

Commenter son code

Un code a beau être bien rédigé, il doit être commenté.

En effet, un code bien rédigé sera compréhensible par tout

développeur.

Le commentaire permettra de comprendre la logique d’ajout du

code en question, dont la cause peut être aussi bien fonctionnelle

que technique.

Documenter son code

Au delà de commenter son code, il est également important de

bien le documenter.

Cela permettra par la suite une meilleure maintenabilité, et

permettra aussi d’éditer une documentation qui pourra contribuer

à la montée en compétences technique d’un nouveau

développeur.

Cette version complète du code est téléchargeable en cliquant ici.

Ajout d’une nouvelle fonctionnalitéConsulter le détail d’un pays

Présentation de la fonctionnalité

Avant de découvrir d’autres notions, nous allons enrichir notre

application et lui ajouter une nouvelle fonctionnalité : la

consultation de détails pour chaque pays.

Présentation de la fonctionnalité

Pour chaque pays, on pourra consulter un certain nombre

d’informations présentes en base de donnés :

Les étapes de réalisation

Modifier la base de données

Nous allons ajouter une table « details » dans notre base de données.

Cette table contiendra quatre colonnes :

▪ id : l’identifiant du détail

▪ country_id : l’identifiant du pays concerné

▪ label : le libellé du détail

▪ value : la valeur du détail

Les étapes de réalisation

Modification dumodèle

Pour pouvoir accéder aux données de cette nouvelle table, nous devons

ajouter une fonction dans notre model.php :

Les étapes de réalisation

Créer la vue

Pour afficher les détails d’un pays, nous devons disposer d’une vue qui sera

dédiée à cette tâche. Nous la nommerons « detailsView.php ».

Cette vue affichera le nom du pays concerné et la liste de ses détails.

Le titre de la page sera « Détails ».

Un bouton « Retour » nous permettra de revenir à la liste des pays.

Les étapes de réalisation

Créer un contrôleur spécifique

Nous allons créer un contrôleur dédié à la gestion des détails d’un pays que

nous appellerons « details.php ».

Il fera appel au modèle « model.php », vérifiera la présence de l’ID du pays

passé en paramètre pour lequel on souhaite consulter les détails, récupèrera

le pays concerné ainsi que ses détails puis fera appel à la vue

« detailsView.php » que nous venons de créer.

Les étapes de réalisation

Modifier la vue « countriesView.php »

Nous allons également modifier la vue « contriesView.php » afin d’y insérer

un lien « Afficher les détails » sur chacun des pays qui nous redirigera vers la

page de détails de chaque pays.

<a href=<?= "details.php?countryId=".$country['id'] ?>>Afficher les détails</a>

Cette version complète du code est téléchargeable en cliquant ici.

Création d’un routeurRoutage des requêtes

Qu’est-ce qu’un routeur ?

Un routeur peut être assimilé à un contrôleur « frontal ». Son

objectif sera d’appeler le bon contrôleur selon la requête réalisée

par l’utilisateur.

On dit qu’il « route » les requêtes, d’où son nom de « routeur ».

Qu’est-ce qu’un routeur ?

Voici un schéma de notre architecture MVC avec la mise en place

de notre routeur :

Pourquoi utiliser un routeur ?

La mise en place d’un routeur n’est pas obligatoire en soi.

Actuellement, nous avons deux vues, et deux contrôleurs

associés :

▪ index.php qui est le contrôleur pour la vue countriesView.php

▪ details.php qui est le contrôleur pour la vue detailsView.php

Pourquoi utiliser un routeur ?

Cela fonctionne très bien en l’état.

Toutefois, si l’on garde le système actuel, on risque vite de se

retrouver avec un fichier par page de notre site.

De plus, si des informations communes seraient à charger pour

deux vues différentes, nous devrions dupliquer le code.

Mise en place du routeur

Regrouper les contrôleurs

Nous allons commencer par regrouper nos deux contrôleurs index.php et

details.php dans deux fonctions au sein d’un même fichier que l’on

nommera « controller.php ».

On peut donc supprimer le fichier details.php qui ne nous est plus utile

désormais.

Mise en place du routeur

Création du routeur

Ensuite, nous allons insérer le contenu de notre routeur dans le fichier

index.php.

Ce routeur fera appel à nos différents contrôleurs (ici uniquement

controller.php pour le moment) et recevra systématiquement un paramètre

« action » qui permettra de réaliser le traitement adéquate.

Mise en place du routeur

Cette version complète du code est téléchargeable en cliquant ici.

Création du routeurindex.php controller.php

Amélioration du code : acte 2Organisation des fichiers dans des dossiers

Toujours dans l’optique de mieux organiser notre code, nous

allons créer une arborescence afin de classer nos fichiers :

Structurer pour mieux s’y retrouver

Structurer pour mieux s’y retrouver

On retrouve très fréquemment ce type d’arborescence :

controller/ contient l’ensemble de nos contrôleurs

model/ contient l’ensemble de nos modèles

public/ contient l’ensemble des fichiers statiques (css, js, etc.)

classés en sous-dossiers (css/, js/, images/, etc.)

vendor/ contient les bibliothèques tierces

views/ contient l’ensemble de nos vues

Adapter le code

Comme nos fichiers ont été déplacés dans différents dossiers, il ne

faut pas oublier d’ajuster les inclusions (scripts, feuilles de style,

modèles, vues, etc.)

J’ai profité de cette étape pour renommer les fichiers

« controller.php » et « model.php » respectivement en

« countryController.php » et « countryModel.php »

Cette version complète du code est téléchargeable en cliquant ici.

Ajout d’une nouvelle fonctionnalitéAjouter une information dans le détail d’un pays

Présentation de la fonctionnalité

Nous allons à nouveau enrichir notre application en ajoutant une

nouvelle fonctionnalité : l’ajout d’informations pour un pays.

Les étapes de réalisation

Enrichir lemodèle

La première étape consiste à créer une nouvelle fonction dans le fichier

« countryModel.php » afin d’insérer des données dans la table « details ».

Pour rappel, voici les attributs de cette table :

Les étapes de réalisation

Enrichir lemodèle

Nous allons donc créer la fonction suivante :

Les étapes de réalisation

Enrichir le contrôleur

Le contrôleur doit également être enrichi afin de pouvoir contacter le modèle :

Les étapes de réalisation

Modification de la vue « detailsView.php »

De même, nous devons ajouter un formulaire de saisie pour les informations :

Les étapes de réalisation

Enrichir le routeur

La dernière étape consiste à mettre à jour notre routeur afin qu’il puisse faire

appelle à notre contrôleur lors de la soumission du formulaire d’ajout.

Il sera chargé de vérifier la présence de l’id du pays, de la clé ainsi que de la

valeur de l’information à ajouter.

Les étapes de réalisation

Enrichir le routeur

Voici le code à ajouter :

Cette version complète du code est téléchargeable en cliquant ici.

Gestion des exceptionsGérer les erreurs dans le code

Gérer les erreurs dans une application

La gestion des erreurs est un sujet important en

programmation.

Malgré la qualité des développements et les différents tests qui

sont réalisés, il arrive parfois que des erreurs surgissent et il

vaut mieux les avoir anticipées au maximum.

Gérer les erreurs dans une application

Si l’on reprend notre routeur, on constate de nombreux if… else.

Ils ont pour but de réaliser des contrôles afin de s’assurer, par

exemple, de la présence des paramètres requis.

De cette façon, le code de notre routeur gère d’une certaine

manière les erreurs qui lui sont propres.

Gérer les erreurs dans une application

En revanche, si une erreur survient dans l’une des fonctions

appelées par le routeur, par exemple dans le contrôleur ou le

modèle, que se passe-t-il ?

Gérer les erreurs dans une application

On pourrait appliquer le même principe que pour le routeur, mais

cela présente deux inconvénients :

▪ Le code deviendrait vite complexe et la duplication augmenterait

▪ Ce n’est pas le rôle du contrôleur ni du modèle de gérer les

erreurs

Gérer les erreurs dans une application

Heureusement pour nous, on a une façon plus propre et générique

de gérer les erreurs dans le code : utiliser les exceptions.

Qu’est-ce qu’une exception ?

Voici à quoi ressemble un bloc de gestion d’exception :

Le traitement se réalise dans le bloc try.

Les erreurs sont gérées dans le bloc catch. S’il n’y a pas

d’erreurs, le bloc catch n’est pas interprété.

Qu’est-ce qu’une exception ?

Pour générer une exception, on doit « jeter une exception » (throw

exception en anglais) :

Qu’est-ce qu’une exception ?

En réalité, on a déjà utilisé ce principe depuis le début du module

sans forcément y prêter attention avec la connexion à la base de

données :

Obtenir du détail sur l’exception

Dans le cas où une erreur se produit et que l’on passe par le bloc

catch, on peut récupérer l’exception en question et afficher des

détails.

On utilise pour cela l’objet PHP « Exception ».

Obtenir du détail sur l’exception

Voici les informations que l’on peut récupérer pour une Exception $e :

▪ $e->getMessage Récupère le message de l'exception

▪ $e->getCode Récupère le code de l'exception

▪ $e->getFile Récupère le fichier dans lequel l'exception a été créée

▪ $e->getLine Récupère la ligne dans laquelle l'exception a été créée

▪ $e->getTrace Récupère la trace de la pile

Traitement post-exécution

A noter également que l’on peut insérer un bloc finally après des

blocs catch.

Le code à l'intérieur du bloc finally sera toujours exécuté après les

blocs try et catch, indépendamment du fait qu'une exception ait été

lancée, avant de continuer l'exécution normale.

Traitement post-exécution

Si une déclaration return est rencontrée à l'intérieur des blocs

try ou catch, le bloc finally sera quand même exécuté !

De plus, la déclaration return est évaluée quand elle est rencontrée,

mais le résultat sera retourné après le bloc finally soit exécuté.

Enfin, si le bloc finally contient aussi une déclaration return la

valeur du bloc finally est retournée.

Gérer les exceptions dans notre routeur

On réalise le traitement du

routeur dans un bloc try

Gérer les exceptions dans notre routeur

On génère une exception

pour chaque cas d’erreur

dans notre routeur avec

un message permettant

de comprendre l’origine

du problème.

Gérer les exceptions dans notre routeur

Dans un bloc catch, on

récupère l’exception en

cas d’erreur ainsi que

certains détails.

On appelle ensuite une vue « errorView.php » dédiée à

l’affichage des erreurs.

Gérer les exceptions dans notre routeur

Voici le résultat obtenu en cas d’erreur dans le code de notre

application :

Remonter les exceptions

Jusque là, on a simplement amélioré notre système de gestion

des erreurs en remplaçant les if…else par des blocs try /

catch avec des exceptions.

Un des principaux avantages de l’usage des exceptions est la

remontée des exceptions.

Remonter les exceptions

En effet, si une erreur survient dans une fonction appelée dans

un bloc try, l’exception est directement remontée jusqu’au bloc

catch correspondant :

Remonter les exceptions

On peut ainsi gérer les exceptions dans nos contrôleurs et nos

modèles :

Remonter les exceptions

De même, le bloc try / catch de notre fonction « connect »

dans notre modèle model.php n’est plus utile puisque le

traitement est déjà encapsulé par un bloc try / catch dans le

routeur :

Cette version complète du code est téléchargeable en cliquant ici.

POOProgrammation Orientée Objet

Qu’est-ce que la POO ?

La POO, ou Programmation Orientée Objet consiste à

manipuler des objets.

Un objet peut être définie comme une classe qui regroupe un

ensemble de variables et de fonctions.

Pourquoi utiliser la POO ?

Imaginons que l’on souhaite implémenter un champs de

sélection de date dans un formulaire :

Pourquoi utiliser la POO ?

Si nous devions développer cette fonctionnalité de zéro, ce

serait un travail complexe nécessitant plusieurs fonctions et

plusieurs variables pour stocker les différentes informations.

De plus, si nous devions réutiliser cela à plusieurs reprises

dans notre application web, il n’est pas envisageable de repartir

de zéro à nouveau.

Pourquoi utiliser la POO ?

Ainsi, que ce soit pour la réutilisabilité dans notre application

web ou que ce soit pour diffuser notre développement afin qu’il

soit utilisé par d’autres projets, le code ainsi rédigé aura une

certaine complexité et ne sera peut-être pas forcément simple

d’usage au premier abord.

Pourquoi utiliser la POO ?

On réalise pour cela une sorte de « boite noire » conçue de

façon « orientée objet » qui contient l’ensemble de nos

traitements.

Le but étant de mettre à disposition cette « boite noire » avec

quelques fonctions à disposition.

Pourquoi utiliser la POO ?

Ainsi, l’utilisateur qui souhaite utiliser notre code n’aura pas à

comprendre la totalité du fonctionnement du programme mais

devra simplement utiliser les quelques fonctions que nous lui

mettons à disposition et qui l’intéresse.

Pourquoi utiliser la POO ?

En résumé, programmer de manière « orientée objet », c'est

créer du code source (potentiellement complexe) mais que l'on

masque en le plaçant à l'intérieur d'un cube (un objet) à travers

lequel on ne voit rien.

Pour la personne qui va l'utiliser, travailler avec un objet est

donc beaucoup plus simple qu'avant : il suffit de faire appel à

certaines fonctions de base mise à disposition.

Pourquoi utiliser la POO ?

Si l’on se souvient, nous avons déjà utilisé la POO depuis le

début du module :

Au final, on utilise l’objet PDO facilement mais sans se

demander, ni avoir besoin de savoir, ce qu’il se passe derrière.

Plus concrètement, d’un point de vue du code

Si l’on se focalise un peu plus sur le code, un objet peut être

créé à partir d’une classe.

On peut par exemple imaginer une classe Maison qui agirait

comme un plan de construction nous permettant de créer

plusieurs objets (premireMaison, deuxiemeMaison, etc.).

Plus concrètement, d’un point de vue du code

On peut schématiser cela comme ceci :

Plus concrètement, d’un point de vue du code

Le code associé serait le suivant :

Plus concrètement, d’un point de vue du code

On note 2 types d'éléments dans la classe :

▪ Des variables membres

▪ Des fonctions membres

Ces variables et fonctions sont encapsulées dans la classe.

Cela permet de ne pas les mélanger avec d'autres variables et

fonctions du même nom dans notre programme.

Plus concrètement, d’un point de vue du code

On peut donc sans problème avoir 2 fonctions nommées

« ouvrirPorte » ou 2 variables « temperature » dans le

code, à condition qu'elles soient dans des classes différentes.

Plus concrètement, d’un point de vue du code

On constate la présence des mots-clés « public » et

« private » :

Plus concrètement, d’un point de vue du code

Ils permettent de gérer la visibilité de nos variables et fonctions

dans la classe.

Par défaut, sans indication particulière, les variables seront

considérées comme ayant une visibilité « public »

Plus concrètement, d’un point de vue du code

Voici les différentes visibilités :

▪ private visibles et accessibles directement que

depuis l'intérieur même de la classe

▪ protected visible et accessible depuis l’intérieur de la

classe ainsi que dans une classe parente et

ses classes dérivées (héritantes)

▪ public visibles et accessible depuis n'importe où

dans le programme

Création de « repositories »Passage du modèle en objet

Patron de conception (« design pattern »)

Nous allons maintenant mettre en place un patron de conception

(« design pattern ») appelé « Repository ».

Il nous permettra d’encapsuler le modèle dans une classe.

Qu’est-ce qu’un patron de conception ?

Un patron de conception (« design pattern ») est un arrangement

caractéristique de modules, reconnu comme bonne pratique en

réponse à un problème de conception d’un logiciel.

Il décrit une solution standard, utilisable dans la conception de

différents logiciels.

Repository Design Pattern

Le patron de conception « Repository » ou « Repository Design

Pattern » permet d’encapsuler les requêtes lancées à la base de

données.

Grâce au repository, on applique la règle dite « Thin controllers,

fat models » permettant d’alléger les contrôleurs de l’accès aux

données.

Repository Design Pattern

De plus, les méthodes développées pour un repository pourront

facilement être réutilisées dans l’application.

Enfin, il est plus facile de tester un repository qu’un contrôleur

puisque moins de dépendances sont en jeu.

Passage du modèle en objet

Dans notre cas, nous allons distinguer la gestion de pays de celle

des détails des pays.

Passage du modèle en objet

Notre modèle sera donc scindé en deux classes :

CountryRepository qui regroupera l’accès aux

données des pays

DetailRepository qui regroupera l’accès aux

données des détails des pays

CountryRepository

DetailRepository

Passage du modèle en objet

Nous devons désormais mettre à jour notre contrôleur.

Le contrôleur ne doit plus faire appel à des fonctions mais doit

désormais créer des objets à partir des classes précédemment

créées.

Ces objets permettront de faire appel aux fonctions des

repositories.

Passage du modèle en objet

Nous commençons par faire appel aux repositories :

On utilise la fonction require_once qui nous permet de nous

assurer qu'on ne charge pas la classe une seconde fois.

Passage du modèle en objet

On crée ensuite des objets à partir des repositories au lieu de faire

un simple appel à une fonction d’un modèle :

HéritageInclusion de caractéristiques d’une classe au sein d’une autre classe

Qu’est-ce que l’héritage ?

Nous allons aborder une nouvelle notion de la programmation

orientée objet : l’héritage.

En POO, une classe peut hériter d'une autre classe pour en

récupérer toutes ses caractéristiques.

Qu’est-ce que l’héritage ?

Si l’on imagine deux objets Maison et Appartement, on peut

affirmer que ce sont tous les deux des logements avec des points

communs : une porte, une superficie, une température etc.

Néanmoins, un maison et un appartement ont chacun leur

spécificité : l’appartement est situé à un certain étage

contrairement à une maison.

Qu’est-ce que l’héritage ?

On peut représenter cela par deux

objets Maison et Appartement qui

héritent tous les deux d’une classe

Logement.

Qu’est-ce que l’héritage ?

La classe Logement (classe mère) pourrait être ainsi :

Qu’est-ce que l’héritage ?

Les classes Maison et Appartement (classes filles) ainsi :

Elles étendent de la classe Logement.

Utiliser l’héritage

Dans le cadre de notre application, nous pouvons appliquer ce

principe.

Dans nos repositories, nous avons du dupliquer la méthode

connect permettant de se connecter à la base de données.

Utiliser l’héritage

Nous pouvons désormais créer une classe Repository générique,

dont hériteront les classes CountryRepository et

DetailRepository :

Utiliser l’héritage

Cette version complète du code est téléchargeable en cliquant ici.

Utiliser des namespacesÉviter les collisions de noms de classes

Qu’est-ce qu’un namespace ?

Un espace de nom (ou « namespace »), permet d’éviter les

collisions de noms de classes.

Dans une application d’envergure, en cas d’utilisation de

bibliothèques externes, il est possible qu’une classe d’une

bibliothèque possède le même nom qu’une de nos classes.

Qu’est-ce qu’un namespace ?

Sans gestion particulière de notre part, l’application cesserait de

fonctionner car il n’est pas permis d’avoir deux classes possédant

le même nom.

On utilise pour cela les namespaces qui vont agir comme des

dossiers et vont permettre d'avoir 2 classes du même du moment

qu'elles sont dans des namespaces différents.

Qu’est-ce qu’un namespace ?

Voici un exemple :

CountryRepository CountryRepository

Library\Model Company\Model

Mise en place des namespace

Nous définissons le namespace de nos repositories :

Mise en place des namespace

Puis nous faisons appel à ces namespaces dans notre contrôleur :

Mise en place des namespace

Attention pour l’usage de PDO, nous devons désormais réaliser

l’appel comme ceci avec un « \ » avant « PDO » :

Cette version complète du code est téléchargeable en cliquant ici.

protected function connect(){

return new \PDO('mysql:host=localhost;dbname=essai', 'root', '');

}