Doctrine orm Zend \与条令2和多通关系一起形成

Doctrine orm Zend \与条令2和多通关系一起形成,doctrine-orm,zend-form,relationship,zend-framework2,Doctrine Orm,Zend Form,Relationship,Zend Framework2,今天我开始阅读Zend\Form的功能。我从Michael Gallego那里找到了一篇文章,他在文章中解释了如何使用一些新的很酷的功能 如果我们处理的是1-1关系,那么这个例子到目前为止效果很好。教义很好地涵盖了他们 我想做的是 我想要一个选择框,而不是用textarea作为相关值 选择框应具有有效选项,具体取决于数据库中的内容 为了以后进行编辑,需要选择当前选定的值 条令不应向一个表中添加新行 正如您在上所看到的,我使用了教程中的示例,但将其缩短为产品和品牌。在我的示例中,Brands是一个

今天我开始阅读Zend\Form的功能。我从Michael Gallego那里找到了一篇文章,他在文章中解释了如何使用一些新的很酷的功能

如果我们处理的是1-1关系,那么这个例子到目前为止效果很好。教义很好地涵盖了他们

我想做的是

我想要一个选择框,而不是用textarea作为相关值 选择框应具有有效选项,具体取决于数据库中的内容 为了以后进行编辑,需要选择当前选定的值 条令不应向一个表中添加新行 正如您在上所看到的,我使用了教程中的示例,但将其缩短为产品和品牌。在我的示例中,Brands是一个DB表,其中包含预定义的品牌Nike、Adidas、Puma等,当您从表单中创建新产品时,您可以将这些品牌作为选择菜单

现在,我添加选项的方式不起作用。我知道我可以用如下数组手动设置选项

