title: How to search ManyToOne side by OneToMany
body: <p>I have Four Entities:</p>
  
  <ol>
  <li>Batch</li>
  <li>BachGroup</li>
  <li>BachGroupApplication</li>
  <li>Application</li>
  </ol>
  
  <p>Entity 1(Batch) has OneToMany Bidirectional relationship with Entity 2(BatchGroup).</p>
  
  <p>Entity 2(BatchGroup) has OneToMany Bidirectional relationship with Entity 3(BachGroupApplication).</p>
  
  <p>Entity 3(BachGroupApplication) has ManyToOne Bidirectional relationship with Entity 4(Application).</p>
  
  <p><strong>DETAIL ON ABOVE ENTITIES:</strong>
  Each batch has it's groups which i'm storing in bachGroup entity with batch reference column in it, now each batchGroup can have multiple applications so i have created BatchGroupApplication entity which holds reference to batchGroup and Application.</p>
  
  <p><strong>TODO:</strong>
  I want to be able to search applications by individual batch group which i'm not able to do i searched the web and stackoverflow but failed to get it working! i don't know if my mind has stopped somewhere! my entities are listed below please help:</p>
  
  <p><strong>Batch Entity</strong></p>
  
  <pre><code>&lt;?php
  
  namespace ModelBundle\Entity;
  
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Component\Validator\Constraints as Assert;
  use Doctrine\Common\Collections\ArrayCollection;
  
  /**
   * Batch
   *
   * @ORM\Table(name="batch")
   * @ORM\Entity(repositoryClass="ModelBundle\Repository\BatchRepository")
   */
  class Batch
  {
      /**
       * @var int
       *
       * @ORM\Column(name="id", type="integer")
       * @ORM\Id
       * @ORM\GeneratedValue(strategy="AUTO")
       */
      private $id;
  
      // ..............
  
      /**
       * If a Batch is removed all it's associated Groups will be deleted as well..
       *
       * @ORM\OneToMany(targetEntity="BatchGroup", mappedBy="batch", cascade={"remove"})
       **/
      private $batchGroups;
  
  
      public function __construct() {
  
          $this-&gt;batchGroups = new ArrayCollection();
      }
  
  
      /**
       * Get id
       *
       * @return integer 
       */
      public function getId()
      {
          return $this-&gt;id;
      }
  
      // ...............
  
      /**
       * Add batchGroups
       *
       * @param \ModelBundle\Entity\BatchGroup $batchGroups
       * @return Batch
       */
      public function addBatchGroup(\ModelBundle\Entity\BatchGroup $batchGroups)
      {
          $this-&gt;batchGroups[] = $batchGroups;
  
          return $this;
      }
  
      /**
       * Remove batchGroups
       *
       * @param \ModelBundle\Entity\BatchGroup $batchGroups
       */
      public function removeBatchGroup(\ModelBundle\Entity\BatchGroup $batchGroups)
      {
          $this-&gt;batchGroups-&gt;removeElement($batchGroups);
      }
  
      /**
       * Get batchGroups
       *
       * @return \Doctrine\Common\Collections\Collection 
       */
      public function getBatchGroups()
      {
          return $this-&gt;batchGroups;
      }
  }
  </code></pre>
  
  <p><strong>BatchGroup Entity</strong></p>
  
  <pre><code>&lt;?php
  
  namespace ModelBundle\Entity;
  
  use Doctrine\ORM\Mapping as ORM;
  
  use Doctrine\Common\Collections\ArrayCollection;
  
  /**
   * BatchGroup
   *
   * @ORM\Table(name="batch_group")
   * @ORM\Entity()
   */
  class BatchGroup
  {
      /**
       * @var integer
       *
       * @ORM\Column(name="id", type="integer")
       * @ORM\Id
       * @ORM\GeneratedValue(strategy="AUTO")
       */
      private $id;
  
      /**
       * @var string
       *
       * @ORM\Column(name="title", type="string", length=128)
       */
      private $title;
  
      /**
       * @ORM\ManyToOne(targetEntity="Batch", inversedBy="batchGroups")
       * @ORM\JoinColumn(name="batch_id", referencedColumnName="id")
       **/
      private $batch;
  
      /**
       * @ORM\OneToMany(targetEntity="BatchGroupApplication", mappedBy="batchGroup", cascade={"remove"})
       **/
      private $batchGroupApplications;
  
  
      public function __construct() {
          $this-&gt;batchGroupApplications = new ArrayCollection();
      }
  
      /**
       * Get id
       *
       * @return integer 
       */
      public function getId()
      {
          return $this-&gt;id;
      }
  
      // ............
  
      /**
       * Set batch
       *
       * @param \ModelBundle\Entity\Batch $batch
       * @return BatchGroup
       */
      public function setBatch(\ModelBundle\Entity\Batch $batch = null)
      {
          $this-&gt;batch = $batch;
  
          return $this;
      }
  
      /**
       * Get batch
       *
       * @return \ModelBundle\Entity\Batch 
       */
      public function getBatch()
      {
          return $this-&gt;batch;
      }
  
      /**
       * Add batchGroupApplications
       *
       * @param \ModelBundle\Entity\BatchGroupApplication $batchGroupApplications
       * @return BatchGroup
       */
      public function addBatchGroupApplication(\ModelBundle\Entity\BatchGroupApplication $batchGroupApplications)
      {
          $this-&gt;batchGroupApplications[] = $batchGroupApplications;
  
          return $this;
      }
  
      /**
       * Remove batchGroupApplications
       *
       * @param \ModelBundle\Entity\BatchGroupApplication $batchGroupApplications
       */
      public function removeBatchGroupApplication(\ModelBundle\Entity\BatchGroupApplication $batchGroupApplications)
      {
          $this-&gt;batchGroupApplications-&gt;removeElement($batchGroupApplications);
      }
  
      /**
       * Get batchGroupApplications
       *
       * @return \Doctrine\Common\Collections\Collection 
       */
      public function getBatchGroupApplications()
      {
          return $this-&gt;batchGroupApplications;
      }
  }
  </code></pre>
  
  <p><strong>BatchGroupApplication Entity</strong></p>
  
  <pre><code>&lt;?php
  
  namespace ModelBundle\Entity;
  
  use Doctrine\ORM\Mapping as ORM;
  
  /**
   * BatchGroupApplication
   * 
   * Table generated through this entity class will hold all application and can be filtered through BatchGroup
   *
   * @ORM\Table(name="batch_group_application")
   * @ORM\Entity()
   */
  class BatchGroupApplication
  {
      /**
       * @var integer
       *
       * @ORM\Column(name="id", type="integer")
       * @ORM\Id
       * @ORM\GeneratedValue(strategy="AUTO")
       */
      private $id;
  
      /**
       * @ORM\ManyToOne(targetEntity="BatchGroup", inversedBy="batchGroupApplications")
       * @ORM\JoinColumn(name="batch_group_id", referencedColumnName="id")
       **/
      private $batchGroup;
  
      /**
       * @ORM\ManyToOne(targetEntity="Application", inversedBy="batchGroupApplications")
       * @ORM\JoinColumn(name="application_id", referencedColumnName="id")
       **/
      private $application;
  
      /**
       * Get id
       *
       * @return integer 
       */
      public function getId()
      {
          return $this-&gt;id;
      }
  
      /**
       * Set batchGroup
       *
       * @param \ModelBundle\Entity\BatchGroup $batchGroup
       * @return BatchGroupApplication
       */
      public function setBatchGroup(\ModelBundle\Entity\BatchGroup $batchGroup = null)
      {
          $this-&gt;batchGroup = $batchGroup;
  
          return $this;
      }
  
      /**
       * Get batchGroup
       *
       * @return \ModelBundle\Entity\BatchGroup 
       */
      public function getBatchGroup()
      {
          return $this-&gt;batchGroup;
      }
  
      /**
       * Set application
       *
       * @param \ModelBundle\Entity\Application $application
       * @return BatchGroupApplication
       */
      public function setApplication(\ModelBundle\Entity\Application $application = null)
      {
          $this-&gt;application = $application;
  
          return $this;
      }
  
      /**
       * Get application
       *
       * @return \ModelBundle\Entity\Application 
       */
      public function getApplication()
      {
          return $this-&gt;application;
      }
  }
  </code></pre>
  
  <p><strong>Application Entity</strong></p>
  
  <pre><code>&lt;?php
  
  namespace ModelBundle\Entity;
  
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Component\Validator\Constraints as Assert;
  use Doctrine\Common\Collections\ArrayCollection;
  
  /**
   * Application
   *
   * @ORM\Table(name="application")
   * @ORM\Entity(repositoryClass="ModelBundle\Repository\ApplicationRepository")
   */
  class Application
  {
      /**
       * @var integer
       *
       * @ORM\Column(name="id", type="integer")
       * @ORM\Id
       * @ORM\GeneratedValue(strategy="AUTO")
       */
      private $id;
  
      // ............
  
      /**
       * @ORM\OneToMany(targetEntity="BatchGroupApplication", mappedBy="application", cascade={"remove"})
       **/
      private $batchGroupApplications;
  
  
      public function __construct()
      {
          $this-&gt;batchGroupApplications = new ArrayCollection();
      }
  
      /**
       * Get id
       *
       * @return integer 
       */
      public function getId()
      {
          return $this-&gt;id;
      }
  
      // ............
  
      /**
       * Add batchGroupApplications
       *
       * @param \ModelBundle\Entity\BatchGroupApplication $batchGroupApplications
       * @return Application
       */
      public function addBatchGroupApplication(\ModelBundle\Entity\BatchGroupApplication $batchGroupApplications)
      {
          $this-&gt;batchGroupApplications[] = $batchGroupApplications;
  
          return $this;
      }
  
      /**
       * Remove batchGroupApplications
       *
       * @param \ModelBundle\Entity\BatchGroupApplication $batchGroupApplications
       */
      public function removeBatchGroupApplication(\ModelBundle\Entity\BatchGroupApplication $batchGroupApplications)
      {
          $this-&gt;batchGroupApplications-&gt;removeElement($batchGroupApplications);
      }
  
      /**
       * Get batchGroupApplications
       *
       * @return \Doctrine\Common\Collections\Collection 
       */
      public function getBatchGroupApplications()
      {
          return $this-&gt;batchGroupApplications;
      }
  }
  </code></pre>
  
  <p><strong>ApplicationRepository</strong>
  <br />
  Search function in this repository is being called from controller and from data is being sent to it via parameter that is in key value pair format, because form may have more properties so i'm checking if user is searching through batchGroup as well if yes it should combine the result from there as well.
      
  
  <pre><code>namespace ModelBundle\Repository;
  
  use Doctrine\ORM\EntityRepository;
  
  /**
   * ApplicationRepository
   *
   * This class was generated by the Doctrine ORM. Add your own custom
   * repository methods below.
   */
  class ApplicationRepository extends EntityRepository
  {
      /**
       * Search Applications
       *
       * data: search form data in key =&gt; value fashion
       *
       *
       */
      public function search($data)
      {
          $em = $this-&gt;getEntityManager();
  
          $applicationRepository = $em-&gt;getRepository('ModelBundle:Application');
  
          $qb = $applicationRepository-&gt;createQueryBuilder('a');
  
          foreach ($data as $field =&gt; $value) {
  
              if($field=="batchGroupApplications"){    
                  $qb-&gt;andWhere(":value_$field MEMBER OF a.batchGroupApplications")-&gt;setParameter("value_$field", $value);
              }else{
                  $qb-&gt;andWhere("a.$field = :value_$field")-&gt;setParameter("value_$field", $value);
              }
          }
  
          $query = $qb-&gt;getQuery();
  
          $result = $query-&gt;getResult();
  
          return $result;
      }
  }
  </code></pre>
  
  <p><strong>Controller</strong>
  <br />
  Here i'm creating a search form with batchGroupApplications dropdown, where user will choose any batch group and submit the form, once submitted user should be able to see all applications which are in that group but i'm getting nothing!
      
  
  <pre><code>namespace SISBundle\Controller;
  
  use Symfony\Component\HttpFoundation\Request;
  use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
  use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
  use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  
  use ModelBundle\Entity\Batch;
  use SISBundle\Form\BatchType;
  
  use ModelBundle\Entity\Application;
  use DefaultBundle\Form\ApplicationType;
  
  use Symfony\Component\Form\FormError;
  
  use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  
  use SISBundle\Form\SearchApplicationType;
  
  use ModelBundle\Entity\Group;
  use ModelBundle\Entity\BatchGroup;
  
  /**
   * Admission controller.
   *
   * @Route("/admission")
   */
  class AdmissionController extends Controller
  {
      // ..............
  
      /**
       * List Applications for selected Batch
       *
       * @Route("/{batch}/applications")
       * 
       * @Method({"GET", "POST"})
       * @Template()
       */
      public function applicationsAction(Request $request, Batch $batch)
      {
          $em = $this-&gt;getDoctrine()-&gt;getManager();
  
          if( $batch != null ){
              $applications = $batch-&gt;getApplications();
  
              /*
               * Search Applications
               *
               */
              $searchForm = $this-&gt;createForm(SearchApplicationType::class, null, array(
                  'action' =&gt; $this-&gt;generateUrl('sis_admission_applications', array('batch'=&gt;$batch-&gt;getId())),
                  'method' =&gt; 'POST',
                  'attr'   =&gt; array(
                      'novalidate' =&gt; 'novalidate',
                      'id' =&gt; 'sis_application_search_form',
                  ),
              ));
              // Manually Populating groups dropdown based on their availability for current loaded batch
              $searchForm-&gt;add('batchGroupApplications', ChoiceType::class, array(
                  'choices'  =&gt; $batch-&gt;getBatchGroups(),
                  'choices_as_values' =&gt; true,
                  'multiple'=&gt;false,
                  'choice_label'=&gt;'title',
                  'placeholder'=&gt;' - Select Group..',
                  )
              );
              $searchForm-&gt;handleRequest($request);
              if ($searchForm-&gt;isSubmitted()) {
                  // data is an array with "firstname", "middlename", and "lastname" keys etc
                  $data = $searchForm-&gt;getData();
                  $applications = $em-&gt;getRepository('ModelBundle:Application')-&gt;search($data);
              }
              /*********************************** end: Search Applications ***************************************/
  
              return array(
                  'batch' =&gt; $batch,
                  'applications' =&gt; $applications,
                  'searchForm' =&gt; $searchForm-&gt;createView(),
              );
          }
      }
  
  }
  </code></pre>
  
  <p>Again, please suggest how can i search applications through batchGroup in andWhere fashion as search form may have some more fields which are available in application entity, for other fields it's working fine but this search by BatchGroup is somewhat tricky may be because of complicated associations etc.</p>
  
  <p>Looking forward to solution..</p>