Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Personalizar la clase de usuario

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Lo bueno de la clase User es que... ¡es nuestra clase! Mientras implementemosUserInterface, podemos añadir lo que queramos:

... lines 1 - 7
use Symfony\Component\Security\Core\User\UserInterface;
... lines 9 - 12
class User implements UserInterface
{
... lines 15 - 113
}

Por ejemplo, me gustaría almacenar el nombre de mis usuarios. Así que vamos a añadir una propiedad para eso. En tu terminal, ejecuta:

symfony console make:entity

Editaremos la entidad User, añadiremos una propiedad firstName, haremos que sea una cadena, de 255 de longitud... y diremos "sí" a anulable. Hagamos que esta propiedad sea opcional en la base de datos.

Ya está De vuelta a la clase User, ¡no hay sorpresas! Tenemos una nueva propiedad... y nuevos métodos getter y setter:

... lines 1 - 12
class User implements UserInterface
{
... lines 15 - 31
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $firstName;
... lines 36 - 119
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
}

Ve a generar una migración para nuestro nuevo User. En el terminal, ejecuta

symfony console make:migration

¡Genial! Gira y abre eso para asegurarte de que no esconde ninguna sorpresa:

... lines 1 - 2
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20211001172813 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(180) NOT NULL, roles JSON NOT NULL, first_name VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE user');
}
}

Ejecuta: CREATE TABLE user con las columnas id, email, roles y first_name. Cierra esto... y ejecútalo:

symfony console doctrine:migrations:migrate

¡Éxito!

Añadiendo las entidades de los usuarios

Y como la entidad User es... una entidad normal de Doctrine, también podemos añadir usuarios ficticios a nuestra base de datos utilizando el sistema de accesorios.

Abre src/DataFixtures/AppFixtures.php. Vamos a utilizar Foundry para ayudarnos a cargar los datos. Así que vamos a crear una nueva fábrica de Foundry para User. Como nos estamos divirtiendo tanto ejecutando comandos en este vídeo, vamos a colar uno... o tres más:

symfony console make:factory

¡Sí! Queremos una para User. Ve a abrirlo: src/Factory/UserFactory.php:

... lines 1 - 2
namespace App\Factory;
use App\Entity\User;
use App\Repository\UserRepository;
use Zenstruck\Foundry\RepositoryProxy;
use Zenstruck\Foundry\ModelFactory;
use Zenstruck\Foundry\Proxy;
... lines 10 - 28
final class UserFactory extends ModelFactory
{
public function __construct()
{
parent::__construct();
// TODO inject services if required (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services)
}
protected function getDefaults(): array
{
return [
// TODO add your default values here (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories)
'email' => self::faker()->text(),
'roles' => [],
'firstName' => self::faker()->text(),
];
}
protected function initialize(): self
{
// see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
return $this
// ->afterInstantiate(function(User $user) {})
;
}
protected static function getClass(): string
{
return User::class;
}
}

Nuestro trabajo en getDefaults() es asegurarnos de que todas las propiedades necesarias tienen buenos valores por defecto. Establece email en self::faker()->email(), no estableceré ninguna función por ahora y establece firstName en self::faker()->firstName():

... lines 1 - 28
final class UserFactory extends ModelFactory
{
... lines 31 - 37
protected function getDefaults(): array
{
return [
'email' => self::faker()->email(),
'firstName' => self::faker()->firstName(),
];
}
... lines 45 - 57
}

¡Genial! En AppFixtures, en la parte inferior, crea un usuario: UserFactory::createOne(). Pero utiliza un correo electrónico específico para que podamos iniciar sesión con él más tarde. Qué tal,abraca_admin@example.com:

... lines 1 - 11
use App\Factory\UserFactory;
... lines 13 - 15
class AppFixtures extends Fixture
{
public function load(ObjectManager $manager)
{
... lines 20 - 41
AnswerFactory::new(function() use ($questions) {
... lines 43 - 45
})->needsApproval()->many(20)->create();
UserFactory::createOne(['email' => 'abraca_admin@example.com']);
... lines 49 - 51
}
}

