Question

how to listing two table join in symfony2

I have four table

  1. Country
  2. CountryTranslation
  3. State
  4. StateTranslation

following 4 table Entity

Table (1) Country


/**
 * 
 *
 * @ORM\Table(name="Country")
 * @ORM\Entity(repositoryClass="Dashboard\CountryBundle\Entity\CountryRepository")
 */
class Country
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

   /**
     * @ORM\OneToMany(
     *   targetEntity="CountryTranslation",
     *   mappedBy="object",
     *   cascade={"persist", "remove"}
     * )
     */
    private $translations; 


}

Table (2) CountryTranslation


/**
 * 
 *
* @ORM\Table(name="CountryTranslation")
 * @ORM\Entity
 */
class CountryTranslation
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

  /**
     * @var string $culture
     *
     * @ORM\Column(type="string", length=8)
     */
    private $culture;

     /**
     * @ORM\Column(name="country_name", type="string", length=255)
     */
    private $country_name;


   /**
     * @ORM\ManyToOne(targetEntity="Country", inversedBy="translations")
     * @ORM\JoinColumn(name="country_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $object;
}

Table (3) State


/**
 *
 * @ORM\Table(name="State")
 * @ORM\Entity(repositoryClass="Dashboard\CountryBundle\Entity\StateRepository")
 */
class State
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

   /**
     * @ORM\ManyToOne(targetEntity="Country")
     * @ORM\JoinColumn(name="country_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $countryId;  


   /**
     * @ORM\OneToMany(
     *   targetEntity="StateTranslation",
     *   mappedBy="object",
     *   cascade={"persist", "remove"}
     * )
     */
    private $translations;


}

Table (4) StateTranslation


/**
 * StateTranslation
 *
 * @ORM\Table(name="StateTranslation")
 * @ORM\Entity
 */
class StateTranslation
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;


   /**
     * @var string $culture
     *
     * @ORM\Column(type="string", length=8)
     */
    private $culture;

     /**
     * @ORM\Column(name="state_name", type="string", length=255)
     */
    private $state_name;


   /**
     * @ORM\ManyToOne(targetEntity="State", inversedBy="translations")
     * @ORM\JoinColumn(name="state_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $object;
}

I want to have the following type listing

**No  Country name     state name   Action**
 1     India           Gujarat       edit/delete
 2     USA             california    edit/delete    

I have following code in StateRepository file but how to display country name on list page now . I can see bellow table in listing page

**No  Country name               state name   Action**
 1     3(country id)             Gujarat       edit/delete
 2     5(country id)             california    edit/delete    

public function loadAllState($culture = 'en')
{

    $em = $this->getEntityManager();
    $q  = $em->createQuery("SELECT c, t
                FROM Dashboard\CountryBundle\Entity\State c
                LEFT JOIN c.translations t
                WHERE  t.culture = :culture ")->setParameter('culture', $culture);
    return $q->getResult();
}

my other question is

how to Language wise display in add / edit twig file

currently my code in StateType.php file

$builder->add('country', 'entity', array(
    'class'         => 'DashboardCountryBundle:Country',
    'property' => 'translations[0].country_name', 
    'query_builder' => function(EntityRepository $er) {
    return $er->createQueryBuilder('mc')
    ->select('mc','d')
    ->innerJoin('mc.translations', 'd')
    ->where('d.culture =  :culture')
    ->setParameter('culture', 'en');
    },
    'label'    => false,
    'attr'=> array('class' => 'validate[required] form-control'),
    'empty_value'=>'Please Select Category'
));

it is working fine but my question for how to reduce query which i have used in above statement ?

currently i am using this code but facing problem that i am getting country of all language
how to language wise getting country

**StateType.php file**  
      ->add('country', 'entity', array('class' => 'DashboardCountryBundle:CountryTranslation','property' => 'name', 'label' => false,'attr'=> array('class' => 'validate[required] form-control')));
Was it helpful?

Solution

I think you're almost there, you just had to apply the same logic with the country entity to fetch the translations.

1 It's a good practice to change this in your State class:

protected $countryId;  

to this:

protected $country

Why? Because it's a relationship between State entity and Country entity (and not between State entity and CountryId field. Entities and primary keys are different things. However, you use the primary key ($countryId) of the Country entity to create a relationship with the State entity.

Note: Therefore, you'll have to change your getter and setter to getCountry() and setCountry($country)

2 That would be your query:

public function loadAllState($culture = 'en')
{

    $em = $this->getEntityManager();
    $q  = $em->createQuery("

                SELECT s, st, c, ct
                FROM Dashboard\CountryBundle\Entity\State s

                INNER JOIN s.translations st
                WHERE  st.culture = :state_culture

                INNER JOIN s.country c

                INNER JOIN c.translations ct
                WHERE  ct.culture = :country_culture

        ")
        ->setParameter('state_culture', $culture)
        ->setParameter('country_culture', $culture);

    return $q->getResult();
}

3 You will get a collection of Dashboard\CountryBundle\Entity\State objects.


Extra for fun

Using the Query Builder instead:

public function loadAllState($culture = 'en')
{
    //   we create a query builder
    $queryBuilder = $this->getEntityManager()
        ->createQueryBuilder();

    //   we select what we need
    $queryBuilder
        ->select('s, st, c, ct')

    //  from the appropriate connection class
        ->from('Dashboard\CountryBundle\Entity\State', 's')

    //  join the state translations
        ->innerJoin('s.translations','st')
        ->andWhere('st.culture = :state_culture')
        ->setParameter('state_culture', $culture)

    //  join the country 
        ->innerJoin('s.country','c')

    //  join the country translations
        ->innerJoin('c.translations','ct')
        ->andWhere('ct.culture = :country_culture')
        ->setParameter('country_culture', $culture);

    return $queryBuilder
        ->getQuery()
        ->getResult();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top