2017-05-28 13 views
0

私はSymfony3でAPIを作成していますが、ユーザーは自分のスタックにゲームを追加できる状況があります。だから私は、ユーザーのidのゲームIDを接続しているテーブルがありますが、私は重複があることができ、状況があり得ることでDBに行を追加しているとき、同じよう:Symfony 3 - SQLテーブルの重複行を防ぐ方法

duplicates

私は避けたいですその状況が、どのようにそれを行うには?このような状況を防ぐsymfony3のような方法がいくつかありますか?または、エンドポイントにif-elseステートメントを追加して、JSONを返す必要があります:false?とにかく、どうすればいいですか?私は、最も簡単で効率的な方法を探しています。

エンティティのコードは次のようになります。

<?php 
namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Doctrine\Common\Collections\ArrayCollection; 
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; 

/** 
* @ORM\Entity 
* @ORM\Table(name="games_on_stacks") 
*/ 
class GamesOnStacks 
{ 
    /** 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    * @ORM\Column(type="integer") 
    */ 
    private $id; 
    /** 
    * @ORM\ManyToOne(targetEntity="User") 
    * 
    */ 
    private $user; 

    /** 
    * @return mixed 
    */ 
    public function getUser() 
    { 
     return $this->user; 
    } 

    /** 
    * @param mixed $user 
    */ 
    public function setUser(User $user) 
    { 
     $this->user = $user; 
    } 

    /** 
    * @ORM\ManyToOne(targetEntity="Game") 
    */ 
    private $game; 

    /** 
    * @return mixed 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 

    /** 
    * @return mixed 
    */ 
    public function getGame() 
    { 
     return $this->game; 
    } 

    /** 
    * @param mixed $game 
    */ 
    public function setGame($game) 
    { 
     $this->game = $game; 
    } 

} 

およびRESTエンドポイント:

<?php 


namespace AppBundle\Controller; 

use AppBundle\Entity\Game; 
use AppBundle\Entity\GamesOnStacks; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\HttpFoundation\JsonResponse; 
use Symfony\Component\HttpFoundation\Response; 

class GameController extends Controller 
{ 
    (...) 

    /** 
    * @Route("/game/{gameId}/add", name="game_add_to_stack") 
    */ 
    public function addToStack($gameId) 
    { 
     $gameOnStack = new GamesOnStacks(); 
     // db apply 
     $em = $this->getDoctrine()->getManager(); 
     $game = $em->getRepository('AppBundle:Game') 
      ->findOneBy(['id' => $gameId]); 
     $gameOnStack->setGame($game); 
     $user = $em->getRepository('AppBundle:User') 
      ->findOneBy(['id' => 1]); 
     $gameOnStack->setUser($user); 
     $em->persist($gameOnStack); 
     $em->flush(); 
     $arr = array('success' => true); 

     return new JsonResponse(json_encode((array)$arr)); 

    } 
} 
+0

既存 'GamesOnStacks'を探し、何も存在しない場合にのみ保存することができます。さらに、[データベースレベルの制約](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#annref-uniqueconstraint)を設定することができます。 –

+0

@MateuszSip OKですが、それを行う方法は? 私が試した: '@UniqueEntity( *フィールド= { "ユーザ"、 "ゲーム"}、 * errorPath = "ゲーム"、 を*メッセージ= "このゲームは既にこのユーザスタックに追加される。" *) '@ORM \ Table(name =" games_on_stacks ")'行の下に ' を追加すると、 が動作しませんでした。 –

+0

'@ UniqueEntity'は[validator component](https://symfony.com/doc/current/validation.html)に関連する別のものです。私が言及した制約は、スキーマの更新/移行を必要とします(そしてそれは価値があります)。リポジトリメソッドを使用した手動チェック(これはより明示的ですが、正しく実装されていれば同じように動作します)の両方で '@ UniqueEntity'を置き換えることもできます。 symfonyのドキュメントではすべてがうまく文書化されていますので、読書に時間を費やし、面倒なく問題を解決する必要があります。 –

答えて

2

はあなたのエンティティにUniqueEntity制約を追加し、あなたのコントローラでvalidator serviceを使用してオブジェクトを検証:

AppBundle/Entity/GamesOnStacks.php

<?php 
namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Doctrine\Common\Collections\ArrayCollection; 
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; 

/** 
* @ORM\Entity 
* @ORM\Table(name="games_on_stacks") 
* 
* @UniqueEntity(fields={"user", "game"}, errorPath="game", message="This game is already added on this user stack.") 
*/ 
class GamesOnStacks 
{ 
... 
} 

AppBundle /コントローラ/ GameController

/** 
* @Route("/game/{gameId}/add", name="game_add_to_stack") 
*/ 
public function addToStack($gameId) 
{ 
    $gameOnStack = new GamesOnStacks(); 
    // db apply 
    $em = $this->getDoctrine()->getManager(); 
    $game = $em->getRepository('AppBundle:Game') 
     ->findOneBy(['id' => $gameId]); 
    $gameOnStack->setGame($game); 
    $user = $em->getRepository('AppBundle:User') 
     ->findOneBy(['id' => 1]); 
    $gameOnStack->setUser($user); 

    // validate using the validator service 
    $validator = $this->get('validator'); 
    $errors = $validator->validate($gameOnStack); 

    if (count($errors) > 0) { 

     // custom error handling, e.g. returning failure jsonreponse, etc. 
     $errorsString = (string) $errors;   

    } else { 

     $em->persist($gameOnStack); 
     $em->flush(); 
     $arr = array('success' => true); 


     return new JsonResponse(json_encode((array)$arr)); 
    } 

} 
+0

ありがとう!それはまさに私が探していたものでした。;)私はそのようにエラー処理を作成しました: 'if(count($ errors)> 0){ $ errorsString = ''; foreach($ errors as $ error){ $ errorsString = $ error-> getMessage(); } $ errArr = array( '成功' =>偽、 'エラー' => $ errorsString ); return新しいJsonResponse(json_encode((array)$ errArr)); } ' –

関連する問題