【问题标题】:PHP : Association error using doctrinePHP:使用学说的关联错误
【发布时间】:2014-05-13 15:43:39
【问题描述】:

我在学说 2 中遇到了以下问题:我想加入我的世界实体,将实体投票给我的玩家实体。因此,经过一些尝试,它在数据库中运行良好,当使用我的自定义 findOneBy 时,我遇到:tw_player.security.error.[Semantical Error] line 0, col 170 near 'polls INNER JOIN': Error: Class Tw\PlayerBundle\ Entity\Player 没有名为 polls 的关联。

玩家实体:

<?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;
    }
}

世界实体

<?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;
    }
}

投票实体

<?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 实体

<?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 实体

<?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;
    }

}

最后是播放器存储库中使用的函数

/**
 * 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;
}

我删除了一些不相关的属性/功能。知道我做错了什么吗? 谢谢

【问题讨论】:

  • 如果你var_dump($q-&gt;getSQL()); 它显示什么?确定当您调用自定义 findBy 时,Criteria 元素作为字段存在于您的实体中? (你也可以转储)
  • 错误发生在$q = $qb->getQuery();之前所以 var_dump($q->getSQL());不执行。是的,标准存在。
  • 为了更精确,错误似乎出现在 ->join('player.polls', 'polls') 和 ->join('polls.poll', 'poll') 行存储库。
  • 您是否通过php app/console doctrine:schema:validate 验证了您的架构?
  • 所有 ArrayCollections 都需要在实体的构造函数中创建。我认为这不会导致您的问题,但也许。并删除你的缓存。

标签: php symfony doctrine-orm doctrine-odm


【解决方案1】:

我认为没有理由拥有 PlayerPoll 和 PlayerWorld 实体。您只需要 Player、Poll 和 World。

玩家实体将使用$polls$worlds 属性链接投票和世界。

然后您可以获取 Player 存储库并使用标准 find() 来获取具有您想要的任何条件的 Player。

如果我没有直接收到您的问题,请告诉我。

看看the bidirectional references docsassociation mapping

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 2012-10-08
    • 1970-01-01
    相关资源
    最近更新 更多