zf2 表单不在组合对象中设置值
zf2 forms don't set value in composed object
我对 ZF2 注释表单有疑问。
具有 "composed Object" 的值不设置默认值。
我附上了我的代码。
为什么表单不在 MetaContent 对象行中设置值?我做错了什么?
在我写的时候在控制器中
"echo $category->getMetaContent()->getMetaDescription();" 它显示正确的值
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zend\Form\Annotation;
/**
* BlogCategory
*
* @ORM\Table(name="blog_category", indexes={@ORM\Index(name="category_parent_idx", columns={"parent_id"})})
* @ORM\Entity
*
* @Annotation\Hydrator("Zend\Stdlib\Hydrator\ObjectProperty")
* @Annotation\Name("Category")
*/
class BlogCategory
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*
* @Annotation\Exclude()
*/
private $id;
* @Annotation\Filter({"name":"StripTags"})
* @Annotation\Required({"required":"true"})
* @Annotation\Attributes({"class":"gui-input"})
*/
private $name;
/**
* @var \Application\Entity\MetaContent
*
* @ORM\ManyToOne(targetEntity="Application\Entity\MetaContent", cascade={"persist"})
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="meta_content_id", referencedColumnName="id")
* })
*
*
* @Annotation\ComposedObject("Application\Entity\MetaContent")
* @Annotation\Options({"label":"Meta content:", "label_options":{"class":"control-label"}})
*/
private $metaContent;
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zend\Form\Annotation;
/**
* MetaContent
*
* @ORM\Table(name="meta_content")
* @ORM\Entity
*
* @Annotation\Name("MetaContent")
*/
class MetaContent
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*
* @Annotation\Attributes({"type":"hidden"})
* @Annotation\AllowEmpty(true)
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="meta_description", type="string", length=255, nullable=true)
*
* @Annotation\Type("Zend\Form\Element\Text")
* @Annotation\Required({"required":"true"})
* @Annotation\Options({"label":"Meta description:"})
* @Annotation\Validator({"name":"StringLength", "options":{"min":"5", "max":"255"}})
* @Annotation\Filter({"name":"StripTags"})
* @Annotation\Attributes({"class":"gui-input"})
*/
private $metaDescription;
use Zend\Form\Annotation\AnnotationBuilder;
use DoctrineORMModule\Stdlib\Hydrator\DoctrineEntity;
class IndexController extends AbstractAdminController {
public function indexAction() {
$em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$view = new ViewModel();
$data = $this->getRequest()->getPost();
$category = $em->getRepository('Application\Entity\BlogCategory')->findOneByName('tests');
$builder = new AnnotationBuilder();
$form = $builder->createForm($category);
$form->setHydrator(new DoctrineEntity($em, false));
$form->add(array(
'type' => 'submit',
'name' => 'save',
'attributes' => array(
'value' => 'Submit',
)
));
$form->bind($category);
$form->prepare();
if ($this->getRequest()->isPost()){
$form->setData($data);
if ($form->isValid()){
echo 'good!';
}else{
echo 'bad';
}
}
$view->setVariable('form', $form);
return $view;
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<h1>Test</h1>
{{form().openTag(form)|raw}}
{{formCollection(form)}}
{{form().closeTag()|raw}}
</body>
</html>
默认情况下,学说关系是延迟加载(代理)的 - 它们仅在实际访问集合中的项目时加载。这一切都在幕后发生,所以当您这样做时:
$category->getMetaContent();
// Collection is NOT loaded yet, it is a transparent PROXY
count($category->getMetaContent());
// In order to cound, we must load,
// so only NOW the collection is loaded, replacing the PROXY
$category->getMetaContent()->getMetaDescription();
// Same here, only this command actually would load the MetaDescription
$category->getMetaContent()->getMetaDescription();
// Subsequent calls will return the MetaDescription directly,
// as it already be been loaded
最后一个特别重要。一旦代理被实际对象替换,该对象总是立即返回。有关代理的更多信息,请参阅 this question(推荐阅读!)
现在使用保湿器时事情变得有点困难。在提取期间,getMetaContent
返回的引用是 PROXY。但是 DoctrineEntity
hydrator 不解析代理,只是将其作为 un-extractable
跳过。这正是您在这里看到的。
那么,当您的控制器中有
$category->getMetaContent()->getMetaDescription();
时,为什么它一开始就起作用了?因为这样,控制器已经确保代理已被实际对象替换!现在 hydrator 接收实际对象而不是代理 - 它知道如何提取。
为了解决这个问题,您需要确保代理确实已解析。您可以通过两种简单的方式做到这一点:
- 讲学说对EAGER load的关系。这将始终立即加载
MetaDescription
对象。请注意,这会影响性能。
- 向知道如何处理此字段(即从代理中提取它)的水化器注册自定义策略。见 this question/answer 同样 issue/approach
我对 ZF2 注释表单有疑问。 具有 "composed Object" 的值不设置默认值。 我附上了我的代码。
为什么表单不在 MetaContent 对象行中设置值?我做错了什么? 在我写的时候在控制器中 "echo $category->getMetaContent()->getMetaDescription();" 它显示正确的值
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zend\Form\Annotation;
/**
* BlogCategory
*
* @ORM\Table(name="blog_category", indexes={@ORM\Index(name="category_parent_idx", columns={"parent_id"})})
* @ORM\Entity
*
* @Annotation\Hydrator("Zend\Stdlib\Hydrator\ObjectProperty")
* @Annotation\Name("Category")
*/
class BlogCategory
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*
* @Annotation\Exclude()
*/
private $id;
* @Annotation\Filter({"name":"StripTags"})
* @Annotation\Required({"required":"true"})
* @Annotation\Attributes({"class":"gui-input"})
*/
private $name;
/**
* @var \Application\Entity\MetaContent
*
* @ORM\ManyToOne(targetEntity="Application\Entity\MetaContent", cascade={"persist"})
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="meta_content_id", referencedColumnName="id")
* })
*
*
* @Annotation\ComposedObject("Application\Entity\MetaContent")
* @Annotation\Options({"label":"Meta content:", "label_options":{"class":"control-label"}})
*/
private $metaContent;
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zend\Form\Annotation;
/**
* MetaContent
*
* @ORM\Table(name="meta_content")
* @ORM\Entity
*
* @Annotation\Name("MetaContent")
*/
class MetaContent
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*
* @Annotation\Attributes({"type":"hidden"})
* @Annotation\AllowEmpty(true)
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="meta_description", type="string", length=255, nullable=true)
*
* @Annotation\Type("Zend\Form\Element\Text")
* @Annotation\Required({"required":"true"})
* @Annotation\Options({"label":"Meta description:"})
* @Annotation\Validator({"name":"StringLength", "options":{"min":"5", "max":"255"}})
* @Annotation\Filter({"name":"StripTags"})
* @Annotation\Attributes({"class":"gui-input"})
*/
private $metaDescription;
use Zend\Form\Annotation\AnnotationBuilder;
use DoctrineORMModule\Stdlib\Hydrator\DoctrineEntity;
class IndexController extends AbstractAdminController {
public function indexAction() {
$em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$view = new ViewModel();
$data = $this->getRequest()->getPost();
$category = $em->getRepository('Application\Entity\BlogCategory')->findOneByName('tests');
$builder = new AnnotationBuilder();
$form = $builder->createForm($category);
$form->setHydrator(new DoctrineEntity($em, false));
$form->add(array(
'type' => 'submit',
'name' => 'save',
'attributes' => array(
'value' => 'Submit',
)
));
$form->bind($category);
$form->prepare();
if ($this->getRequest()->isPost()){
$form->setData($data);
if ($form->isValid()){
echo 'good!';
}else{
echo 'bad';
}
}
$view->setVariable('form', $form);
return $view;
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<h1>Test</h1>
{{form().openTag(form)|raw}}
{{formCollection(form)}}
{{form().closeTag()|raw}}
</body>
</html>
默认情况下,学说关系是延迟加载(代理)的 - 它们仅在实际访问集合中的项目时加载。这一切都在幕后发生,所以当您这样做时:
$category->getMetaContent();
// Collection is NOT loaded yet, it is a transparent PROXY
count($category->getMetaContent());
// In order to cound, we must load,
// so only NOW the collection is loaded, replacing the PROXY
$category->getMetaContent()->getMetaDescription();
// Same here, only this command actually would load the MetaDescription
$category->getMetaContent()->getMetaDescription();
// Subsequent calls will return the MetaDescription directly,
// as it already be been loaded
最后一个特别重要。一旦代理被实际对象替换,该对象总是立即返回。有关代理的更多信息,请参阅 this question(推荐阅读!)
现在使用保湿器时事情变得有点困难。在提取期间,getMetaContent
返回的引用是 PROXY。但是 DoctrineEntity
hydrator 不解析代理,只是将其作为 un-extractable
跳过。这正是您在这里看到的。
那么,当您的控制器中有
$category->getMetaContent()->getMetaDescription();
时,为什么它一开始就起作用了?因为这样,控制器已经确保代理已被实际对象替换!现在 hydrator 接收实际对象而不是代理 - 它知道如何提取。
为了解决这个问题,您需要确保代理确实已解析。您可以通过两种简单的方式做到这一点:
- 讲学说对EAGER load的关系。这将始终立即加载
MetaDescription
对象。请注意,这会影响性能。 - 向知道如何处理此字段(即从代理中提取它)的水化器注册自定义策略。见 this question/answer 同样 issue/approach