如何通过 FOSUserBundle 和 Symfony3 中的附加字段扩展注册表单

How to extend register form by additional fields in FOSUserBundle and Symfony3

我正在学习 Symfony3 框架。现在我已经构建了包含两个实体的项目:用户和目录。目录实体用于附加公司数据(公司名称、地址等)——它就像一张名片。单个用户(但不是全部)仅与一张名片(目录实体)相关联,这就是我决定使用两个独立实体的原因。一些用户可以访问,例如后端和其他人有可能添加和管理他们的一张名片。 我想允许用户在注册时填写他的公司详细信息。我正在为用户实体使用 FOSUserBundle。现在我可以使用注册表单,但我卡住了,需要您帮助我嵌入 CatalogType 表单。

CatalogType 形式:

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CatalogType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('name')
        ->add('address')
        ->add('city')
        ->add('province')
        ->add('postcode')
        ->add('telephone')
        ->add('fax')
        ->add('mobile')
        ->add('email')
        ->add('webpage')
        ->add('misc')        
        ;
    }

    public function getParent()
    {
        return 'FOS\UserBundle\Form\Type\RegistrationFormType';
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'app_user_registration';
    }

}

用户实体:

use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */
class User extends BaseUser
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
    * @var
    * 
    * @ORM\OneToMany(targetEntity="Comment", mappedBy="user")
    */
    private $comments;

    /**
    * @var
    * 
    * @ORM\OneToOne(targetEntity="Catalog", mappedBy="user")
    */
    private $catalog;

    public function __construct()
    {
        parent::__construct();

        $this->comments = new \Doctrine\Common\Collections\ArrayCollection();
    }


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

    /**
     * Add comment
     *
     * @param \AppBundle\Entity\Comment $comment
     *
     * @return User
     */
    public function addComment(\AppBundle\Entity\Comment $comment)
    {
        $this->comments[] = $comment;

        return $this;
    }

    /**
     * Remove comment
     *
     * @param \AppBundle\Entity\Comment $comment
     */
    public function removeComment(\AppBundle\Entity\Comment $comment)
    {
        $this->comments->removeElement($comment);
    }

    /**
     * Get comments
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getComments()
    {
        return $this->comments;
    }

    /**
     * Set catalog
     *
     * @param \AppBundle\Entity\Catalog $catalog
     *
     * @return User
     */
    public function setCatalog(\AppBundle\Entity\Catalog $catalog = null)
    {
        $this->catalog = $catalog;

        return $this;
    }

    /**
     * Get catalog
     *
     * @return \AppBundle\Entity\Catalog
     */
    public function getCatalog()
    {
        return $this->catalog;
    }
}

目录实体

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Catalog
 *
 * @ORM\Table(name="catalog")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CatalogRepository")
 */
class Catalog
{
// ... definition a lot of private variables ...
/**
* @var
* 
* @ORM\OneToOne(targetEntity="User", inversedBy="catalog")
* @ORM\JoinColumn(name="user_id", nullable=true)
*/
private $user;

// ...

/**
 * Set user
 *
 * @param \AppBundle\Entity\User $user
 *
 * @return Catalog
 */
public function setUser(\AppBundle\Entity\User $user = null)
{
    $this->user = $user;

    return $this;
}

/**
 * Get user
 *
 * @return \AppBundle\Entity\User
 */
public function getUser()
{
    return $this->user;
}

服务配置文件:

// app/config/services.yml
services:
    app.form.registration:
        class: AppBundle\Form\CatalogType
        tags:
            - { name: form.type, alias: app_user_registration }

当我尝试在 http://localhost:8000/register/ 下显示注册表时 我收到一个错误:

Neither the property "name" nor one of the methods "getName()", "name()", "isName()", "hasName()", "__get()" exist and have public access in class "AppBundle\Entity\User".

我知道问题出在哪里,但我不知道如何正确解决它,所以如果有人能帮助我寻找解决方案或如何解决它,那就太好了。 谢谢。

CatalogType 不应扩展 RegistrationFormType。它应该是 AppBundle\Entity\Catalog 的表单类型。 您应该创建基于用户 class(FOS\UserBundle\Model\User 的子class)的表单类型,并且嵌入 CatalogType 表单。

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('...', ...)
                ->add('tasks', CollectionType::class, array(
                    'entry_type' => CatalogType::class,
                    ...
                ));
                ...
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\User',
        ));
    }

    public function getBlockPrefix()
    {
        return 'app_user_registration';
    }
}


class CatalogType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('name')
        ->add('address')
        ->add('city')
        ->add('province')
        ->add('postcode')
        ->add('telephone')
        ->add('fax')
        ->add('mobile')
        ->add('email')
        ->add('webpage')
        ->add('misc')        
        ;
    }
 ...
}

有关嵌入形式的更多信息:https://symfony.com/doc/current/form/form_collections.html 有关覆盖 FosUserBundle 表单的更多信息:http://symfony.com/doc/current/bundles/FOSUserBundle/overriding_forms.html