2

私のプロジェクトのカテゴリ構造のために、私はエンティティを構築しています。追加フォームには、DoctrineObject ハイドレーターを使用します。$parent の値がある場合、これは正常に機能しますが、親がない場合は、親を選択するための ID がないため、エラーが発生します。この場合、親プロパティの値は null にする必要があります。

そのためのフィルターを作成します。このフィルターは実行されますが、ハイドレーターは私がやりたいことをしていないようです。

これを解決する方法を知っている人はいますか?

私のエンティティ:

use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Flex\Entity\Entity;

/**
 * @Gedmo\Tree(type="materializedPath")
 * @ORM\Table(name="categories")
 * @ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\MaterializedPathRepository")
 */
class Category extends Entity
{
    /**
     * @ORM\OneToMany(mappedBy="parent", targetEntity="FlexCategories\Entity\Category")
     */
    protected $children;

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @Gedmo\TreeLevel
     * @ORM\Column(nullable=true, type="integer")
     */
    protected $level;

    /**
     * @ORM\Column(length=64, type="string")
     */
    protected $name;

    /**
     * @Gedmo\TreeParent
     * @ORM\ManyToOne(inversedBy="children", targetEntity="FlexCategories\Entity\Category")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(onDelete="SET NULL", referencedColumnName="id")
     * })
     */
    protected $parent;

    /**
     * @Gedmo\TreePath(appendId=false, endsWithSeparator=false, separator="/", startsWithSeparator=true)
     * @ORM\Column(length=255, nullable=true, type="string", unique=true)
     */
    protected $path;

    /**
     * @Gedmo\Slug(fields={"name"}, unique=false)
     * @Gedmo\TreePathSource
     * @ORM\Column(length=64)
     */
    protected $slug;

    public function setId($value)
    {
        $this->id = $value;
    }    
    public function setName($value)
    {
        $this->name = $value;
    }
    public function setParent($value)
    {
        $this->parent = $value;
    }
}

私のフォーム:

use DoctrineModule\Stdlib\Hydrator\DoctrineObject;
use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;

class CategoryForm extends Form implements InputFilterProviderInterface, ServiceManagerAwareInterface
{
    private $_serviceManager;

    public function init()
    {
        // Init hydrator
        $hydrator        = new DoctrineObject($this->_serviceManager->get('doctrine.entitymanager.orm_default'),
                                              'FlexCategories\Entity\Category');

        // Set form basic configurations
        $this->setAttribute('method', 'post')
             ->setHydrator($hydrator);

        // Add parent field
        $this->add(array(
            'name'        => 'parent',
            'type'        => 'Zend\Form\Element\Hidden',
        ));

        // Add name field
        $this->add(array(
            'attributes'  => array(
                'required' => 'required',
            ),
            'name'        => 'name',
            'options'     => array(
                'label'       => 'Name',
            ),
            'type'        => 'Zend\Form\Element\Text',
        ));

        // Add description field
        $this->add(array(
            'name'       => 'description',
            'options'    => array(
                'label'       => 'Description',
            ),
            'type'       => 'Zend\Form\Element\Textarea',
        ));

        // Add CSRF element
        $this->add(array(
            'name'        => 'csrf',
            'type'        => 'Zend\Form\Element\Csrf',
        ));

        // Add submit button
        $this->add(array(
            'attributes'  => array(
                'type'    => 'submit',
                'value'   => 'Save',
            ),
            'name'        => 'submit',
        ));
    }
    public function getInputFilterSpecification()
    {
        return array(
            'description'  => array(
                'filters'     => array(
                    array(
                        'name'    => 'Zend\Filter\StringTrim'
                    ),
                ),
                'required'    => false,
            ),
            'name'         => array(
                'filters'     => array(
                    array(
                        'name'    => 'Zend\Filter\StringTrim'
                    ),
                ),
                'required'    => true,
                'validators'  => array(
                    array(
                        'name'    => 'Flex\Validator\EntityUnique',
                        'options' => array(
                            'entity'    => 'FlexCategories\Entity\Category',
                            'filter'   => array(
                                array('property'     => 'parent',
                                      'value'        => array('_context', 'parent')),
                            ),
                            'property'  => 'name',
                            'serviceLocator'    => $this->_serviceManager,
                        ),
                    ),
                ),
            ),
            'parent'       => array(
                'filters'     => array(
                    array(
                        'name'    => 'Flex\Filter\NullIfEmpty'
                    ),
                ),
                'required'    => false,
            ),
        );
    }

    public function setServiceManager(ServiceManager $serviceManager)
    {
        $this->_serviceManager = $serviceManager;
        $this->init();

        return $this;
    }
}

私のコントローラー:

use Flex\Controller\AbstractController;
use FlexCategories\Entity\Category;
use FlexCategories\Form\CategoryForm;

class AdminController extends AbstractController
{
    public function addAction()
    {
        // Load form
        $form                = $this->getServiceLocator()->get('FlexCategories\Form\CategoryForm');

        // Create and bind new entity
        $category            = new Category();
        $form->bind($category);

        // Load parent category if present
        $parentId            = $this->params()->fromRoute('id', null);
        if ($parentId !== null)
        {
            if (!is_numeric($parentId))
                throw new \InvalidArgumentException('Invalid parent id specified');

            $entityManager   = $this->getEntityManager();
            $repository      = $entityManager->getRepository('FlexCategories\Entity\Category');
            $parent          = $repository->find($parentId);

            if (!$parent)
                throw new \InvalidArgumentException('Invalid parent id specified');

            $form->get('parent')->setValue($parent->getId());
        }

        // Process request
        $request             = $this->getRequest();
        if ($request->isPost())
        {
            $form->setData($request->getPost());

            if ($form->isValid())
            {                
                $entityManager    = $this->getEntityManager();
                $entityManager->persist($category);
                $entityManager->flush();

                $this->flashMessenger()->addSuccessMessage(sprintf('The category "%1$s" has succesfully been added.', $category->getName()));
                return $this->redirect()->toRoute($this->getEvent()->getRouteMatch()->getMatchedRouteName());
            }
        }

        // Return form
        return array(
            'form'           => $form,
        );
    }
    public function indexAction()
    {
        // Load all categories
        $entityManager        = $this->getEntityManager();
        $repository           = $entityManager->getRepository('FlexCategories\Entity\Category');
        $categories           = $repository->findBy(array(), array('path' => 'asc'));

        return array(
            'categories'      => $categories,
        );
    }
}

私のデータベース:

CREATE TABLE `categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) DEFAULT NULL,
  `level` int(11) DEFAULT NULL,
  `name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `path` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `slug` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UNIQ_3AF34668B548B0F` (`path`),
  KEY `IDX_3AF34668727ACA70` (`parent_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


ALTER TABLE `categories`
  ADD CONSTRAINT `FK_3AF34668727ACA70` FOREIGN KEY (`parent_id`) REFERENCES `categories` (`id`) ON DELETE SET NULL;
4

2 に答える 2

0

「DoctrineModule\Form\ElementObjectSelect」に基づいて「HiddenElement」要素を作成し、これを入力タイプとして使用することで、この問題を解決します。

于 2013-04-23T18:55:30.700 に答える