Luego, para rellenar un poco el sistema, añade UserFactory::createMany(10):

... lines 1 - 11
use App\Factory\UserFactory;
... lines 13 - 15
class AppFixtures extends Fixture
{
public function load(ObjectManager $manager)
{
... lines 20 - 47
UserFactory::createOne(['email' => 'abraca_admin@example.com']);
UserFactory::createMany(10);
... lines 50 - 51
}
}

¡Vamos a probarlo! De vuelta al terminal, ejecuta:

symfony console doctrine:fixtures:load

¡No hay errores! Comprueba la nueva tabla:

symfony console doctrine:query:sql 'SELECT * FROM user'

Y... ¡ahí están! Ahora que tenemos usuarios en la base de datos, tenemos que añadir una o varias formas para que se autentiquen. ¡Es hora de construir un formulario de acceso!

Leave a comment!

¡Este tutorial también funciona muy bien para Symfony 6!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.4.1 || ^8.0.0",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "babdev/pagerfanta-bundle": "^3.3", // v3.3.0
        "composer/package-versions-deprecated": "^1.11", // 1.11.99.4
        "doctrine/annotations": "^1.0", // 1.13.2
        "doctrine/doctrine-bundle": "^2.1", // 2.6.3
        "doctrine/doctrine-migrations-bundle": "^3.0", // 3.1.1
        "doctrine/orm": "^2.7", // 2.10.1
        "knplabs/knp-markdown-bundle": "^1.8", // 1.9.0
        "knplabs/knp-time-bundle": "^1.11", // v1.16.1
        "pagerfanta/doctrine-orm-adapter": "^3.3", // v3.3.0
        "pagerfanta/twig": "^3.3", // v3.3.0
        "phpdocumentor/reflection-docblock": "^5.2", // 5.2.2
        "scheb/2fa-bundle": "^5.12", // v5.12.1
        "scheb/2fa-qr-code": "^5.12", // v5.12.1
        "scheb/2fa-totp": "^5.12", // v5.12.1
        "sensio/framework-extra-bundle": "^6.0", // v6.2.0
        "stof/doctrine-extensions-bundle": "^1.4", // v1.6.0
        "symfony/asset": "5.3.*", // v5.3.4
        "symfony/console": "5.3.*", // v5.3.7
        "symfony/dotenv": "5.3.*", // v5.3.8
        "symfony/flex": "^1.3.1", // v1.17.5
        "symfony/form": "5.3.*", // v5.3.8
        "symfony/framework-bundle": "5.3.*", // v5.3.8
        "symfony/monolog-bundle": "^3.0", // v3.7.0
        "symfony/property-access": "5.3.*", // v5.3.8
        "symfony/property-info": "5.3.*", // v5.3.8
        "symfony/rate-limiter": "5.3.*", // v5.3.4
        "symfony/runtime": "5.3.*", // v5.3.4
        "symfony/security-bundle": "5.3.*", // v5.3.8
        "symfony/serializer": "5.3.*", // v5.3.8
        "symfony/stopwatch": "5.3.*", // v5.3.4
        "symfony/twig-bundle": "5.3.*", // v5.3.4
        "symfony/ux-chartjs": "^1.3", // v1.3.0
        "symfony/validator": "5.3.*", // v5.3.8
        "symfony/webpack-encore-bundle": "^1.7", // v1.12.0
        "symfony/yaml": "5.3.*", // v5.3.6
        "symfonycasts/verify-email-bundle": "^1.5", // v1.5.0
        "twig/extra-bundle": "^2.12|^3.0", // v3.3.3
        "twig/string-extra": "^3.3", // v3.3.3
        "twig/twig": "^2.12|^3.0" // v3.3.3
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.3", // 3.4.0
        "symfony/debug-bundle": "5.3.*", // v5.3.4
        "symfony/maker-bundle": "^1.15", // v1.34.0
        "symfony/var-dumper": "5.3.*", // v5.3.8
        "symfony/web-profiler-bundle": "5.3.*", // v5.3.8
        "zenstruck/foundry": "^1.1" // v1.13.3
    }
}