My use case is simple. There are two entities:
Server
andClient
. Each Server can have Multiple Clients. This should be pretty simple really...
I require the following as a result of this:
$server->getClients()
will return all Client
entities associated with that server$client->getServer()
will return the Server
entity associated with that clientI 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.
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
.
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?
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")