$form->get('product')->get('brand')->setAttribute('options', array('Nike'=>'1', 'Adidas'=>'2', etc);
但我坚信有一种更自动化的方法可以做到这一点。我只是不理解Zend提供的所有这些内容或类

问题是,即使我如上所述手动定义数组,产品和品牌的映射也无法正常工作。现在的$product转储如下所示

object(Application\Entity\Product)[210]
  protected 'id' => null
  protected 'name' => string 'asdasd' (length=6)
  protected 'price' => string '123123' (length=6)
  protected 'brand' => 
    object(Application\Entity\Brand)[215]
      protected 'id' => null
      protected 'name' => string '1' (length=1)
很明显,我想要实现的品牌完全错了,zend可能认为这是对的,因为我选择的值是1

问题:如何告诉表单将select值映射到映射的对象ID?尽管在这种情况下,我建立产品模型的方式可能是错误的


任何帮助都将不胜感激:

查看您的BrandFieldSet,您只为InputFilterProvider指定了名称,因此永远不会传递id

其次,我会建议你删除注册表。使用ServiceManager创建的类可以/应该实现ServiceManagareAwareInterface,如果它们需要访问其他任何东西(如果不是使用构造函数指定的话)

因此,在控制器中而不是使用注册表访问服务管理器

$this->getServiceLocator()
     ->get('FQCN_OR_ALIAS');
这里有一些由框架贡献者编写的好例子,我将在这里列出一些github Repo

因为我没有名声,所以不能再发了


如果您还有任何问题,请访问irc.freenode.org上的zftalk.2加入我们

这是来自我的表单对象的代码 我希望这会有帮助

class ProductForm extends Form
{
public function __construct($em)
{
    parent::__construct();

    $this->add(array(
        'name' => 'productGroupId',
        'attributes' => array(
            'type'  => 'select',
            'label' => 'Category',
            'options' => array(),
        ),
    ));

$this->setProductGropus($em->getRepository('Project\Entity\ProductGroup')->findAll());

public function setProductGropus($groups)
{
  $groupsForm = array('--Select--'=>'');
  foreach ($groups as $group) {
        $groupsForm[$group->name] = (string) $group->productGroupId;
    }
    $this->get('productGroupId')->setAttribute('options',$groupsForm);  
}
}
}

虽然这是个老问题,但我想我还是会回答的。前面的答案没有使用原则的定义

class ProductForm
{
    /** @var  ObjectManager */
    protected $objectManager;

    public function __construct($name = 'product-form', $options = [])
    {
        parent::__construct($name, $options);
    }

    public function init()
    {
        $this->add([
            'type' => 'DoctrineModule\\Form\\Element\\ObjectSelect',
            'name' => 'brand',
            'required' => true,
            'attributes' => [
                'id' => 'selectBrand',
                'multiple' => false,
                'value' => null,
            ],
            'options' => [
                'label' => 'Select brand',
                'object_manager' => $this->getObjectManager(),
                'target_class' => Brand::class,
                'property' => 'id',
                'is_method' => true,
                'find_method' => [
                    'name' => 'findBy',
                    'params' => [
                        'criteria' => [],
                        'orderBy' => ['name' => 'ASC'],
                    ],
                ],
                'empty_option' => '--- Select Brand ---',
                'label_generator' => function (Brand $entity) {
                    return $entity->getName();
                }
            ],
        ]);
    }

    /**
     * @return ObjectManager
     */
    public function getObjectManager()
    {
        return $this->objectManager;
    }

    /**
     * @param ObjectManager $objectManager
     */
    public function setObjectManager(ObjectManager $objectManager)
    {
        $this->objectManager = $objectManager;
    }
}
您说有一个OneToOne关系,不希望将记录添加到一个表中;我假设你有一段感情

然而,如果你把产品和品牌作为一个实体,一种关系可能更合适

然而,使用OneTONE时,您的实体应如下所示:

class Brand {
    /**
     * @var int
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @var string
     * @ORM\Column(name="name", type="string", nullable=false, length=128)
     */
    protected $name;

    //Getters/Setters
}

class Product {
    /**
     * @var int
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @var string
     * @ORM\Column(name="name", type="string", nullable=false, length=128)
     */
    protected $name;

    //Change below "OneToOne" to "ManyToOne" for proper product + brand relationship. Just this change will leave it as uni-directional.
    /**
     * @var Brand
     * @ORM\OneToOne(targetEntity="Brand", fetch="EAGER")
     * @ORM\JoinColumn(name="brand", referencedColumnName="id")
     */
    protected $brand;

    //Getters/Setters
}
假设您的实体是正确的,那么您应该使用内置原则

class ProductForm
{
    /** @var  ObjectManager */
    protected $objectManager;

    public function __construct($name = 'product-form', $options = [])
    {
        parent::__construct($name, $options);
    }

    public function init()
    {
        $this->add([
            'type' => 'DoctrineModule\\Form\\Element\\ObjectSelect',
            'name' => 'brand',
            'required' => true,
            'attributes' => [
                'id' => 'selectBrand',
                'multiple' => false,
                'value' => null,
            ],
            'options' => [
                'label' => 'Select brand',
                'object_manager' => $this->getObjectManager(),
                'target_class' => Brand::class,
                'property' => 'id',
                'is_method' => true,
                'find_method' => [
                    'name' => 'findBy',
                    'params' => [
                        'criteria' => [],
                        'orderBy' => ['name' => 'ASC'],
                    ],
                ],
                'empty_option' => '--- Select Brand ---',
                'label_generator' => function (Brand $entity) {
                    return $entity->getName();
                }
            ],
        ]);
    }

    /**
     * @return ObjectManager
     */
    public function getObjectManager()
    {
        return $this->objectManager;
    }

    /**
     * @param ObjectManager $objectManager
     */
    public function setObjectManager(ObjectManager $objectManager)
    {
        $this->objectManager = $objectManager;
    }
}
确保设置Module.php以加载此表单。向其中添加getServiceConfig函数

public function getServiceConfig()
    {
        /** @var ServiceManager $sm */
        return [
            'factories' => [
                'product_form' => function ($sm)
                {
                    $form = new ProductForm();
                    $form->setInputFilter(new ProductInputFilter());

                    /** @var EntityManager $entityManager */
                    $entityManager = $sm->get('doctrine.entitymanager.orm_default');

                    //Set Doctrine ObjectManager
                    $form->setObjectManager($entityManager);
                    //Set Doctrine Object as Hydrator
                    $form->setHydrator(new DoctrineObject($entityManager, Product::class));
                    //Set Doctrine Entity
                    $form->setObject(new Product());
                    //Initialize elements onto form
                    $form->init();

                    return $form;
                },
            ],
        ];
    }
}
接下来,将表单加载到控制器中

$form = $this->getServiceLocator()->get('product_form');
===========================


注意:这在Zend Framework 2.5.2之前一直有效,我整天都在那里。我将尝试看看是否可以将ServiceManagerWareInterface应用到我的实体中,以及这是否符合我的要求,尽管这最终无助于解决我的问题:谢谢你的回答。实际上,我更进一步了,不需要手动填充select语句,因为有DOCTRINENTITY表单元素,但这些元素目前不适用于编辑目的。这种手动方法是有效的,但它缺乏神奇的发生-仍然是一个很好的答案;但问题是,我认为应该是$groupForms[$group->id]=$group->name?有关于ZF2水合器的最新情况吗?我正在实现一个hack,它从一个实体手动构造一个数组,并用setValueOptions设置它。如何将关联实体与选择下拉列表链接?例如:一个用户可以有多个客户端,所以当我编辑一个用户时,我需要一个客户端名称的下拉列表。@hohner只需查看github上DoctrineModule文档文件夹中的文档,Bakura就写了一篇惊人的自述;