Reputation: 175
I've got the following problem with doctrine 2: I want to join my world entity, poll entity to my player entity. So after some tries it works fine in the database, when using my custom findOneBy I'm having : tw_player.security.error.[Semantical Error] line 0, col 170 near 'polls INNER JOIN': Error: Class Tw\PlayerBundle\Entity\Player has no association named polls.
Player Entity :
<?php
namespace Tw\PlayerBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Tw\PollBundle\Entity\Poll;
/**
* Player
*
* @ORM\Table(name="players")
* @ORM\Entity(repositoryClass="Tw\PlayerBundle\Entity\PlayerRepository")
*/
class Player
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", options={"unsigned"=true})
* @ORM\Id
*/
private $id;
/**
* @var PlayerWorld
*
* @ORM\OneToMany(targetEntity="PlayerWorld", mappedBy="player")
*/
private $worlds;
/**
* @var PlayerPoll
*
* @ORM\OneToMany(targetEntity="PlayerPoll", mappedBy="player")
*/
private $polls;
/**
* === Id ===
*/
public function setId($id)
{
//if ($id !== (int) $id)
// return false;
$this->id = $id;
return $this;
}
public function getId()
{
return $this->id;
}
/**
* === Worlds ===
*/
public function getWorlds()
{
return $this->worlds ?: $this->worlds = new ArrayCollection();
}
public function getWorldsId()
{
$ids = array();
foreach ($this->getWorlds() as $world) {
$ids[] = $world->getWorld()->getId();
}
return $ids;
}
public function hasWorld($id)
{
return in_array($id, $this->getWorldsId());
}
public function addWorld(World $world)
{
if (!$this->getWorlds()->contains($world)) {
$this->getWorlds()->add($world);
}
return $this;
}
public function removeWorld(World $world)
{
if ($this->getWorlds()->contains($world)) {
$this->getWorlds()->removeElement($world);
}
return $this;
}
/**
* === Polls ===
*/
public function getPolls()
{
return $this->polls ?: $this->polls = new ArrayCollection();
}
public function getPollsId()
{
$ids = array();
foreach ($this->getPolls() as $poll) {
$ids[] = $poll->getPoll()->getId();
}
return $ids;
}
public function hasPoll($id)
{
return in_array($id, $this->getPollsId());
}
public function addPoll(Poll $poll)
{
if (!$this->getPolls()->contains($poll)) {
$this->getPolls()->add($poll);
}
return $this;
}
public function removePoll(Poll $poll)
{
if ($this->getPolls()->contains($poll)) {
$this->getPolls()->removeElement($poll);
}
return $this;
}
}
World entity
<?php
namespace Tw\PlayerBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* World
*
* @ORM\Table(name="worlds")
* @ORM\Entity(repositoryClass="Tw\PlayerBundle\Entity\WorldRepository")
*/
class World
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", options={"unsigned"=true})
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=6, unique=true)
*/
private $name;
/**
* === Id ===
*/
public function getId()
{
return $this->id;
}
/**
* === Name ===
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getName()
{
return $this->name;
}
}
Poll entity
<?php
namespace Tw\PollBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Poll
*
* @ORM\Table(name="polls")
* @ORM\Entity(repositoryClass="Tw\PollBundle\Entity\PollRepository")
*/
class Poll
{
/**
* @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=255)
*/
private $title;
/**
* @var Tw\PlayerBundle\Entity\World
*
* @ORM\ManyToOne(targetEntity="Tw\PlayerBundle\Entity\World")
* @ORM\JoinColumn(nullable=true)
*/
private $world;
/**
* === Id ===
*/
public function getId()
{
return $this->id;
}
/**
* === title ===
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
public function getTitle()
{
return $this->title;
}
/**
* === world ===
*/
public function setWorld($world)
{
$this->world = $world;
return $this;
}
public function getWorld()
{
return $this->world;
}
}
PlayerPoll entity
<?php
namespace Tw\PlayerBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Tw\PollBundle\Entity\Poll;
/**
* PlayerPoll
*
* @ORM\Table(name="players_polls")
* @ORM\Entity(repositoryClass="Tw\PlayerBundle\Entity\PlayerPollRepository")
*/
class PlayerPoll
{
/**
* @var Player
*
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Player", inversedBy="polls")
*/
private $player;
/**
* @var Tw\PollBundle\Entity\Poll
*
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Tw\PollBundle\Entity\Poll")
*/
private $poll;
/**
* === Player ===
*/
public function setPlayer(Player $player)
{
$this->player = $player;
return $this;
}
public function getPlayer()
{
return $this->player;
}
/**
* === Poll ===
*/
public function setPoll(Poll $poll)
{
$this->poll = $poll;
return $this;
}
public function getPoll()
{
return $this->poll;
}
}
PlayerWorld Entity
<?php
namespace Tw\PlayerBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* PlayerWorld
*
* @ORM\Table(name="players_worlds")
* @ORM\Entity(repositoryClass="Tw\PlayerBundle\Entity\PlayerWorldRepository")
*/
class PlayerWorld
{
/**
* @var integer
*
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Player", inversedBy="worlds")
*/
private $player;
/**
* @var integer
*
* @ORM\Id
* @ORM\ManyToOne(targetEntity="World")
*/
private $world;
/**
* === Player ===
*/
public function setPlayer(Player $player)
{
$this->player = $player;
return $this;
}
public function getPlayer()
{
return $this->player;
}
/**
* === World ===
*/
public function setWorld(World $world)
{
$this->world = $world;
return $this;
}
public function getWorld()
{
return $this->world;
}
}
And finally the fonction used in the player repository
/**
* Finds one player using various criterias
*
* @param array.string - criteria
*
* @return Player|null
*/
public function findOneBy(array $criteria)
{
// build base query
$qb = $this->createQueryBuilder('player')
->join('player.worlds', 'worlds')
->join('worlds.world', 'world')
->join('player.polls', 'polls')
->join('polls.poll', 'poll')
->addSelect('worlds, world, polls, poll');
// add select criterias to query
foreach ($criteria as $field => $value) {
$qb->andWhere("player.$field = :$field")
->setParameter($field, $value);
}
// run query
$q = $qb->getQuery();//->useResultCache(true, 120, 'player_'.serialize($criteria));
$player = $q->getResult();
// return player only if one was found
if(is_array($player) && count($player) === 1)
return $player[0];
return null;
}
I've removed some not related attributes / functions. Any idea on what I'm doing wrong ? Thanks
Upvotes: 0
Views: 102
Reputation: 2527
I don't see a reason to have PlayerPoll and PlayerWorld Entities. You only need Player, Poll and World.
Player Entity will be linking both Poll and World using $polls
and $worlds
properties.
You can then get the Player repository and use the standard find() to get the Player with any set of criteria you want.
Please let me know if I didn't get your question directly.
Have a look at the bidirectional references docs as well as association mapping.
Upvotes: 0