【问题标题】:zf2 forms don't set value in composed objectzf2 表单不在组合对象中设置值
【发布时间】:2016-07-30 17:50:06
【问题描述】:

我对 ZF2 注释表单有疑问。 具有“组合对象”的值未设置默认值。 我已附上我的代码。

为什么表单没有在 MetaContent 对象行中设置值?我做错了什么? 当我写的时候在控制器中 “回声 $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>

enter image description here

【问题讨论】:

    标签: forms doctrine-orm annotations zend-framework2 entity


    【解决方案1】:

    默认情况下,原则关系是延迟加载(代理)的——它们仅在集合中的项目被实际访问时加载。这一切都发生在幕后,所以当你这样做时:

    $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 返回的引用是代理。但是DoctrineEntity hydrator 不能解析代理,而只是将其作为un-extractable 跳过。这正是您在这里看到的。

    那么,当您的控制器中有 $category->getMetaContent()->getMetaDescription(); 时,为什么它首先会起作用?因为这样,控制器已经确保代理已被实际对象替换!现在 hydrator 接收实际对象而不是代理 - 它知道如何提取。

    要解决这个问题,您需要确保代理已实际解析。您可以通过两种简单的方式做到这一点:

    • 将教义告诉EAGER load关系。这将始终立即加载 MetaDescription 对象。请注意,这会对性能产生影响。
    • 向知道如何处理此字段的 hydrator 注册自定义策略(即从代理中提取它)。有关相同的问题/方法,请参阅 this question/answer

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-08
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多