Вопрос или проблема
У меня есть этот объект
<?php
namespace App\Domain\Entity;
use App\Domain\ValueObject\Email;
use App\Domain\ValueObject\Name;
use App\Domain\ValueObject\Password;
use App\Domain\ValueObject\Surname;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
public function __construct(
private UuidInterface $id,
private Name $name,
private Surname $surname,
private Email $email,
private Password $password,
private array $roles = []
) {}
public function getId(): UuidInterface
{
return $this->id;
}
public function setId(UuidInterface $id): void
{
$this->$id = $id;
}
public function getName(): Name
{
return $this->name;
}
public function setName(Name $name): void
{
$this->name = $name;
}
public function getSurname(): Surname
{
return $this->surname;
}
public function setSurname(Surname $surname): void
{
$this->surname = $surname;
}
public function getEmail(): string
{
return $this->email->value();
}
public function setEmail(String $email): void
{
$this->$email = new Email($email);
}
public function getVOEmail(): Email
{
return $this->email;
}
public function setVOEmail(Email $email): void
{
$this->$email = $email;
}
public function getVOPassword(): Password
{
return $this->password;
}
public function setVOPassword(Password $password): void
{
$this->password = $password;
}
public function getPassword(): ?string
{
return $this->password->value();
}
public function setPassword(string $password): static
{
$this->password = $password;
return $this;
}
/**
* Получить роли, предоставленные пользователю.
*/
public function getRoles(): array
{
// Обеспечить, чтобы у каждого пользователя была хотя бы роль ROLE_USER
if (empty($this->roles)) {
$this->roles[] = 'ROLE_USER';
}
return array_unique($this->roles);
}
/**
* Установить роли для пользователя.
*/
public function setRoles(array $roles): static
{
$this->roles = $roles;
return $this;
}
/**
* Получить идентификатор пользователя (например, email).
*/
public function getUserIdentifier(): string
{
return $this->email->value(); // Или любой другой уникальный идентификатор
}
/**
* Стереть любую конфиденциальную информацию.
*/
public function eraseCredentials(): void
{
// Если есть конфиденциальная информация, которую вы хотите удалить, сделайте это здесь.
// Например, если вы использовали незашифрованный пароль во время аутентификации:
// $this->plainPassword = null; // Или любое другое временное поле.
}
}
сопоставлено следующим образом
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://raw.githubusercontent.com/doctrine/doctrine2/main/doctrine-mapping.xsd">
<!-- Определение сущности -->
<entity name="App\Domain\Entity\User" table="`user`" repository-class="App\Infrastructure\Service\UserRepository">
<!-- Идентификатор (ID) -->
<id name="id" type="uuid" column="id">
<generator strategy="NONE"/> <!-- Мы используем UUID, сгенерированный вручную -->
</id>
<!-- Определение полей -->
<embedded name="email" class="App\Domain\ValueObject\Email" use-column-prefix="false"/>
<embedded name="name" class="App\Domain\ValueObject\Name" use-column-prefix="false"/>
<embedded name="surname" class="App\Domain\ValueObject\Surname" use-column-prefix="false"/>
<embedded name="password" class="App\Domain\ValueObject\Password" use-column-prefix="false"/>
<!-- Определение столбца JSON для ролей -->
<field name="roles" type="json" column="roles"/>
</entity>
</doctrine-mapping>
Email является объектом значения (как и остальные атрибуты), я использовал вложенные классы для атрибутов, я работал над сохранением пользователей в базе данных, но не для входа с использованием LexikJWTAuthenticationBundle
. Проблема в том, что когда я пытаюсь войти как пользователь, я получаю ошибку Unrecognized field: App\Domain\Entity\User::$email
При отладке я обнаружил, что этот код
$this->class->fieldMappings[$field]
не возвращает имена полей, такие как email, name, surname… он возвращает email.value, name.value… так как в классе значение email содержится в переменной, называемой $value
<?php
namespace App\Domain\ValueObject;
class Email
{
public function __construct(private string $value)
{}
public function value(): string
{
return $this->value;
}
}
Я не знаю, как сделать так, чтобы получить name
вместо name.value
когда $this->class->fieldMappings[$field]
вызывается, имя уже задано в XML-файле конфигурации
Ответ или решение
Вопрос, с которым вы столкнулись, касается работы с сущностями и значимыми объектами в Symfony, а именно, проблемы с неправильным определением имен полей при работе с LexikJWTAuthenticationBundle
. Давайте подробно рассмотрим, как можно решить проблему "Unrecognized field: App\Domain\Entity\User::$email" и изменить имена встроенных полей.
Проблема
При попытке аутентификации пользователи сталкиваются с ошибкой, потому что система не распознает поле email
как ожидаемое. Поскольку email
является значимым объектом (Value Object), ваше текущее представление поля с использованием Doctrine как embedded
приводит к тому, что имена полей, возвращаемые Doctrine, выглядят как email.value
вместо простого email
.
Решение
Для решения данной проблемы, вы можете использовать следующие подходы:
1. Изменение конфигурации Doctrine
Попробуйте изменить ваши настройки маппинга, добавив явное указание на имя поля. Возможно, вам нужно будет определить каждое поле вашего значимого объекта отдельно. Например, вы можете задать поля в таких значениях:
<embedded name="email" class="App\Domain\ValueObject\Email" use-column-prefix="false">
<field name="value" type="string" column="email" />
</embedded>
Каждое поле вашего объекта должно быть явно указано в конфигурации Doctrine. Примерно так же вы можете сделать для name
, surname
и password
.
2. Обновление класса Value Object
Если вы решите переименовать поле в своих Value Objects
, используйте более очевидные названия, которые не конфликтуют с другими именами полей объекта User
. Например:
namespace App\Domain\ValueObject;
class Email
{
public function __construct(private string $emailAddress)
{}
public function value(): string
{
return $this->emailAddress;
}
}
Обновите ваши маппинги соответствующим образом.
3. Обновление логики аутентификации
Убедитесь, что ваш код аутентификации правильно настроен для работы с новыми именами полей. Если вы обновляете способ получения идентификатора пользователя, убедитесь, что используете метод getUserIdentifier
, который возвращает корректный адрес электронной почты:
public function getUserIdentifier(): string
{
return $this->email->value(); // Или другое уникальное значение
}
4. Отладка конфигурации
При отладке проверьте, используют ли все компоненты вашего приложения актуальные имена полей. Включите логи Doctrine для выявления конфигурации и убедитесь, что все маппинги отражают последние изменения.
Заключение
Изменение имен в значимых объектах и их правильное маппирование в Doctrine поможет избежать проблемы с распознаванием полей. Обязательно обновите всю логику взаимодействия с вашими объектами, чтобы соответствовать новой конфигурации. Также важно тестировать аутентификацию после внесения всех изменений, чтобы убедиться, что система работает как ожидается.
Следуя этим шагам, вы можете устранить проблему с ошибкой "Unrecognized field" и корректно настроить вашу систему аутентификации на основе JWT в Symfony.