2016-03-06 22 views
2

鑑於以下Category實體...的Symfony:如何創建一個POST請求與Voryx REST捆綁一個一對多的關係

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** 
* Category 
* 
* @ORM\Table(name="category", uniqueConstraints = @ORM\UniqueConstraint(name="unique_categoryName", columns={"name"})}) 
* @ORM\Entity(repositoryClass="AppBundle\Repository\CategoryRepository") 
*/ 
class Category 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

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

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

    /** 
    * @ORM\OneToMany(targetEntity="AppBundle\Entity\Subcategory", mappedBy="category", cascade={"remove"}) 
    * @ORM\OrderBy({"name" = "ASC"}) 
    */ 
    private $subcategories; 

    ... 
} 

...及以下Subcategory實體:

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** 
* Subcategory 
* 
* @ORM\Table(name="subcategory") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\SubcategoryRepository") 
*/ 
class Subcategory 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

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

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

    /** 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="subcategories") 
    */ 
    private $category; 

    ... 
} 

我使用https://github.com/voryx/restgeneratorbundle 生成REST控制器...這下面是我src/AppBundle/Form/SubcategoryType看起來像(src/AppBundle/Form/CategoryType很相似):

<?php 

namespace AppBundle\Form; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class SucategoryType extends AbstractType 
{ 
    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('name') 
      ->add('description') 
      ->add('category', 'voryx_entity', array('class' => 'AppBundle\Entity\Category')) 
     ; 
    } 

    /** 
    * @param OptionsResolverInterface $resolver 
    */ 
    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\Sucategory' 
     )); 
    } 

    /** 
    * @return string 
    */ 
    public function getName() 
    { 
     return 'appbundle_subcategory'; 
    } 
} 

最後,這裏是我src/AppBundle/Controller/CategoryRESTController

<?php 

namespace AppBundle\Controller; 

use AppBundle\Entity\Category; 
use AppBundle\Form\CategoryType; 

use FOS\RestBundle\Controller\Annotations\QueryParam; 
use FOS\RestBundle\Controller\Annotations\RouteResource; 
use FOS\RestBundle\Controller\Annotations\View; 
use FOS\RestBundle\Request\ParamFetcherInterface; 
use FOS\RestBundle\Util\Codes; 
use FOS\RestBundle\View\View as FOSView; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\Form\Form; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 

use Voryx\RESTGeneratorBundle\Controller\VoryxController; 

/** 
* Category controller. 
* @RouteResource("Category") 
*/ 
class CategoryRESTController extends VoryxController 
{ 
    /** 
    * Get a Category entity 
    * 
    * @View(serializerEnableMaxDepthChecks=true) 
    * 
    * @return Response 
    * 
    */ 
    public function getAction(Category $entity) 
    { 
     return $entity; 
    } 

    /** 
    * Get all Category entities. 
    * 
    * @View(serializerEnableMaxDepthChecks=true) 
    * 
    * @param ParamFetcherInterface $paramFetcher 
    * 
    * @return Response 
    * 
    * @QueryParam(name="offset", requirements="\d+", nullable=true, description="Offset from which to start listing notes.") 
    * @QueryParam(name="limit", requirements="\d+", default="20", description="How many notes to return.") 
    * @QueryParam(name="order_by", nullable=true, array=true, description="Order by fields. Must be an array ie. &order_by[name]=ASC&order_by[description]=DESC") 
    * @QueryParam(name="filters", nullable=true, array=true, description="Filter by fields. Must be an array ie. &filters[id]=3") 
    */ 
    public function cgetAction(ParamFetcherInterface $paramFetcher) 
    { 
     try { 
      $offset = $paramFetcher->get('offset'); 
      $limit = $paramFetcher->get('limit'); 
      $order_by = $paramFetcher->get('order_by'); 
      $filters = !is_null($paramFetcher->get('filters')) ? $paramFetcher->get('filters') : array(); 

      $em = $this->getDoctrine()->getManager(); 
      $entities = $em->getRepository('AppBundle:Category')->findBy($filters, $order_by, $limit, $offset); 
      if ($entities) { 
       return $entities; 
      } 

      return FOSView::create('Not Found', Codes::HTTP_NO_CONTENT); 
     } catch (\Exception $e) { 
      return FOSView::create($e->getMessage(), Codes::HTTP_INTERNAL_SERVER_ERROR); 
     } 
    } 

