如何在SF表单中显示用户全名并保存用户ID,而不使用select

时间:2017-05-31 07:50:57

标签: php symfony autocomplete symfony-forms

在symfony项目中,我有一个注册表单,其中我必须显示所选用户。用户来自用户实体。

我需要保存用户ID(在注册实体中我保存UserId),但在表单字段中显示用户全名。 如何管理,没有选择字段?

我的结论是使用

创建自定义字段
  • 非表单标记中的名称(span)
  • 隐藏输入中的ID

但在这种情况下我不知道如何实现它。

我的用户实体:

class User extends BaseUser
{
...
    public function __toString()
    {
        return ($this->lastName . " " . $this->firstName. " [".$this->getId()."]");
    }
}

我的注册实体:

class Registration
{
    /**
     * @var \MyBundle\Entity\User
     *
     * @ORM\ManyToOne(targetEntity="MyBundle\Entity\User")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="userId", referencedColumnName="id")
     * })
     */
    private $user;
...
}

我的第一个明显尝试是将用户字段作为实体放在注册表单中。

class RegistrationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('user', EntityType::class, [
                'label' => 'user.name',
                'attr' => [
                    'class' => 'reguser',
                ],
                'class' => 'MyBundle\Entity\User',
            ]);
    }
}

我有一个显示用户名的选项,id为值。最大的问题是人体工程学:我可能有几千个用户。我无法显示那么大的列表。

所以我想到了一个自动填充字段。

    $builder
        ->add('user', TextType::class, [
            'label' => 'user.name',
            'attr' => [
                'class' => 'reguser userpicker',
            ],
        ]);

这里的问题是多方面的: 在自动填充字段中,我显然显示了名称(最终用户搜索名称,而不是id)但是当我保存时这将是无用的,因为我需要用户ID。

所以我开始玩自动完成js以在额外的范围内显示名称,并用id替换自动完成的值。这是hacky并且不可用,因为当我编辑时,我在文本字段中显示来自User的__toString()值。

1 个答案:

答案 0 :(得分:1)

实现此目标的一种方法是在您的字段中添加DataTransformer

整个文档可用here

<强> 1。创建您的DataTransformer

此类会将您的用户名(字符串)转换为User

namespace AppBundle\Form\DataTransformer;

// your User class :
use AppBundle\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

class  implements DataTransformerInterface
{
    private $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    /**
     * Transforms an object (user) to a string (number).
     *
     * @param  User|null $user
     * @return string
     */
    public function transform($user)
    {
        if (null === $user) {
            return '';
        }

        return (string) $user;
    }

    /**
     * Transforms a string (username) to an object (user).
     *
     * @param  string $username
     * @return User|null
     * @throws TransformationFailedException if object (user) is not found.
     */
    public function reverseTransform($username)
    {
        // no username ? It's optional, so that's ok
        if (!$issueNumber) {
            return;
        }

        $user = $this->em
            ->getRepository('AppBundle:User')
            // query for the issue with this id
            ->findByUsername($username)
        ;

        if (null === $user) {
            // causes a validation error
            // this message is not shown to the user
            // see the invalid_message option
            throw new TransformationFailedException(sprintf(
                'User with username %s not found',
                $username
            ));
        }

        return $user;
    }
}

<强> 2。将您的datatransformer附加到您的类型

您必须使用服务将EntityManager作为参数,或者将UsernameToUserTransformer声明为具有正确参数的服务

$builder
        ->add('user', EntityType::class, [
            'label' => 'user.name',
            'attr' => [
                'class' => 'reguser',
            ],
            'class' => 'MyBundle\Entity\User',
        ]);

$builder
     ->get('user')
     ->addModelTransformer(new UsernameToUserTransformer($this->em))
     ;