2017-06-29 1 views
2

Je voudrais être en mesure d'utiliser des contraintes de validateur entité afin de vérifier si la book_id clé étrangère est valide, s'il vous plaît voir ci-dessous:validation de l'entité Symfony vérifier la clé étrangère existe

Book.php

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

    /** 
    * @var string 
    * @ORM\Column(name="name", type="string") 
    * @Assert\Length(
    *  max = 250, 
    *  maxMessage = "Name cannot be longer than {{ limit }} characters", 
    *  groups={"create","update"} 
    *) 
    */ 
    private $name; 

    /** 
    * @ORM\OneToOne(targetEntity="Loan", mappedBy="book", fetch="LAZY") 
    */ 
    protected $loan; 
} 

prêt .php

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

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

    /** 
    * @var string 
    * @ORM\Column(name="name", type="string") 
    * @Assert\Length(
    *  max = 500, 
    *  maxMessage = "Person cannot be longer than {{ limit }} characters", 
    *  groups={"create","update"} 
    *) 
    */ 
    private $person; 

    /** 
     * @ORM\OneToOne(targetEntity="Book", inversedBy="loan") 
     * @ORM\JoinColumn(name="book_id", referencedColumnName="id") 
     */ 
    protected $book; 
} 

Voici comment je valide actuellement l'entité de prêt

$loan = new Loan(); 
    $loan->setPerson($person); 
    $loan->setBookId($id); 

    /** @var ConstraintViolation $error */ 
    foreach ($this->get('validator')->validate($loan,null,['create'])->getIterator() as $index => $error) { 
     $errorMessages[] = $error->getMessage(); 
    } 

j'ai pensé peut-être que je peux ajouter un validateur personnalisé comme celui-ci à l'entité de prêt:

/** 
* @Assert\IsTrue(message = "The book does not exist") 
* @return bool 
*/ 
public function isBookLegal(BookRepository $bookRepository) 
{ 
    return !$bookRepository->fetchById($this->book_id); 
} 

Mais je finis à l'exception de suivi:

Type error: Too few arguments to function 
AppBundle\Entity\Loan::isBookLegal(), 0 passed and exactly 1 expected 
+0

d'abord affecter le 1er paramètre de la variable foreach à une variable, puis l'utiliser dans foreach, ce qui est tout simplement désagréable. Deuxièmement, lorsque vous appelez votre 'isBookLegal', vous l'appelez sans paramètre - c'est pourquoi vous obtenez ce message. – Edwin

+0

Mais comment puis-je appeler isBookLegal quand il est déclenché via validation? En d'autres termes comment puis-je valider pour passer le paramètre dans cette fonction? – Freid001

Répondre

2

Tout d'abord, vous ne devriez pas avoir $book_id et $book dans votre entité Loan. Vous devez supprimer $book_id, ce qui est suffisant pour votre relation d'entité.

Ensuite, tout ce que vous devez faire est d'ajouter un @Assert\NotBlank() sur $book:

use Symfony\Component\Validator\Constraints as Assert; 

... 

/** 
    * @ORM\OneToOne(targetEntity="Book", inversedBy="loan") 
    * @ORM\JoinColumn(name="book_id", referencedColumnName="id") 
    * @Assert\NotBlank() 
    */ 
protected $book; 

Je ne suis pas sûr de ce code que vous utilisez pour obtenir tous vos prêts, mais comme les États Edwin ce n'est pas vraiment bon forme. Vous voulez voulez quelque chose comme:

foreach ($loans as $loan) { 
    $errors = $this->get('validator')->validate($loan); 
    // do something here if there is an error 
} 

La fonction d'assertion que vous avez écrit ne va pas travailler parce que vous ne pouvez pas passer une valeur à votre là la fonction isBookLegal(), ne pouvez-vous jamais utiliser la connexion de base de données/référentiel à partir de votre classe d'entité.

Je ne suis pas vraiment sûr de ce que vous essayez d'accomplir sans plus de contexte ici. Doctrine va d'ores et déjà valider votre membre $book en raison de votre annotation @ORM\OneToOne en premier lieu. Vous n'avez pas besoin d'effectuer de validation supplémentaire. Je suppose que vous essayez de transmettre directement une valeur à $book_id, ce qui est incorrect. Tout d'abord, vous devez passer des entités $book déjà valides à votre classe Loan, via $loan->setBook(Book $book);

+0

Merci pour la réponse détaillée, je pense que je ne comprends pas comment fonctionnent les relations d'entité de la doctrine. Si je supprime book_id, que dois-je définir comme nom dans ceci: @ORM \ JoinColumn (name = "book_id", referencedColumnName = "id") – Freid001

+0

Oh je pense que je vois maintenant. Donc, je n'ai pas besoin de définir implicitement book_id comme une propriété de classe car la doctrine établira qu'elle doit ajouter cette colonne comme spécifié par son nom. – Freid001

+0

C'est exact. Consultez également ceci: http://symfony.com/doc/current/doctrine/reverse_engineering.html Vous pouvez demander à Doctrine de générer automatiquement toutes vos entités si la base de données est déjà créée. –