    /** 
    * Create a Category entity. 
    * 
    * @View(statusCode=201, serializerEnableMaxDepthChecks=true) 
    * 
    * @param Request $request 
    * 
    * @return Response 
    * 
    */ 
    public function postAction(Request $request) 
    { 
     $entity = new Category(); 
     $form = $this->createForm(new CategoryType(), $entity, array("method" => $request->getMethod())); 
     $this->removeExtraFields($request, $form); 
     $form->handleRequest($request); 

     if ($form->isValid()) { 
      $em = $this->getDoctrine()->getManager(); 
      $em->persist($entity); 
      $em->flush(); 

      return $entity; 
     } 

     return FOSView::create(array('errors' => $form->getErrors()), Codes::HTTP_INTERNAL_SERVER_ERROR); 
    } 

    /** 
    * Update a Category entity. 
    * 
    * @View(serializerEnableMaxDepthChecks=true) 
    * 
    * @param Request $request 
    * @param $entity 
    * 
    * @return Response 
    */ 
    public function putAction(Request $request, Category $entity) 
    { 
     try { 
      $em = $this->getDoctrine()->getManager(); 
      $request->setMethod('PATCH'); //Treat all PUTs as PATCH 
      $form = $this->createForm(new CategoryType(), $entity, array("method" => $request->getMethod())); 
      $this->removeExtraFields($request, $form); 
      $form->handleRequest($request); 
      if ($form->isValid()) { 
       $em->flush(); 

       return $entity; 
      } 

      return FOSView::create(array('errors' => $form->getErrors()), Codes::HTTP_INTERNAL_SERVER_ERROR); 
     } catch (\Exception $e) { 
      return FOSView::create($e->getMessage(), Codes::HTTP_INTERNAL_SERVER_ERROR); 
     } 
    } 

    /** 
    * Partial Update to a Category entity. 
    * 
    * @View(serializerEnableMaxDepthChecks=true) 
    * 
    * @param Request $request 
    * @param $entity 
    * 
    * @return Response 
    */ 
    public function patchAction(Request $request, Category $entity) 
    { 
     return $this->putAction($request, $entity); 
    } 

    /** 
    * Delete a Category entity. 
    * 
    * @View(statusCode=204) 
    * 
    * @param Request $request 
    * @param $entity 
    * 
    * @return Response 
    */ 
    public function deleteAction(Request $request, Category $entity) 
    { 
     try { 
      $em = $this->getDoctrine()->getManager(); 
      $em->remove($entity); 
      $em->flush(); 

      return null; 
     } catch (\Exception $e) { 
      return FOSView::create($e->getMessage(), Codes::HTTP_INTERNAL_SERVER_ERROR); 
     } 
    } 
} 

公佈一個請求增加一個類別像這樣完美的作品:

curl -i -H "Content-Type: application/json" -X POST -d '{"name" : "Sport", "description" : "Sport category"}' http://localhost:8000/api/categories 

...這裏是結果:

+----+-------+---------------------------+ 
| id | name | description    | 
+----+-------+---------------------------+ 
| 1 | Sport | Sport category   | 
+----+-------+---------------------------+ 

但是,如何發佈請求以將子類別添加到上面創建的類別中?這個想法是添加一個子類別是這樣的:

curl -i -H "Content-Type: application/json" -X POST -d '{"name" : "Football", "description" : "Groups ranks about football"}' http://localhost:8000/api/categories/1/subcategories 
+0

你的問題通過我的回答解決了嗎? –

回答

4

是,創建類別的子類別資源POST請求會完全恢復正常。

我也認爲(根據這個如何你的實體看起來),你不需要SubcategoryType。因爲它會和CategoryType一樣。

取而代之的是兩個實體,您可以看看Gedmo Tree extensionhttps://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/tree.md並將其全部保留在一個實體上。

相關問題