对于一个Symfony2项目,我必须在博客文章和所谓的平台之间建立一种关系。平台根据您用于查看站点的域定义特定的筛选器。例如:如果您通过url first-example.com加入站点,则站点将只提供连接到此特定平台的博客帖子。
为此,我创建了两个实体Post和Platform。之后,我用多对多关系将它们映射在一起。我正在尝试通过这种多对多关系从relationship的EntityRepository
中的内置函数findBy()
中检索数据。
// every one of these methods will throw the same error
$posts = $postRepo->findBy(array('platforms' => array($platform)));
$posts = $postRepo->findByPlatforms($platform);
$posts = $postRepo->findByPlatforms(array($platform));
其中$postRepo
是Post
实体的正确存储库,$platform
是现有Platform
对象。
无论哪种方式:我最终都会得到以下错误:
ErrorException: Notice: Undefined index: joinColumns in [...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line 1495
[...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:1495
[...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:1452
[...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:1525
[...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:1018
[...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:842
[...]/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php:157
[...]/src/Foobar/BlogBundle/Tests/ORM/PostTest.php:102
是否有可能以这种方式检索多对多关系中的相关实体,或者我是否被迫自己编写这些函数?奇怪的是: Doctrine不会抛出任何像“这不可能”这样的错误,而是抛出一个内部E_NOTICE
。这就是为什么我认为这应该是可能的,但我在这里遗漏了一些要点。
剥离到有趣的部分,这两个实体看起来像这样。
<?php
namespace Foobar\CommunityBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
// [...] other namespace stuff
/**
* @ORM\Entity(repositoryClass="Foobar\CommunityBundle\Entity\Repository\PlatformRepository")
* @ORM\Table(name="platforms")
*/
class Platform
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
// [...] other field stuff
}
<?php
namespace Foobar\BlogBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
// [...] other namespace stuff
/**
* @ORM\Entity(repositoryClass="Foobar\BlogBundle\Entity\Repository\PostRepository")
* @ORM\Table(name="posts")
*/
class Post implements Likeable, Commentable, Taggable, PlatformAware
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity="Foobar\CommunityBundle\Entity\Platform", cascade={"persist"})
* @ORM\JoinTable(name="map_post_platform",
* joinColumns={@ORM\JoinColumn(name="post_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="platform_id", referencedColumnName="id")}
* )
*/
protected $platforms;
// [...] other fields
/**
* Constructor
*/
public function __construct()
{
// [...]
$this->platforms = new ArrayCollection();
}
}
当然还有composer.json文件(以及精简到相关行)
{
[...]
"require": {
"php": ">=5.3.3",
"symfony/symfony": "2.1.*",
"doctrine/orm": ">=2.2.3,<2.4-dev",
"doctrine/doctrine-bundle": "1.0.*",
"doctrine/doctrine-fixtures-bundle": "dev-master",
[...]
},
[...]
}
发布于 2012-11-23 00:40:59
这是很有可能的,但Stock Doctrine Repository不是这样工作的。
您有两个选项,具体取决于您的上下文:
在存储库中编写一个自定义方法。
class PostRepository extends EntityRepository
{
public function getPosts($id)
{
$qb = $this->createQueryBuilder('p');
$qb->join('p.platform', 'f')
->where($qb->expr()->eq('f.id', $id));
return $qb;
}
}
或者使用platform对象中的默认getter方法。
$posts = $platform->getPosts();
你“剥离到有趣的部分”,所以如果你有这个方法,那就不明显了,但它通常是在
app/console doctrine:generate:entities
发布于 2014-09-22 21:11:36
另一种方式,可能是在不使用ID的情况下进行一些OO/cleaner:
public function getPosts(Platform $platform)
{
$qb = $this->createQueryBuilder("p")
->where(':platform MEMBER OF p.platforms')
->setParameters(array('platform' => $platform))
;
return $qb->getQuery()->getResult();
}
更好的方法名应该是findPostsByPlatform
发布于 2014-08-17 22:51:28
这个问题似乎是你想要双向的ManyToMany关系的问题(现在是裁剪)。使用MappedBy创建双向功能:
http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#many-to-many-bidirectional
实用:
你的一个实体是拥有的,另一个是相反的。在您的示例中,名为Post的实体是owning侧,而名为Platform的实体是反向侧。
拥有方设置:
Class Post {
...
/**
* @ManyToMany(targetEntity="Platform")
* @JoinTable(name="map_post_platform",
* joinColumns={@JoinColumn(name="post_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="platform_id", referencedColumnName="id", unique=true)} )
**/
protected $platforms;
...
public function Post() {
$this->platforms= new ArrayCollection();
}
...
public function assignToPlatform($platform) {
$this->platforms[] = $platform;
}
...
public function getPlatforms() {
return $this->platforms;
}
}
反面设置:
Class Platform {
...
/**
* @ManyToMany(targetEntity="Post", mappedBy="platforms")
**/
protected $posts;
...
public function Platform() {
$this->posts= new ArrayCollection();
}
...
public function getPosts()
{
return $this->posts;
}
}
从其中一个侧面开始检索实体数组的示例:
$post->getPlatforms();
$platform->getPosts();
https://stackoverflow.com/questions/13343533
复制相似问题