Quand on démarre le développement d’une site sous Symfony, l’une des première chose à faire concerne la gestion des utilisateurs. En effet dans la plupart des cas notre application devra permettre à des utilisateurs de s’inscrire puis de se connecter au site afin d’avoir accès à des sections particulières (espace membre, espace administrateur). Je reprends dans cet article les différents éléments à mettre en place pour avoir une base de travail fonctionnelle.
On va rendre possible une inscription (email / mot de passe), puis une connexion (idem). Une fois connecté on aura accès a un espace membre.
Nous partirons d’une installation « website » de symfony 4 lancé avec la commande
La première chose à faire sera de créer la base de données, et de la configurer dans le fichier « /.env », par exemple :
Entrons dans le vif du sujet, avec la création de l’entité « User », dans « /src/Entity/User.php ». Elle contiendra les champs email, password, isActive, roles et étendra la classe « UserInterface » de symfony. Ce qui nous donne avec les getters/setters et les méthodes obligatoires à implémenter, le code suivant :
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* @ORM\Table(name="user")
* @UniqueEntity(fields="email")
* @ORM\Entity()
*/
class User implements UserInterface, \Serializable {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string", length=255, unique=true)
* @Assert\NotBlank()
* @Assert\Email()
*/
private $email;
/**
* @Assert\NotBlank()
* @Assert\Length(max=250)
*/
private $plainPassword;
/**
* The below length depends on the "algorithm" you use for encoding
* the password, but this works well with bcrypt.
*
* @ORM\Column(type="string", length=64)
*/
private $password;
/**
* @ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* @ORM\Column(name="roles", type="array")
*/
private $roles = array();
public function __construct() {
$this->isActive = true;
// may not be needed, see section on salt below
// $this->salt = md5(uniqid('', true));
}
public function getUsername() {
return $this->email;
}
public function getSalt() {
// you *may* need a real salt depending on your encoder
// see section on salt below
return null;
}
public function getPassword() {
return $this->password;
}
function setPassword($password) {
$this->password = $password;
}
public function getRoles() {
if (empty($this->roles)) {
return ['ROLE_USER'];
}
return $this->roles;
}
function addRole($role) {
$this->roles[] = $role;
}
public function eraseCredentials() {
}
/** @see \Serializable::serialize() */
public function serialize() {
return serialize(array(
$this->id,
$this->email,
$this->password,
$this->isActive,
// see section on salt below
// $this->salt,
));
}
/** @see \Serializable::unserialize() */
public function unserialize($serialized) {
list (
$this->id,
$this->email,
$this->password,
$this->isActive,
// see section on salt below
// $this->salt
) = unserialize($serialized);
}
function getId() {
return $this->id;
}
function getEmail() {
return $this->email;
}
function getPlainPassword() {
return $this->plainPassword;
}
function getIsActive() {
return $this->isActive;
}
function setId($id) {
$this->id = $id;
}
function setEmail($email) {
$this->email = $email;
}
function setPlainPassword($plainPassword) {
$this->plainPassword = $plainPassword;
}
function setIsActive($isActive) {
$this->isActive = $isActive;
}
}
Une fois ce fichier enregistré, on peux mettre à jour notre base de données afin d’y créer la table « User ». Pour cela on lance les 2 commandes suivantes :
php bin/console doctrine:migration:migrate
Il est temps de passer à la configuration. Rendons nous dans le fichier « /config/packages/security.yaml » et remplissons le de la façon suivante :
# encoder
encoders:
App\Entity\User:
algorithm: bcrypt
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
our_db_provider:
entity:
class: App\Entity\User
property: email
firewalls:
main:
pattern: ^/
http_basic: ~
provider: our_db_provider
anonymous: ~
form_login:
login_path: login
check_path: login
logout:
path: /logout
target: /
role_hierarchy:
ROLE_ADMIN: ROLE_USER
#ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/member, roles: ROLE_USER }
Comme on peux le comprendre on a mis en place la configuration pour l’encodage du mot de passe, on indique que nos utilisateurs passe par l’entité « App\Entity\User » et que le login est le champ « email ». On configure aussi les liens /login et /logout à utiliser, les différents roles possible (ROLE_USER, ROLE_ADMIN) et bien sur les droits d’accès en fonctions des rôles. Ici toutes les routes commençant par « /member » ne seront accessible que pour les membres connectés, et celle commençant par « /admin » pour les membres connecté ayant le rôle « ROLE_ADMIN ».
Pour faire fonctionner la déconnexion « logout », il faut simplement créer la route. On se rend donc dans le fichier « /config/routes.yaml » pour y mettre ce code :
path: /logout
Il nous reste à créer la page contenant le formulaire d’inscription, celle contenant le formulaire de connexion et tout sera fonctionnel.
Pour l’inscription, on va d’abord créer le formulaire dans un fichier à part qui sera « /src/Form/UserType.php ». J’ai ajoutés des classes css de bootstrap pour le bouton submit, car on verra plus bas que je propose d’utiliser bootstrap 4 pour l’affichage, mais il s’agit bien sur uniquement d’un exemple.
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class UserType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('email', EmailType::class)
->add('plainPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'first_options' => array('label' => 'Mot de passe'),
'second_options' => array('label' => 'Confirmation du mot de passe'),
))
->add('submit', SubmitType::class, ['label'=>'Envoyer', 'attr'=>['class'=>'btn-primary btn-block']])
;
}
}
Nous allons utiliser ce formulaire dans le controller « /src/Controller/RegistrationController.php ». La page permettant l’inscription sera accessible sur l’url « /register », ici on enregistre et on valide directement le compte, on peut aussi attribuer le rôle utilisateur dans ce controlleur. C’est une base qui pourras être amélioré (envoie d’un email de confirmation…etc)
use App\Form\UserType;
use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class RegistrationController extends Controller {
/**
* @Route("/register")
*/
public function registerAction(Request $request, UserPasswordEncoderInterface $passwordEncoder) {
// 1) build the form
$user = new User();
$form = $this->createForm(UserType::class, $user);
// 2) handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// 3) Encode the password (you could also do this via Doctrine listener)
$password = $passwordEncoder->encodePassword($user, $user->getPlainPassword());
$user->setPassword($password);
//on active par défaut
$user->setIsActive(true);
//$user->addRole("ROLE_ADMIN");
// 4) save the User!
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
// ... do any other work - like sending them an email, etc
// maybe set a "flash" success message for the user
$this->addFlash('success', 'Votre compte à bien été enregistré.');
//return $this->redirectToRoute('login');
}
return $this->render('registration/register.html.twig', ['form' => $form->createView(), 'mainNavRegistration' => true, 'title' => 'Inscription']);
}
}
Dans la foulée, on enchaine sur le controller « /src/Controller/SecurityController.php » avec la page « /login » qui permettra la connexion, cette fois on créer directement le formulaire dans le controller, cela permet de voir une autre manière de faire que pour l’enregistrement.
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends Controller {
/**
* @Route("/login", name="login")
*/
public function login(Request $request, AuthenticationUtils $authenticationUtils) {
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
//
$form = $this->get('form.factory')
->createNamedBuilder(null)
->add('_username', null, ['label' => 'Email'])
->add('_password', \Symfony\Component\Form\Extension\Core\Type\PasswordType::class, ['label' => 'Mot de passe'])
->add('ok', \Symfony\Component\Form\Extension\Core\Type\SubmitType::class, ['label' => 'Ok', 'attr' => ['class' => 'btn-primary btn-block']])
->getForm();
return $this->render('security/login.html.twig', [
'mainNavLogin' => true, 'title' => 'Connexion',
//
'form' => $form->createView(),
'last_username' => $lastUsername,
'error' => $error,
]);
}
}
Tout ce qui concerne la partie « technique » et maintenant en place et fonctionnel. Pour aller jusqu’au bout on va aussi voir la mise en place des templates pour pouvoir tester le tout (avec un joli affichage à l’aide de bootstrap 4). Pour avoir accès à nos route « /register » et « /login » de nos controllers il nous faut créer les 2 templates appelés par ceux-ci. Les 2 sont très simples et assez proches.
« /templates/registration/register.html.twig »
« /templates/security/login.html.twig »
{% block body %}
{% if error %}
<div class="alert alert-danger">
<ul class="list-unstyled mb-0">
<li><span class="initialism form-error-icon badge badge-danger">Error</span>
<span class="form-error-message">{{ error.messageKey|trans(error.messageData, 'security') }}</span>
</li>
</ul>
</div>
{% endif %}
{{form(form)}}
{% endblock %}
Ces 2 templates dépendent de « base.html.twig », c’est à dire le fichier « /templates/base.html.twig », ci dessous je vous en met un exemple. comme vu précédemment il utilise bootstrap 4. Pour aller jusqu’au bout j’ai inclus ici un menu vers différente page de l’application : les page d’inscription/connnexion ou de déconnexion si on est connecté. Ainsi qu’une page d’accueil, et un espace membre et/ou espace admin en fonction du rôle de l’utilisateur connecté. Pour que tout fonctionne il faudra donc créer les controllers pour ces 3 pages ainsi que leur vues, on voit ça juste après, à la fin de l’article.
<html lang="{{ app.request.locale }}">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>
{% block title %}
{% if title is defined %}{{title}}{% else %}Title{% endif %} | Nom du site
{% endblock %}
</title>
{% block stylesheets %}
{# bootstrap #}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
{# custom #}
<link rel="stylesheet" href="{{ asset('assets/css/styles.css') }}">
{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
</head>
<body>
<body id="{% block body_id %}{% endblock %}">
{% block header %}
<header id="header" class="bck1 border-bottom">
<div class="container">
<h1>{% if title is defined %}{{title}}{% else %}Header{% endif %}</h1>
</div>
</header>
{% endblock %}
{% block nav %}
<nav id="main-nav" class="container navbar navbar-expand-lg navbar-light bg-light border rounded mb-3">
<ul class="navbar-nav">
<li class="nav-item {% if mainNavHome is defined %}active{% endif %}">
<a class="nav-link" href="{{path('app_homepage_index')}}">Accueil</a>
</li>
{% if is_granted('ROLE_USER') %}
<li class="nav-item {% if mainNavMember is defined %}active{% endif %}">
<a class="nav-link" href="{{path('app_member_index')}}">Espace membre</a>
</li>
{% endif %}
{% if is_granted('ROLE_ADMIN') %}
<li class="nav-item {% if mainNavAdmin is defined %}active{% endif %}">
<a class="nav-link" href="{{path('app_admin_homepage_index')}}">Espace admin</a>
</li>
{% endif %}
</ul>
<ul class="navbar-nav ml-auto">
{% if is_granted('ROLE_USER') %}
<li class="nav-item">
<a class="nav-link" href="{{path('logout')}}">Déconnexion</a>
</li>
{% else %}
<li class="nav-item {% if mainNavLogin is defined %}active{% endif %}">
<a class="nav-link" href="{{path('login')}}">Connexion</a>
</li>
<li class="nav-item {% if mainNavRegistration is defined %}active{% endif %}">
<a class="nav-link" href="{{path('app_registration_register')}}">Inscription</a>
</li>
{% endif %}
</ul>
</nav>
{% endblock %}
{% block flash %}
{% for flash_message in app.session.flashbag.get('success') %}
<div class="container alert alert-success" role="alert">
{{ flash_message }}
</div>
{% endfor %}
{% for flash_message in app.session.flashbag.get('info') %}
<div class="container alert alert-info" role="alert">
{{ flash_message }}
</div>
{% endfor %}
{% for flash_message in app.session.flashbag.get('warning') %}
<div class="container alert alert-warning" role="alert">
{{ flash_message }}
</div>
{% endfor %}
{% for flash_message in app.session.flashbag.get('danger') %}
<div class="container alert alert-danger" role="alert">
{{ flash_message }}
</div>
{% endfor %}
{% endblock %}
<div class="container bck1 padded">
{% block body %}
{% endblock %}
</div>
{% block footer %}
<footer id="footer" class="bck1 border-top">
<div class="container">
<h4>Footer</h4>
</div>
</footer>
{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>
Le layout présenté ci-dessus inclus en plus de bootstrap un fichier css custom permettant d’ajouter nos propres classe de présentation. Voici les quelques lignes ajouté pour ma part dans « /public/assets/css/styles.css »
body{background: #ebeff2;}
.bck1{background: #fff;}
/*generique*/
.padded{padding: 15px;}
/*header*/
header#header {margin-bottom: 20px;padding: 10px;}
header#header h1 {text-align: center;color: #5cb85c;}
/*footer*/
footer#footer{margin-top: 20px;padding: 10px;}
Et pour que nos formulaires s’affichent en suivant les conventions de bootstrap 4 on remercie symfony et sa communauté, une seule ligne de configuration suffit ! Dans « /config/packages/twig.yaml » :
form_themes: ['bootstrap_4_layout.html.twig']
Pour la page d’accueil le simple controller « /src/Controller/HomepageController.php » suffira :
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
class HomepageController extends Controller {
/**
* @Route("/")
*/
public function index() {
return $this->render('homepage/index.html.twig', ['mainNavHome'=>true, 'title'=>'Accueil']);
}
}
Rien de spécial pour la vue il suffit de créer le fichier correspandant « /templates/homepage/index.html.twig » de la même façon qu’on l’a fait pour « inscription » et « login », avec le contenu que l’on souhaite.
Le dernier points à voir, c’est la création des « espace membre » et « espace administrateur » limité selon les rôles de l’utilisateur. Il suffit pour cela, en accord avec la configuration faite dans « /config/packages/security.yaml » de faire commencer les routes par « /member » ou « /admin » selon ce que l’on souhaite. Voici pour l’espace utilisateur (fichier « /src/Controller/MemberController.php ») :
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
/** @Route("/member") */
class MemberController extends Controller {
/**
* @Route("/")
*/
public function index() {
return $this->render('member/index.html.twig', ['mainNavMember'=>true, 'title'=>'Espace Membre']);
}
}
Exactement pareil pour l’admin, sauf que dans un soucis d’organisation je place le fichier dans un dossier admin, ce qui donne « src/Controller/Admin/HomepageController.php : «
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
/** @Route("/admin") */
class HomepageController extends Controller {
/**
* @Route("/")
*/
public function index() {
return $this->render('admin/homepage/index.html.twig', ['mainNavAdmin' => true, 'title' => 'Espace Admin']);
}
}
Je ne rajoute pas le code des « views » car rien de particulier et donc même processus que pour la page d’accueil.
C’est terminé pour ce long article à réutiliser à souhait lors du démarrage d’un projet symfony 4
salu frere merci pour le partage mais j’ai un souci quand j’ai taper la commande php bin/console doctrine:migration:migrate sa maffiche cette erreur
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
2018-06-08T11:22:29+02:00 [error] Error thrown while running command « »doctrine:migration:migrate » ». Message: « An exception occurred while executing ‘CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(255) NOT NULL, password VARCHAR(64) NOT NULL, is_active TINYINT(1) NOT NULL, roles LONGTEXT NOT NULL COMMENT ‘(DC2Type:array)’, UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB’:
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes »
votre aide m sera utile svp
Version de MySQL =>5.7 ou MariaDB=>10.2
J’ai eu le même souci, c’est lié à l’encodage j’ai remplacer par « DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB »par « DEFAULT CHARACTER SET utf8 ENGINE = InnoDB ».
C’est lié au faite que l’encodage utf8md4 prends plus d’octets dans pour un caractère donc ce la dépasse la limitation.
Cet article en parle mieux que moi.
https://code.i-harness.com/fr/q/1bb004
Moi aussi j’ai le même souci et je voulais savoir dans quel fichier doit on changer ça ?
Hello pour ma part je l’ai changé dans le fichier de migration
généré par symfony
Hello, pour ma part je l’ai changé dans le fichier de migration généré par symfony une fois la commande…:diff est effectué.
Bonjour, moi j’aimerai bien qu’à part les rôle admin et user, il y aurait 2 autres types de user , etudiant et prof , etudiant (avec une propriété spécial level) prof avec un propriété spécial( account) ces 2 classes sont relié à d’autre entité comme cours, par des relations bi-directionnelles one-to-many pour prof, et many-to-one pour course, je suis trop embétée avec l’héritage pour faire la relation entre cours et etudiant, cours et professeur, j’ai fais de user un classMap, si quelqu’un a une idée merci
Bonjour
Est ce qu’on peut regrouper les rôles dans une table groupe, genre assigner aux utilisateurs un groupe qui contient des rôles
Bonjour, et merci pour ce tuto.
Je débute sur Symfony et je galère un peu.
Tout fonctionne correctement sauf lorsque j’essaie de me logguer et que le nom d’utilisateur et le mot de passe ne sont pas dans la base: Invalid credentials.
UNe idée?
Bonjour, cela veut dire que les identifiants ne sont pas corrects, ce qui est normal si tu utilise des identifiants invalides.
bonjour
bon je voulais savoir pourquoi à chaque fois qu’on met /admin on acces denied
Car dans la configuration du fichier « security.yaml » on à indiqué que les url commençant par admin sont limités au utilisateurs ayant le rôle admin.
Pour créer un utilisateur ayant le role admin il suffit de dé-commenter la ligne « //$user->addRole(« ROLE_ADMIN »); » dans la fonction « registerAction »
ok je vois
bonjour je viens de dé-commenter la ligne « //$user->addRole(« ROLE_ADMIN »); » mais j’ai toujours acces denied
merci beaucoup le problème est réglé merci encore une fois
Que faut-il faire pour le /admin fonctionne?
à partir de là comment on peut gérer la session?
comment je peux faire pour démarrer une session et détruire la session ?
La session est déjà gérer par smyfony, pour plus d’informations se référer à la documentation : https://symfony.com/doc/current/components/http_foundation/sessions.html
Bonjour, j’ai deux problèmes.
Tout d’abord lorsque je veux créer un utilisateur, je n’ai pas le message « Votre compte à bien été enregistré. » en gros l’utilisateur n’a pas été crée apparemment. Seulement lorsque j’essaye de recréer un compte avec la même adresse mail on me dit que cette adresse mail est déjà utilisée donc peut être que ça a marché, dans tout les cas je n’ai pas le message de succès…
De plus, j’ai un petit soucis sur les controllers, sans doute a cause des versions de Symfony : « User Deprecated: The « Symfony\Bundle\FrameworkBundle\Controller\Controller » class is deprecated since Symfony 4.2, use Symfony\Bundle\FrameworkBundle\Controller\AbstractController instead. »
Merci, pour ce tutoriel qui reste tout de même très clair!
Non ce n’est pas en rapport avec les éléments « deprecated » (qui poseront problème à partir de la version 5.0 de Symfony.
Comme tu l’indique, l’enregistrement semble fonctionné (il suffit de vérifier si l’utilisateur est crée dans ta base de données) c’est simplement l’affichage de la réussite qui ne fonctionne pas. As tu bien mis le code correspondant dans tes templates ? Ce qu’il y’a dans le « {% block flash %} » de base.htm.twig
Comment faire pour changer la redirection par défaut, quand je suis sur /login et que je me connecte, je souhaite vérifier si on est admin ou pas pour rediriger sur des endroits différents.
Bonjour, c’est intéressant ce que vous avez publier merci beaucoup.
Je suis débutante en Symfony j’ai installé la dernière version et je veux créer un espace Admin qui peux gérer la partie gestion de l’application et un espace client qui peux s’inscrire ,voir les produits,ajouter un produit dans le panier.
Ma question est : Entre la classe client et la classe user, est ce qu’il aura un héritage? parce que à l’inscription d’un client ça crée son compte directement.
Merci d’avance.
Il y’a plusieurs façons de faire, mais pour moi la classe « User » peux représenter tous les utilisateurs, autant les client que les admin, c’est leur « role » qui permet de définir les différents droits.
Merci pour votre réponse 🙂
En fait, moi je ne comprends pas comment je peut à partir d’un formulaire d’inscription qui contient le: Nom client , Prenom Client, Email Client , Adresse, ville , code postale , année de naissance … liée son compte de connexion!!!!. Je galère sur cette partie.
Comment à partir d’un seul formulaire d’inscription qui contient toutes les informations d’un client on crée le compte de connexion???
Merci d’avance 🙂
C’est précisément ce qu’explique cette article. Il y’a l’exemple de la class user et du formulaire d’inscription avec email/password, il suffit d’ajouter des propriétés (nom, prénom…) à cette classe et de les utiliser dans le formulaire d’inscription pour que tout fonctionne.
Je vous remercie 🙂
Bonjour,
la classe User\UserInterface n’existe pas dans mon projet, faut il utiliser composer ?
Pour ceux qui cherchent: je me suis posé la même question et la réponse est OUI. On peut trouver la réponse facilement sur le net mais ce message devrait vous rendre la tache encore plus facile.
Si vous avez le message d’erreur suivant:
Attempted to load interface « UserInterface » from namespace « Symfony\Compone
nt\Security\Core\User ».
Il faut installer security-bundle:
composer require symfony/security-bundle
Voir: https://symfony.com/doc/4.0/security/entity_provider.html
Si vous avez le message suivant:
Attempted to load class « Constraint » from namespace « Symfony\Component\Vali
dator ».
Il faut installer symfony/validator:
composer require symfony/validator
Voir: https://symfony.com/doc/current/components/validator.html
Bonsoir, lors de l’exécution de la commande » php bin/console doctrine:migration:diff » j’ai obtenu cette erreur « In NoMappingFound.php line 13:
No mapping information to process » comment pourrais-je la resoudre svp
J’ai lu votre cours et c’est vraiment hyper bien fait, ce pendant jai 2 soucis:
1- envoyer un mail à l’utilisateur pour confirmer son email
2- permettre à l’utilisateur de modifier son informations
NB: Je suis debutant sur symfony.
Merci
Bonjour, merci pour ce tuto,
J’ai mis en place une durée de vie de session dans le framework.yaml en mettant « cookie_lifetime à 300 » (secondes) pour déconnecter un utilisateur inactif, mais j aimerai aussi afficher un message (flash?) pour le notifier de cette deconnexion. Est-ce possible ? et si oui comment?
Merci
bonjour jaimerais creer deux autres roles en dehors du role_admi et user, mais qui sont nean,oins des users
Ping : Symfony Connexion - ConnexionGuide.Com
Ping : Symfony Connexion Base De Données - ConnexionGuide.Com