更改 symfony 上的嵌入字段名称以避免无法识别的字段:App\Domain\Entity\User::$email 问题

问题描述 投票:0回答:1

我有这个实体

<?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;
    }

    /**
     * Get the roles granted to the user.
     */
    public function getRoles(): array
    {
        // Garantizar que cada usuario tenga al menos el rol ROLE_USER
        if (empty($this->roles)) {
            $this->roles[] = 'ROLE_USER';
        }

        return array_unique($this->roles);
    }

    /**
     * Set the roles for the user.
     */
    public function setRoles(array $roles): static
    {
        $this->roles = $roles;

        return $this;
    }
    /**
     * Get the user identifier (e.g., email).
     */
    public function getUserIdentifier(): string
    {
        return $this->email->value(); // O cualquier otro identificador único
    }

    /**
     * Erase any sensitive information.
     */
    public function eraseCredentials(): void
    {
        // Si hay información sensible que deseas eliminar, hazlo aquí.
        // Por ejemplo, si usaste una contraseña sin encriptar durante la autenticación:
        // $this->plainPassword = null; // O cualquier otro campo temporal.
    }
}

这样映射

<?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">

    <!-- Definición de la entidad -->
    <entity name="App\Domain\Entity\User" table="`user`" repository-class="App\Infrastructure\Service\UserRepository">
        
        <!-- Identificador (ID) -->
        <id name="id" type="uuid" column="id">
            <generator strategy="NONE"/> <!-- Usamos un UUID generado manualmente -->
        </id>

        <!-- Definición de los campos -->
        <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"/>
        
        <!-- Definición de la columna JSON para los roles -->
        <field name="roles" type="json" column="roles"/>
    </entity>
</doctrine-mapping>

和可嵌入映射

<?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">

    <!-- Definición del objeto embebido -->
    <embeddable name="App\Domain\ValueObject\Email">
        <!-- Campo de la clase Email -->
        <field name="value" column="email" type="string" length="255" nullable="false"/>
    </embeddable>
</doctrine-mapping>

电子邮件是一个值对象(与属性上的其余部分一样),我使用了属性的嵌入式类,我的工作是将用户存储在数据库中,但不是使用

LexikJWTAuthenticationBundle
登录,问题是当我尝试登录用户我收到此错误
Unrecognized field: App\Domain\Entity\User::$email

调试发现这段代码

$this->class->fieldMappings[$field]

不会将字段名称重新调整为电子邮件、姓名、姓氏...它会在类中返回 email.value 、name.value...,因为电子邮件值包含在名为

$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 配置文件中设置

php symfony doctrine lexikjwtauthbundle
1个回答
0
投票

将用户名和电子邮件等数据保存为 VO 是非常非标准的方式。如果您放弃这个想法并重构您的实体以将此类数据保存为字符串(您始终可以创建专门的 getter 来设置和获取这些值作为 VO),您将从长远来看受益。

如果

LexikJWTAuthenticationBundle
仅限于使用 ORM 映射来获取这些属性,并且您无法覆盖此行为,那么不幸的是,我没有看到解决方案。作为最后的手段,您可以覆盖捆绑包本身中的这部分代码(如果可能的话,通过使用 symfony DI 覆盖服务),但我也不推荐这样做,因为它可能会导致更糟糕的情况和不可预测的情况未来(不提升级包后的问题)。

最后一件事,如果有办法以某种方式为

LexikJWTAuthenticationBundle
提供属性路径而不是映射字段,您可能可以创建一个单独的 getter (例如
getEmailValue
getNameValue
),并使捆绑包使用
emailValue 
nameValue
属性。但是,同样,这个捆绑包很可能无法开箱即用。

© www.soinside.com 2019 - 2024. All rights reserved.