今天我开始阅读Zend \ Form的功能。我找到了来自Michael Gallego的great tutorial,其中他解释了如何使用一些新的酷炫功能。
如果我们处理1-1关系,这个例子到目前为止工作正常。学说很好。
我想做的是
正如您在my github sources所见,我使用了教程中的示例,但将其缩短为“Product”和“Brand”。品牌 - 在我的例子中 - 是一个带有预定义品牌的数据库表(Nike,Adidas,Puma,等等),当您从表单中创建新产品时,您将这些品牌作为选择菜单。
现在,我添加选项的方式不起作用。我知道我可以使用像
这样的数组手动设置选项$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可能认为这是正确的,因为我的选择的值为1)。
问题如何告诉我的表单将select-value映射到映射的对象ID?虽然在这种情况下我设置产品模型的方式可能不对。
任何帮助将不胜感激:)
答案 0 :(得分:1)
查看您的BrandFieldSet,您只为InputFilterProvider指定了名称,因此永远不会传递ID。
其次我建议您删除注册表。如果没有使用构造函数指定的话,使用ServiceManager创建的类可以/应该实现ServiceManagareAwareInterface,如果他们需要访问其他任何东西。
因此,在您的控制器中,而不是使用您的注册表,您将访问服务管理器
$this->getServiceLocator()
->get('FQCN_OR_ALIAS');
这个框架的贡献者写了一些很好的例子,并列出了一些github repos。
https://github.com/ZF-Commons和https://github.com/EvanDotPro(由于我缺乏声誉,不能再发帖了)
如果您有任何其他问题,请加入irc.freenode.org上的#zftalk.2
答案 1 :(得分: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);
}
}
}
答案 2 :(得分:0)
虽然这是一个老问题,但我还是想回答。以前的答案不使用Doc ObjectSelect
。
你说要有一个OneToOne关系,并且不希望将记录添加到" One-table&#34 ;;我在这里假设你有Uni-directional OneToOne的关系。
然而,如果你得到了"产品"和"品牌"作为实体,OneToMany Bi-directional关系可能更合适;)
然而,使用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