dsa2c2255888 2014-06-17 09:04
浏览 91
已采纳

正确的对象实例化/持久性排序和注释

My use case is simple. There are two entities: Server and Client. Each Server can have Multiple Clients. This should be pretty simple really...

What I need

I require the following as a result of this:

  • Calling $server->getClients() will return all Client entities associated with that server
  • Calling $client->getServer() will return the Server entity associated with that client

I believe that, according to the documentation, this is a One-To-Many Bidirectional relationship.

A one-to-many association has to be bidirectional, unless you are using an additional join-table. This is necessary, because of the foreign key in a one-to-many association being defined on the “many” side. Doctrine needs a many-to-one association that defines the mapping of this foreign key.

The docs above give a really simple example of Product and Feature entities, which I have attempted to adopt for my Server to Client use case.

The Problem

Firstly, I can't seem to get the annotations right to create a Client entity, assign it to a newly created Server entity, then persist / save them. The Client entity always has null for the server_id attribute. What is the ordering required? Why are my annotations not working?

Secondly, I can't figure out if I need a join table to be able to do $client->getServer() or the other way around: $server->getClients(). Do I need a join table to fulfil the above criteria? I tried to add a join table anyway, but no join table was actually created when running doctrine orm:schema-tool:update.

The Code

Note: I do have Setters / Getters on both ends for Client and Server

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

I have tried multiple combinations of creating Client and Server entities, calling $server->addClient(new Client)); etc, persisting both in different orders and more.

What exactly am I doing wrong? Why do I have null? What do I need to fix my annotations and object persistence in order to achieve the methods ::getClients() and ::getServer() being made available to me?

  • 写回答

1条回答 默认 最新

  • dongni3854 2014-06-17 09:25
    关注

    You need to ensure the mutators (getter and setter) methods are present (afaik, at least in my doctrine version) the getter setter are not generated by doctrine, you need to implement them. And the array collection must be in the contstructor:

    in Server Entity:

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

    Your entity is looking good (annotations), not sure wether you really need repositoryClass="App\Model\Repository\ClientRepository".

    The order of things is not important as long as you have the entity persisted once. An entity is automatically persisted when fetched by findBy or when added to an already persisted entity. Example:

    $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
    

    Update:

    Sorry I didn't read that you already have getters and setters.

    When updating the schema, try the following:

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

    Update:

    Found your error:

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

    server_id is not present. Server::id is, but not Server::server_id :-)

    Correct:

    * @ORM\JoinColumn(name="id", referencedColumnName="id")
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料