دورة SYMFONY 4 للمبتدئين الدرس الثالت عشر


فهاد الدرس الثالت عشر من دورة symfony للمبتدئين غادي نشوفوا حاجة مهمة لي هي connexion ول inscription أول حاجة غادي نشوفوا كيفاش نزيدو مستخدم فقاعدة البيانات من بعد عاد غادي نشوفوا كيفاش نديرو la connexion.


1- إضافة ل Entity User

كيف شفنا قبل باش نزيد table فقاعدة البيانات لازمني منزيد Entity لي غادي تمكني من هادشي كنمشي ل dossier Entity كنزيد fichier جديد سميه User.php فيه كنزيد les champs ديال table مع ل validation ديالهم كيف شفنا قبل فل article.

الجديد هنا هو كنخدم ب class سميتها UserInterface لي كتمكني من استخدام des fonctions منهم getRoles لي كترجعلي الدور ديال المستخدم ولي par défaut كيكون مستخدم عادي.

هاد ل classe ضروري متخدم بها وكاين أيضا Serializable لي كتمكن من تخزين المعلومات ف session واسترجاعها كل مرة حول يتكونيكطا.

الكود ديال الملف User.php هو :

                                //
<?php

namespace App\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;


/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @UniqueEntity(fields="email",message="cet email est déja utilisé!")
 * @UniqueEntity(fields="username",message="ce pseudo est déja utilisé!")
 */
class User implements UserInterface,\Serializable
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=50,unique=true)
     * @Assert\NotBlank()
     * @Assert\Length(min=5,max=50)
     */
    private $username;

    /**
     * @ORM\Column(type="string", length=191)
     */
    private $password;

     /**
     * @Assert\NotBlank()
     * @Assert\Length(min=5,max=4096)
     */
    private $plainPassword;

    /**
     * @Assert\NotBlank()
     * @ORM\Column(type="string", length=191 ,unique=true)
     * @Assert\Email()
     */
    private $email;

    /**
     * @Assert\NotBlank()
     * @ORM\Column(type="string", length=191)
     * @Assert\Length(min=5,max=50)
     */
    private $fullname;


    public function getId(): ?int
    {
        return $this->id;
    }

    public function getUsername(): ?string
    {
        return $this->username;
    }

    public function setUsername(string $username): self
    {
        $this->username = $username;

        return $this;
    }
    public function getPlainPassword(): ?string
    {
        return $this->plainPassword;
    }

    public function setPlainPassword(string $plainPassword): self
    {
        $this->plainPassword = $plainPassword;

        return $this;
    }

    public function getPassword(): ?string
    {
        return $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    public function getFullname(): ?string
    {
        return $this->fullname;
    }

    public function setFullname(string $fullname): self
    {
        $this->fullname = $fullname;

        return $this;
    }
    public function getSalt()
    {
        return null;
    }
    public function eraseCredentials()
    {
        return null;
    }
    public function getRoles()
    {
        return ['ROLE_USER'];
    }
    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->password,
        ));
    }
    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->username,
            $this->password,
        ) = unserialize($serialized);
    }
}
                            

2- إضافة table user لقاعدة البيانات

كيف شفنا قبل باش نزيد ل Entity فقاعدة البيانات كنزيد migration جديدة غادي تفتح cmd وغادي تزيد هاد ل commande :

php bin/console make:migration

دبا يلا مشيتي ل dossier src/Migrations غادي تلقى fichier جديد فيه ل migration ديال table user  وغادي يكون فيه هاد الكود :

                                //
<?php

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 Version20190203135540 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->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(50) NOT NULL, password VARCHAR(191) NOT NULL, email VARCHAR(191) NOT NULL, fullname VARCHAR(191) NOT NULL, UNIQUE INDEX UNIQ_8D93D649F85E0677 (username), UNIQUE INDEX UNIQ_8D93D64991657DAE (fullname), 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->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('DROP TABLE user');
    }
}
                            

3- إضافة table user لقاعدة البيانات تتمة

دبا عندي ل migration باش نرسلها لقاعدة البيانات غادي ندير commande :

php bin/console doctrine:migrations:migrate


لي فاش غادي تنفذها غادي تمشي لقاعدة البيانات غادي تلقى فيها table تزادت كيف كتشوف فالصورة :



 منبعد غادي نزيد واحد ل fixture كيف شفنا قبل لي غادي تمكنا من إضافة مستخدم عشوائي فقاعدة البيانات غادي تدير ل commande :

php bin/console make:fixtures  

سميها UserFixture منيعد سير ل dossier Fixtures غادي تلقاها تزادت تما.

عندي نفس الكود لي شفت من قبل باش زدت article فقط هنا خدمت ب class سميتها UserPasswordEncoderInterface لي كتمكن باش ن crypter le mot de passe.

 الكود ديال UserFixture هو :

                                //
<?php

namespace App\DataFixtures;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use App\Entity\User;

class UserFixture extends Fixture
{
    private $passwordEncoder;
    public function __construct(UserPasswordEncoderInterface $passwordEncoder){
        $this->passwordEncoder = $passwordEncoder;
    }
    public function load(ObjectManager $manager)
    {
        $user = new User();
        $user->setUsername('samadi2019');
        $user->setFullname('samadi samir');
        $user->setEmail('samadi@email.com');
        $user->setPassword(
            $this->passwordEncoder->encodePassword(
                $user,'samadi123'
            )
        );
        $manager->persist($user);

        $manager->flush();
    }
}
                            

4- إستعمال security load ف symfony 4

منبعد مازدنا ل fixture غادي تدير هاد ل commande :

 php bin/console doctrine:fixtures:load

دبا لمستخدم تزاد ف table لكن باش نتكونيكطا به خص نخدم ب security load ديال symfony لي كيمكن باش نكونيكطي مستخدم بطريقة آمنة باش نخدم به غادي نفتح cmd ونزيد هاد ل commande :

 composer require symfony/security-bundle


منبعد باش symfony تعرف بلي غادي نخدم ب security load كنمشي ل config/packages/security.yaml تما عندي :

- encoders لي كنعطيها ل Entity User ول bcrypt لي هي خوارزمية كتمكن باش ن crypter le mot de passe.

- ف providers كنعطي ل Entity User ل database_users وكنقول بلي لمستخدم غادي نعرضوا بل username ديالو.

- كنزيد form_login كنعطيها route لي هو security_login وكنزيد token و route لي غادي يمشي ليه المستخدم فاش يتكونيكطا هنا عطيناه hello.

وأيضا route ديال logout لي سميتو security_logout  و route لي غادي يمشي ليه المستخدم فاش يديكونيكطا هنا عطيناه hello.

الكود ديال security.yaml بعد التعديل هو :

                                    //
security:
    #default voter strategy
    access_decision_manager :
        strategy : affirmative
    #set password encrypt mode
    encoders : 
        App\Entity\User: bcrypt
    # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
    providers:
    #set the field that we will use to load users here its username
        database_users:
            entity: {class: App\Entity\User,property: username} 
        #in_memory: { memory: ~ }
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: true
            pattern: ^/
            # activate different ways to authenticate

            # http_basic: true
            # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate

            form_login: 
                check_path : security_login
                login_path : security_login
                csrf_token_generator : security.csrf.token_manager
                default_target_path : hello
            
            logout:
                path: security_logout
                target: hello

    # 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: ^/profile, roles: ROLE_USER }