【问题标题】:Correct object instantiation / persistence ordering and annotations正确的对象实例化/持久性排序和注释
【发布时间】:2014-06-17 09:04:05
【问题描述】:

我的用例很简单。有两个实体:ServerClient每个服务器可以有多个客户端。这应该很简单真的......

我需要什么

因此,我需要以下内容:

  • 调用 $server->getClients() 将返回与该服务器关联的所有 Client 实体
  • 调用 $client->getServer() 将返回与该客户端关联的 Server 实体

我相信,根据documentation,这是一个一对多的双向关系。

一对多关联必须是双向的,除非您使用额外的连接表。这是必要的,因为一对多关联中的外键是在“多”端定义的。 Doctrine 需要一个多对一的关联来定义这个外键的映射。

上面的文档给出了一个非常简单的 example ProductFeature 实体,我试图将其用于我的 ServerClient 用例。

问题

首先,我似乎无法获得正确的注释来创建Client 实体,将其分配给新创建的Server 实体,然后持久化/保存它们。 Client 实体始终具有 null 用于 server_id 属性。需要什么订货?为什么我的注释不起作用?

其次,我不知道是否需要一个连接表才能执行$client->getServer() 或相反的操作:$server->getClients()我需要一个连接表来满足上述条件吗?我还是尝试添加一个连接表,但在运行doctrine orm:schema-tool:update 时实际上没有创建连接表。

代码

注意:我在 ClientServer 的两端都有 Setter / Getter

/**
 * Class Server
 *
 * @ORM\Table(name="servers")
 * @ORM\Entity(repositoryClass="App\Model\Repository\ServerRepository")
 */
class Server
{
   /**
    * @var integer
    *
    * @ORM\Column(name="id", type="integer", nullable=false)
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="IDENTITY")
    */
    private $id;

   /**
    * @var ArrayCollection
    *
    * @ORM\OneToMany(targetEntity="App\Model\Entity\Client", mappedBy="server", cascade={"persist", "remove"})
    */
    private $clients;
}

/**
 * Class Client
 *
 * @ORM\Table(name="clients")
 * @ORM\Entity(repositoryClass="App\Model\Repository\ClientRepository")
 */
class Client
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

   /**
    * @var Server
    *
    * @ORM\OneToMany(targetEntity="App\Model\Entity\Server", inversedBy="client")
    * @ORM\JoinColumn(name="server_id", referencedColumnName="id")
    */
    private $server;
}

我尝试了多种组合,创建ClientServer 实体,调用$server->addClient(new Client)); 等,以不同的顺序保持等等。

究竟我做错了什么?为什么我有null?为了实现::getClients()::getServer() 方法可供我使用,我需要修复我的注释和对象持久性吗?

【问题讨论】:

  • 感谢您对另一个问题的评论,我的回答的哪一部分解决了您的问题? :)
  • @DanFromGermany 不仅我的 setter / getter 不正确(我在文档中看不到这个要求),而且 ManyToOne 是错误的方式。您的回答非常有用,并且可能对未来的用户也有用。此外,id 更改是必需的。谢谢!
  • 我不确定server_id / id 的事情。很高兴它帮助了你!教义不是那么容易入门,但值得学习。

标签: php orm doctrine-orm one-to-many


【解决方案1】:

您需要确保存在 mutators(getter 和 setter)方法(afaik,至少在我的学说版本中)getter setter 不是由学说生成的,您需要实现它们。并且数组集合必须在构造函数中:

Server实体中:

public function __construct() {
    $this->clients = new ArrayCollection();
}

public function addClient(Client $client) {
    $this->clients->add($client);
    return $this;
}

public function removeClient(Client $client) {
    if ($this->clients->contains($client)) {
        $this->clients->remove($client);
    }
    return $this;
}

public function getClients() {
    return $this->clients;
}

您的实体看起来不错(注释),不确定您是否真的需要repositoryClass="App\Model\Repository\ClientRepository"

只要实体持久化一次,事情的顺序并不重要。 当findBy 获取或添加到已经持久化的实体时,实体会自动持久化。示例:

$server = $entityManager->getRepository('App\Model\Entity\Server')
                        ->findOneByName('test');

$server->addClient(new Client());

// client and server are now both persisted

$entityManager->flush();

// stuff is now saved in the database

更新:

抱歉,我没有读到您已经有 getter 和 setter。

更新架构时,请尝试以下操作:

./doctrine orm:clear-cache:metadata
./doctrine orm:schema-tool:update
./doctrine orm:generate-proxies

更新:

发现你的错误:

* @ORM\JoinColumn(name="server_id", referencedColumnName="id")

server_id 不存在。 Server::id 是,但不是 Server::server_id :-)

正确:

* @ORM\JoinColumn(name="id", referencedColumnName="id")

【讨论】:

    猜你喜欢
    • 2023-03-27
    • 2010-09-29
    • 2015-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 2017-10-10
    相关资源
    最近更新 更多