Tutorial para instalar FOSUserBundle en Symfony4
Introducción
En este artículo describiré mi experiencia personal instalando FOSUserBundle en Symfony4 para realizar el control de usuarios de una forma sencilla.
Intentaré describir los principales problemas que he encontrado en la instalacion y describiré la forma de solucionarlos.
Advertencia: Los cambios y modificaciones de los archivos de configuración de Symfony son propuestos por mi en base a mi propia experiencia personal, son dados a modo de recomendación, pero queda en responsabilidad de cada uno aplicarlos a su propio criterio y bajo su responsabilidad en los sitios que ustedes administren, en especial aquellos sitios que se encuentren en un servidor de producción.
Requisitos
Lo primero es instalar las dependencias:
Twig
$ composer require twig
Doctrine
Los usuarios de nuestro sitio se encontrarán en una base de datos (mysql), por tanto hay que crear la base de datos primero.
Este paso es opcional, si ya tienes correctamente configurado Doctrine para comunicarse con tu base de datos puedes pasar al siguiente paso.
Creación de la base de datos
Para crear la base de datos, tenemos que indicar donde estará ubicada, para ello modificamos el archivo /App/.env y configuramos lo siguiente
###> doctrine/doctrine-bundle ### ... DATABASE_URL=mysql://usuariodb:clave@127.0.0.1:3306/dbname ...
donde debemos reemplazar los siguientes valores por los nuestros propios:
- usuariodb: Usuario de la base de datos
- clave: Contraseña del usuario de base de datos
- dbname: Nombre de la base de datos
Luego de eso, procedemos a la creacion de la base de datos con el siguiente comando:
$ php bin/console doctrine:database:create Created database `dbname` for connection named default
Instalar FOSUserBundle
La instalación de FOSUserBundle se hace mediante composer:
$ composer require friendsofsymfony/user-bundle "~2.0"
Sin embargo al tratar de instalar nos encontraremos con el siguiente error:
The child node "db_driver" at path "fos_user" must be configured.
El mensaje nos indica que debemos configurar la sección “fos_user” de los archivos de configuración de Symfony4.
Lo que haremos será crear un archivo de configuración en la ruta App/config/packages/fos.yaml con el siguiente contenido
# App/config/packages/fos.yaml fos_user: db_driver: orm # other valid values are 'mongodb' and 'couchdb' firewall_name: main user_class: App\Entity\Usuario from_email: address: "mailer@yourdomain.com" sender_name: "John Doe"
Al intentar volver a realizar la instalación nos encontramos con un nuevo mensaje de error:
The service "fos_user.resetting.controller" has a dependency on a non-existent service "templating"
Para resolver dicho mensaje, agregaremos las siguientes lineas al archivo que acabamos de crear App/config/packages/fos.yaml:
# App/config/packages/fos.yaml framework: templating: engines: ['twig']
luego de eso pueden intentar volver a instalar FOSUserBundle mediante composer:
$ composer require friendsofsymfony/user-bundle "~2.0" ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Nothing to install or update Generating autoload files ocramius/package-versions: Generating version class... ocramius/package-versions: ...done generating version class Executing script cache:clear [OK] Executing script assets:install --symlink --relative public [OK]
Listo!, ya tienen FOSUserBundle instalado.
Configuración de FOSUserBundle
Una vez instalado FOSUserBundle lo siguiente será configurarlo:
Configurar la clase de usuario
Ahora vamos a crear la clase que controlará los usuarios, la crearemos mediante Doctrine:
$ php bin/console make:entity Class name of the entity to create or update (e.g. GrumpyPizza): > Usuario created: src/Entity/Usuario.php created: src/Repository/UsuarioRepository.php Entity generated! Now let's add some fields! You can always add more fields later manually or by re-running this command. New property name (press <return> to stop adding fields): > nombre Field type (enter ? to see all types) [string]: > Field length [255]: > Can this field be null in the database (nullable) (yes/no) [no]: > yes updated: src/Entity/Usuario.php Add another property? Enter the property name (or press <return> to stop adding fields): > Success! Next: When you're ready, create a migration with make:migration
Ahora debemos personalizar la clase que acabamos de crear App/Src/Entity/usuario.php
<?php namespace App\Entity; use FOS\UserBundle\Model\User as BaseUser; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass="App\Repository\UsuarioRepository") */ class Usuario extends BaseUser { /** * @ORM\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer") */ protected $id; /** * @ORM\Column(type="string", length=255, nullable=true) */ private $nombre; public function getId() { return $this->id; } public function getNombre(): ?string { return $this->nombre; } public function setNombre(?string $nombre): self { $this->nombre = $nombre; return $this; } public function __construct() { parent::__construct(); // your own logic } }
Importante: La clase Usuario debe ser heredada de BaseUser, asimismo la clase Usuario debe ser la misma declarada en el archivo App/config/packages/fos.yaml mediante la etiqueta user_class: App\Entity\Usuario como se ha hecho anteriormente.
Importante: El campo $id debe ser declarado protected, de lo contrario encontraremos el siguiente error:
Compile Error: Access level to App\Entity\Usuario::$id must be protected (as in class FOS\UserBundle \Model\User) or weaker
Importante: Notar que el campo $nombre ha sido declarado nullable=true
Luego de eso actualizaremos el esquema de la base de datos usando Doctrine:
$ php bin/console doctrine:schema:update --force
Seguridad
Lo siguiente es configurar los accesos de la aplicación, esto se hace modificando el archivo App/config/packages/security.yaml
security: encoders: FOS\UserBundle\Model\UserInterface: bcrypt role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: ROLE_ADMIN providers: fos_userbundle: id: fos_user.user_provider.username firewalls: main: pattern: ^/ form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager logout: true anonymous: true access_control: - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin/, role: ROLE_ADMIN }
Ruteo
Se tiene que especificar cuales son las rutas que utilizará FOSUserBundle para las distintas páginas que contiene, para ello modificaremos el archivo App/config/routes.yaml
# App/config/routes.yaml fos_user: resource: "@FOSUserBundle/Resources/config/routing/all.xml"
Traducción
Para utilizar los mensajes por defecto del bundle se debe agregar las siguientes lineas en nuestro archivo de configuración App/config/packages/fos.yaml
#App/config/packages/fos.yaml framework: translator: ~
Para fijar el idioma español debemos configurar lo siguiente en el archivo /App/config/package/traslation.yaml
#App/config/packages/traslation.yaml framework: default_locale: 'es'
Comentarios finales
Habiendo configurado todo lo anterior ya podemos ejecutar nuestro sitio para registrar un usuario.
$ php bin/console server:run [OK] Server listening on http://127.0.0.1:8000
Para crear nuevos usuarios en nuestro sitio lo podemos hacer en la siguiente ruta:
http://127.0.0.1:8000/register
Y para iniciar sesión en el sitio debemos ir a la siguiente dirección:
http://127.0.0.1:8000/login
Hello world!