2017-08-25 1 views
0

Je veux savoir quelles maladies professionnelles sont incluses dans tous les dossiers médicaux d'une unité de production de l'entreprise. L'entité MedicalRecord a beaucoup à plusieurs avec DiseaseTypology comme suit:Comment interroger le côté inverse d'une relation de plusieurs à plusieurs avec Doctrine

/** 
* AppBundle\Entity\HealthData\MedicalRecord 
* 
* @ORM\Table(name="medical_record") 
* @ORM\Entity(repositoryClass="MedicalRecordRepository") 
* @ORM\HasLifecycleCallbacks 
*/ 
class MedicalRecord 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

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

    /** 
    * @var ArrayCollection $professionalDiseases 
    * 
    * @ORM\ManyToMany(targetEntity="AppBundle\Entity\HealthData\Core\DiseaseTypology") 
    * @ORM\JoinTable(name="medical_record_professional_disease", 
    *  joinColumns={@ORM\JoinColumn(name="medical_record_id", referencedColumnName="id")}, 
    *  inverseJoinColumns={@ORM\JoinColumn(name="professional_disease_id", referencedColumnName="id")} 
    *  ) 
    * 
    */ 
    protected $professionalDiseases; 

Dans la classe MedicalRecordReposity j'ai créé la méthode suivante:

public function getProfessionalDiseasesByProductionUnit($productionUnitId) 
{ 
    $em = $this->getEntityManager(); 

    $repository = $em->getRepository('AppBundle:MedicalRecord'); 

    return $repository->createQueryBuilder('m') 
     ->select('m.professionalDiseases') 
     ->where('m.companyProductionUnitId = :productionUnitId') 
     ->setParameter('productionUnitId', $productionUnitId) 
     ->getQuery() 
     ->getArrayResult(); 
} 

Mais je reçois l'erreur:

[Semantical Error] line 0, col 9 near 'professionalDiseases': Error: Invalid PathExpression. Must be a StateFieldPathExpression.

Comment interroger le côté inverse d'une relation plusieurs à plusieurs? Je vous remercie!

+0

Peut-être ces [réponse 1] (https: // stackoverflow .com/questions/22666692/invalid-pathexpression-doit-être-un-statefieldpathexpression-in-query-builder-wi) et [réponse 2] (https://stackoverflow.com/questions/34408073/error-invalid-pathexpression -must-be-a-statefieldpathexpression) peut vous aider à améliorer votre question, ou y répondre. – nicof

Répondre

1

Je ne sais pas si je peux comprendre ce que vous voulez, mais voici mon essai:

class MedicalRecordRepository extends \Doctrine\ORM\EntityRepository 
{ 
    public function getProfessionalDiseasesByProductionUnit($productionUnitId) 
    { 
     $qb = $this->createQueryBuilder('m'); 

     $qb 
      ->select('m, pd') 
      ->innerJoin('m.professionalDiseases', 'pd') 
      ->where('m.companyProductionUnitId = :productionUnitId') 
      ->setParameter('productionUnitId', $productionUnitId) 
     ; 

     return $qb->getQuery()->getArrayResult(); 
    } 
} 

Explication: je pense que vous avez besoin d'une jointure entre MedicalRecord et DiseaseTypology, et pour cela, si vous avez cette configuration (dans les deux vos entités):

#Entity/MedicalRecord.php 
private $companyProductionIUnitId; 

/** 
* @var \AppBundle\Entity\DiseaseTypology 
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\DiseaseTypology", mappedBy="medicalRecords") 
*/ 
private $professionalDiseases; 

d'abord, vous devez avoir cette option mappedBy, de dire la doctrine du côté inverse de la relation.

Et

# Entity/DiseaseTypology.php 
/** 
* @var \AppBundle\Entity\MedicalRecord 
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\MedicalRecord", inversedBy="professionalDiseases") 
*/ 
private $medicalRecords; 

Vous devez avoir cette inversedBy possibilité de dire la doctrine du côté possédante de la relation. Une fois que nous avons clarifié cela, pour laisser la doctrine faire ses choses liées aux jointures, il suffit de lui dire sur quel champ faire la jointure. Et comme dans mon exemple, la relation entre MedicalRecord et DiseaseTypology est faite à travers $professionalDiseases champs. Ainsi, celui-ci sera le terrain pour faire la jonction avec:

->innerJoin('m.professionalDiseases', 'pd') // this professionalDiseases is the $professionalDiseses from MedicalRecord entity 

Ok, je l'ai ai fait toutes ces explications, parce que j'ai vu comment vous avez fait votre requête, et je me sens est pas la bonne approche.

Et mes résultats après l'exécution de la méthode getProfessionalDiseasesByProductionUnit() était comme ceci:

enter image description here

+0

Votre suggestion est correcte, mais la requête retourne un tableau de dossiers médicaux avec les maladies professionnelles connexes. J'aurais aimé recevoir un éventail de maladies professionnelles directement pour tous les dossiers médicaux avec une unité de l'entreprise en particulier. C'est possible? Thx – Gianluca78

+0

@ Gianluca78 Si je vous ai bien compris, vous avez besoin d'un éventail de dises professionnels pour chaque dossier médical, basé sur une unité de l'entreprise en particulier? –

+0

J'ai besoin d'un tableau de toutes les maladies professionnelles identifiées dans les dossiers médicaux ayant un certain ID de compagnie. Exemple: $ professionalDiseasesForCompanyUnit = array ('disease 1', 'disease 2', 'disease 44') – Gianluca78

1

Remarque: Utilisez getResult() au lieu de getArrayResult(), parce que vous allez chercher des entités (DiseaseTypology), et non l'ensemble de champs

Il y a 2 options:

  1. Faire une relation MedicalRecord < => DiseaseTypology bidirectionnelSee documentation.Ensuite, votre méthode serait très simple:

    public function getProfessionalDiseasesByProductionUnit($productionUnitId) 
    { 
        $em = $this->getEntityManager(); 
    
        $repository = $em->getRepository(DiseaseTypology::class); 
    
        return $repository->createQueryBuilder('dt') 
         ->select('dt') 
         ->join('dt.medicalRecords', 'm') 
         ->where('m.companyProductionUnitId = :productionUnitId') 
         ->setParameter('productionUnitId', $productionUnitId) 
         ->getQuery() 
         ->getResult(); 
    } 
    
  2. Conserver la structure existante de DB et ajouter une certaine logique après requête

    public function getProfessionalDiseasesByProductionUnit($productionUnitId) 
    { 
        $em = $this->getEntityManager(); 
    
        $repository = $em->getRepository(MedicalRecord::class); 
    
        $mediaRecords = $repository->createQueryBuilder('m') 
         ->select('m, dt') 
         //note: with this join all professionalDiseases will be loaded within one query for all MedicalRecords 
         ->join('m.professionalDiseases', 'dt') 
         ->where('m.companyProductionUnitId = :productionUnitId') 
         ->setParameter('productionUnitId', $productionUnitId) 
         ->getQuery() 
         ->getResult(); 
    
        $professionalDiseases = []; 
        foreach($mediaRecords as $mediaRecord) { 
         foreach($mediaRecord->professionalDiseases as $professionalDisease) { 
          $professionalDiseases[professionalDisease->id] = $professionalDisease; 
         } 
        } 
    
        return $professionalDiseases; 
    }