ZF2 Doctrine2 - 使用隐藏的id字段保存关联的实体

时间:2014-10-29 16:27:16

标签: doctrine-orm zend-framework2

我有以下情况:

"公司" 1..n"菜单" 1..n" MenuCategory"

为了添加类别,我有一个单独的表单,其中包含相关菜单的id的隐藏字段。如果我想保存类别,我会得到以下异常:

  

SQLSTATE [23000]:完整性约束违规:1048列' menu_id'不能为空

如果在我的控制器中进行验证检查后我得到var_dump $ form-> getData(),我得到以下响应,其中相关菜单为空。我是否必须先加载菜单并将其分配给我要保存的新类别?

object(Company\Entity\MenuCategory)#483 (4) {
    ["id":protected]=>NULL
    ["name":protected]=> string(4) "Test"
    ["description":protected]=>NULL
    ["menu":protected]=>NULL
}

以下是我的相关课程(我将其缩短为相关部分):

菜单

use Company\Entity\Company;
use Doctrine\ORM\Mapping as ORM;
use DateTime;

/**
* @ORM\Entity(repositoryClass="Company\Repository\Doctrine\MenuRepository")
* @ORM\Table(name="menu")
*/
class Menu {

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

    /** 
     * @var string
     * 
     * @ORM\Column(type="string", name="name", nullable=false) 
    */
    protected $name;

    /** 
     * @var string
     * 
     * @ORM\Column(type="string", name="description", nullable=false) 
     */
    protected $description;

    /**
    * @var \Company\Entity\MenuCategory[]
    *
    * @ORM\OneToMany(targetEntity="Company\Entity\MenuCategory", mappedBy="menu", cascade={"remove"})
     */
    protected $categories;
}

MenuCategory

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity(repositoryClass="Company\Repository\Doctrine\MenuCategoryRepository")
* @ORM\Table(name="menu_category")
*/
class MenuCategory {

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

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

    /**
     * @var string
     *
     * @ORM\Column(type="string", name="description", nullable=true)
     */
    protected $description;

    /**
    * @var \Company\Entity\Menu
    *
     * @ORM\ManyToOne(targetEntity="Company\Entity\Menu", inversedBy="categories")
    * @ORM\JoinColumn(nullable=false)
    */
    protected $menu;
}

MenuCategoryForm

use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Zend\Form\Form;    

class MenuCategoryForm extends Form implements ObjectManagerAwareInterface {

    protected $objectManager;

    public function init() {
        $this->add(array(
            'type' => 'hidden',
            'name' => 'menu_id',
            'attributes' => array(
                'required' => 'required'
            )
        ));

        $this->add(array(
            'name' => 'name',
            'options' => array(
                'label' => 'Name'
            ),
            'attributes' => array(
                'id' => 'menu-category-name',
                'required' => 'required'
            )
        ));

        $this->add(array(
            'type' => 'textarea',
            'name' => 'description',
            'options' => array(
                'label' => 'Beschreibung'
            ),
            'attributes' => array(
                'id' => 'menu-category-description'
            )
        ));
    }

    public function setObjectManager(ObjectManager $objectManager) {
        $this->objectManager = $objectManager;
        return $this;
    }

    public function getObjectManager() {
        return $this->objectManager;
    }
}

MenuCategoryFormFactory

use Company\Entity\MenuCategory;
use Company\Form\MenuCategoryForm;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;

class MenuCategoryFormFactory implements FactoryInterface {

    public function createService(ServiceLocatorInterface $formElementManager) {
        $serviceLocator = $formElementManager->getServiceLocator();
        $hydratorManager = $serviceLocator->get('HydratorManager');
        $inputFilterManager = $serviceLocator->get('InputFilterManager');

        $form = new MenuCategoryForm();
        $form->setInputFilter($inputFilterManager->get('Company\InputFilter\MenuCategory'));
        $form->setHydrator($hydratorManager->get('Application\Hydrator\Doctrine'));
        $form->bind(new MenuCategory());

        return $form;
    }

}

控制器

use Company\Service\MenuServiceInterface;
use Doctrine\ORM\Query;
use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;

class MenuCategoryAdminRestController extends AbstractRestfulController {
    protected $menuService;

    protected $menuCategoryForm;

    public function __construct(MenuServiceInterface $menuService) {
        $this->menuService = $menuService;
    }

    public function create($data) {
        $form = $this->getMenuCategoryForm();
        $form->setData($data);

        if ($form->isValid()) {
            $this->getMenuService()->saveMenuCategory($form->getData());
        }

        return new JsonModel();
    }
}

1 个答案:

答案 0 :(得分:1)

您的表单字段MenuCategoryForm :: menu_id未映射到MenuCategory:menu。将名称从menu_id更改为菜单。

至于水合作用,您可以将菜单ID分配给MenuCategoryForm:menu字段,并且在保湿时,映射的实体将由doctrine的保水器加载。从doctrine hydrator doc中查看此section进行解释。