у зарегистрированного пользователя заполнены не все поля

#php #symfony #session #doctrine-orm #logged

#php #symfony #сеанс #doctrine-orm

Вопрос:

Я использую Symfony 2.8 и Doctrine, и у меня есть security.yml, настроенный так, чтобы указывать на класс User, который реализует UserInterface. Моя схема ORM находится в YAML.

Проблема:

  • В базе данных пользователь также указал поле «email», Symfony для ЗАРЕГИСТРИРОВАННОГО ПОЛЬЗОВАТЕЛЯ не заполняет это поле, а также поле «пароль» пустое.

скриншот

Когда я это делаю $this->get('doctrine.orm.entity_manager')->clear(User::class); , диспетчер объектов правильно выбирает объект. Но когда объект ВЫХОДИТ ИЗ СЕАНСА, это неверно.

Проблема также в том, что когда я пытаюсь извлечь новый объект из базы данных с помощью find() в репозитории, тогда извлекается неправильный элемент из сеанса, когда я не буду использовать $em->clear(User::class)

Как сообщить Symfony / Doctrine создать мою сущность таким образом, чтобы все поля были заполнены, поэтому она станет постоянной?

 <?php

namespace XXXAppBundleModelEntity;

use XXXAppBundleModelEntityServerLogging;
use DoctrineORMMapping as ORM;
use SymfonyComponentSecurityCoreUserUserInterface;

/**
 * User
 */
class User implements UserInterface
{
    /**
     * @var integer $id
     */
    protected $id;

    /**
     * @var string $username
     */
    protected $username;

    /**
     * @var string $email
     */
    protected $email;

    /**
     * @var string $password
     */
    protected $password;

    /**
     * @var array $roles
     */
    protected $roles = array();

    /**
     * @var DoctrineCommonCollectionsCollection $logEvents
     */
    protected $logEvents;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * {@inheritdoc}
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * @param string $username
     * @return $this
     */
    public function setUsername($username)
    {
        $this->username = $username;
        return $this;
    }

    /**
     * @return string
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * @param string $email
     * @return $this
     */
    public function setEmail($email)
    {
        $this->email = $email;
        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * @param string $password
     * @return $this
     */
    public function setPassword($password)
    {
        $this->password = $password;
        return $this;
    }

    /**
     * Returns the roles or permissions granted to the user for security.
     */
    public function getRoles()
    {
        $roles = $this->roles;

        // guarantees that a user always has at least one role for security
        if (empty($roles)) {
            $roles[] = 'ROLE_USER';
        }

        return array_unique($roles);
    }

    public function setRoles(array $roles)
    {
        $this->roles = $roles;
    }

    /**
     * Returns the salt that was originally used to encode the password.
     */
    public function getSalt()
    {
        // See "Do you need to use a Salt?" at http://symfony.com/doc/current/cookbook/security/entity_provider.html
        // we're using bcrypt in security.yml to encode the password, so
        // the salt value is built-in and you don't have to generate one

        return;
    }

    /**
     * Removes sensitive data from the user.
     */
    public function eraseCredentials()
    {
        $this->password = null;
        $this->email    = null;
    }

    /**
     * Appends an entry to administration log
     *
     * @param XXXAppBundleModelEntityServerLogging $logEvent
     * @return $this
     */
    public function appendLog(ServerLogging $logEvent)
    {
        if (!$this->logEvents->contains($logEvent))
        {
            $this->logEvents->add($logEvent);
        }

        return $this;
    }

    /**
     * Remove a log entry from the history
     *
     * @param XXXAppBundleModelEntityServerLogging $logEvent
     * @return $this
     */
    public function clearLogEntry(ServerLogging $logEvent)
    {
        $this->logEvents->removeElement($logEvent);

        return $this;
    }
}
 

И конфигурация ORM:

 XXXAppBundleModelEntityUser:
    type: entity
    table: users
    repositoryClass: XXXAppBundleModelRepositoryUserRepository
    id:
        id:
            type: integer
            scale: 0
            length: null
            unique: false
            nullable: false
            precision: 0
            id: true
            generator:
                strategy: IDENTITY
    fields:
        username:
            type: string
            scale: 0
            length: null
            unique: true
            nullable: false
            precision: 0
        email:
            type: string
            scale: 0
            length: null
            unique: true
            nullable: false
            precision: 0
        password:
            type: string
            scale: 0
            length: null
            unique: false
            nullable: false
            precision: 0
        roles:
            type: json_array
            scale: 0
            length: null
            unique: false
            nullable: false
            precision: 0
    oneToMany:
        logEvents:
            targetEntity: XXXAppBundleModelEntityServerLogging
            cascade:
                - remove
                - persist
            fetch: LAZY
            mappedBy: author
            inversedBy: null
            orphanRemoval: false
            orderBy: null
    lifecycleCallbacks: {  }
 

Комментарии:

1. Как вы извлекаете своего пользователя из сеанса, каков код в вашем классе User?

2. Да, я извлекаю пользователя из сеанса. В классе user я только что защитил частные свойства геттеры. И файл ORM yml выглядит нормально, как и в других объектах.

3. Пожалуйста, отправьте код.

4.pastebin.com/CNQf8dCd pastebin.com/VkyRDHXx Спасибо вам!

Ответ №1:

Вы реализовали метод UserInterface::eraseCredentials() таким образом, что он отключает адрес электронной почты и пароль:

 public function eraseCredentials()
{
    $this->password = null;
    $this->email    = null;
}
 

Symfony вызовет этот метод перед сериализацией объекта, чтобы сохранить его в сеансе.

UserInterface::eraseCredentials() предназначен для удаления конфиденциальных данных из объекта user, чтобы они не попали, например, в файлы сеанса, но нет реальной необходимости удалять электронное письмо, как вы делаете. Лучшим примером может быть, если вы храните текстовую версию пароля пользователя где-нибудь на этом объекте, это то, что вы никогда не хотели бы видеть в файлах сеанса.

Комментарии:

1. Спасибо. Я не удаляю имя пользователя, а просто пароль и адрес электронной почты 🙂

2. Как реализовать смену пароля или изменение списка ролей при удалении электронной почты или пароля?

3. Правильно, но именно поэтому электронное письмо отсутствует при извлечении из сеанса.

4. Не уверен, что вы имеете в виду под этим вопросом @KrzysztofaKrzysztof

5. Хорошо, в любом случае спасибо. Вероятно, мне придется отключить зарегистрированного пользователя в форме редактирования пароля и работать с новым объектом из базы данных.