0

今天我开始阅读 Zend\Form 的特性。我从 Michael Gallego 那里找到了一个很棒的教程,他在其中解释了如何使用一些很酷的新功能。

如果我们正在处理 1-1 关系,则该示例到目前为止运行良好。教义很好地涵盖了它们。

我想做的是

  • 我想要一个选择框,而不是相关值的 textarea
  • 选择框应具有有效选项,具体取决于数据库中的内容
  • 为了以后编辑的目的,需要选择当前选择的值
  • Doctrine 不应向 One-Table 添加新行

正如您在我的 github 资源中看到的那样,我使用了教程中的示例,但将其缩短为“产品”和“品牌”。Brands - 在我的示例中 - 是一个带有预定义 Brands(Nike、Adidas、Puma 等)的 DB-Table,当您从表单创建新产品时,您会将这些 Brands 作为选择菜单。

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

$form->get('product')->get('brand')->setAttribute('options', array('Nike'=>'1', 'Adidas'=>'2', etc);

但我强烈认为有一种更自动化的方法可以做到这一点。我根本不理解 Zend 提供的所有这些 Hydrator 类。

问题是,即使我如上所述手动定义数组,产品和品牌的映射也无法正常工作。现在的转储$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 可能认为这是正确的,因为我选择的 VALUE 是 1)。

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

任何帮助将不胜感激 :)

4

3 回答 3

1

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

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

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

$this->getServiceLocator()
     ->get('FQCN_OR_ALIAS');

该框架的贡献者编写了一些很棒的示例,并在此处列出了一些 github 存储库。

https://github.com/ZF-Commonshttps://github.com/EvanDotPro(不能再发帖,因为我缺乏声誉)

如果您有任何其他问题,请加入我们在 irc.freenode.org 上的 #zftalk.2

于 2012-07-18T12:16:09.977 回答
1

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

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);  
}
}
}
于 2012-07-26T16:41:34.973 回答
0

虽然这是一个老问题,但我想我还是会回答。以前的答案不使用ObjectSelectDoctrine 。

您说有一个 OneToOne 关系并且不希望将记录添加到“One-table”;我在这里假设你有一个单向的 OneToOne关系。

但是,如果您将“产品”和“品牌”作为实体,OneToMany 双向关系可能更合适;)

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

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
}

假设您的实体是正确的,那么您应该使用ObjectSelect构建到 Doctrine 中。

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;
                },
            ],
        ];
    }
}

接下来,将表单加载到 Controller 中。

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

============================

注意:这一直有效到 Zend Framework 2.5.2

于 2016-06-18T17:29:31.660 回答