2017-07-24 21 views
0

我已經在StackOverflow上搜索並閱讀Doctrine文檔(http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/index.html)的相應章節,但無法找到我要查找的內容對於。在沒有預先查詢數據庫的情況下從控制器添加對文檔的引用(Symfony/Doctrine MongoDB)

我正在使用Symfony v2.8製作的API,使用Doctrine MongoDB v1.1和MongoDB v3.0.14數據庫。

我有兩個不同的文檔:「Spot」和「Feature」。 A「點」包含文件「功能」的集合,具有ReferenceMany關係:

// Spot document declaration 

/** 
* @var \Transversal\SessionBundle\Document\Feature 
* @MongoDB\ReferenceMany(strategy="set", targetDocument="Transversal\SessionBundle\Document\Feature", sort={"uploadDate"="asc"}) 
* @Serializer\Expose 
*/ 
protected $features = array(); 

我工作的現貨創作路線/控制器上,在那裏我需要發送地點名稱,描述和清單現有特點我想添加到現場。

我現在要做的是在請求的主體中發送名稱,說明和特徵ID數組。 然後,在控制器,I循環通過該陣列中,並且對於每個ID I:

  • 經由它的id獲得從DB中的特徵的實例(所以它的每次迭代1分貝請求)
  • 添加它通過我的$spot->addFeature()方法到Spot對象

然後我堅持並刷新以保存新創建的點。 這是我的控制器方法的代碼(I修改代碼,使其更具有可讀性):

* @Rest\Post("") 
    * @return \Symfony\Component\HttpFoundation\JsonResponse 
    * @throws BosHttpException 
    */ 
    public function createAction() 
    { 
    $spot = new Spot(); 
    $request = $this->getCurrentRequest(); 

    // retrieve the name and description for the new spot here 
    $form = $this->createForm(SpotType::class, $spot); 
    $form->handleRequest($request); 

    $content = $request->getContent(); 
    $params = ""; 
    if (!empty($content)) { 
     $params = json_decode($content, true); 
    } 

    $document_manager = $this->getDocumentManager(); 
    $featureIds = $params['featureIds']; 
    foreach ($featuresIds as $featureId) { 
     $feature = $document_manager->find('Transversal\SessionBundle\Document\Feature', $featureId); 
     $spot->addFeature($feature); 
    } 

    $document_manager = $this->getDocumentManager(); 
    $document_manager->persist($spot); 
    $document_manager->flush(); 

    return $this->getOutputView("Spot creation - succeed", Codes::HTTP_CREATED, $this->formatResponse(null, true)); 

    } 

這裏是addFeature()中的文件Spot.php的代碼:

/** 
* Add feature 
* 
* @param \Transversal\SessionBundle\Document\Feature $feature 
*/ 
public function addFeature(\Transversal\SessionBundle\Document\Feature $feature) 
{ 
    $this->features[] = $feature; 
} 

這意味着如果我有一個20特徵的ID的數組,我的foreach循環將請求20倍的數據庫,我知道這不是一個可行的解決方案(我知道我可能使用一個請求來獲取它們,但這不是我正在尋找)。

有沒有辦法將功能分配給現場,而不必生成它們的實例和請求我的分貝,知道有引用

在此先感謝您的幫助!

+0

不是您的問題的答案,而是提高您的代碼的提示。您不需要執行'$ request = $ this-> getCurrentRequest();'因爲您可以注入方法簽名:'public function createAction(Request $ request)'。 –

+0

@FrancescoAbeni謝謝您的提示! – Enzo

回答

0

這是你如何使用@ParamConverter傳遞$功能僅僅是ID的例子,不是對象

use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; 

/** 
* @ParamConverter("feature", class="YourBundle:Feature") 
*/ 
public function addFeature(\Transversal\SessionBundle\Document\Feature $feature){ 
    $this->features[] = $feature; 
} 

這意味着,如果你讓這樣

foreach($featuresIds as $featureId) { 
    $spot->addFeature($featureId); 
} 
代碼

也可以工作,因爲學說應該認識到你作爲參數傳遞的id是'Feature'實體的id。無論如何,ORM正在進行查詢以獲取對象,您可以嘗試和比較時間。

+0

感謝您的回覆。不幸的是,如果我傳遞id作爲參數而不是Feature的實例,則會得到一個異常,說'參數1傳遞給Transversal \\ SpotBundle \\ Document \\ Spot :: addFeature()必須是Transversal \\的一個實例SessionBundle \\ Document \\ Feature,給出字符串「';這個解決方案不適合我。 – Enzo

+0

我剛剛編輯帖子,請參閱[@ParamConverter文檔](https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html) – Migdress

相關問題