I'm using doctrine and I added a join to an entity. After the join a setter (setcustomerorderID) is no longer being saved when they data is saved to the database. Every other column gets saved. The join is correct and $this->data->orderId is set.
The code works without the join.
I added the relationship as follows:
/**
* #var orders
*
* #ORM\ManyToOne(targetEntity="FYP\CartBundle\Entity\Orders", inversedBy="CustomerDesign")
* #ORM\JoinColumn(name="customerorder_id", referencedColumnName="orderID")
*/
private $orders;
On the reverse side:
/**
* #var customerDesign
*
* #ORM\OneToMany(targetEntity="FYP\BaseDesignBundle\Entity\CustomerDesign", mappedBy="orders")
*/
private $customerDesign;
Attempting to set customerorder_id in a different file.
$cd = new CustomerDesign();
$cd->setcustomerID($this->data->customerId);
$cd->setcustomerorderID($this->data->orderId);
$cd->setQuantity($cartItem->getQuantity());
$cd->setProductVariant($cartItem->getProductVariant());
$cd->setDesignData($cartItem->getDesignData());
$cd->setRequestProof($cartItem->getRequestProof());
$cd->setComments($cartItem->getComments());
$cd->setSpecialComments($cartItem->getSpecialComments());
$cd->setgiftSetID($cartItem->getgiftSetID());
$cd->setgiftSetParent($cartItem->getgiftSetParent());
$cd->setisBlank($cartItem->getisBlank());
$cd->setbasedOn($cartItem->getbasedOn());
$cd->setApprovalData($cartItem->getApprovalData());
$cd->setdesignName('');
$this->em->persist($cd);
$this->em->flush();
This $cd->setcustomerorderID($this->data->orderId); is not working at all.
setcustomerorderID Looks like:
/**
* Set customerorder_id
*
* #param integer $customerorder_id
*/
public function setcustomerorderID($customerorder_id)
{
$this->customerorder_id = $customerorder_id;
}
Thanks.
Change your code here:
/**
* #var order
*
* #ORM\ManyToOne(targetEntity="FYP\CartBundle\Entity\Orders", inversedBy="CustomerDesign")
* #ORM\JoinColumn(name="customerorder_id", referencedColumnName="orderID")
*/
private $order;
As far as I understand, according your relationships, you might have one order to many customer designs.
Instead of ID, you need to assign Entity.
Details can be found in Doctrine documentation.
<?php
$order = new Order();
$design = new CustomerDesign();
$design->setOrder($order);
...
public function setOrder($order)
{
$this->order = $order;
}
...
$this->em->persist($order);
$this->em->persist($design);
$this->em->flush();
You created relationships, and it means customerorder_id is under ORM control.
Related
So I have a following single inheritance table defined:
/**
* #Entity
* #Table(name="listKeys")
* #InheritanceType("SINGLE_TABLE");
* #DiscriminatorColumn(name="parent", type="string")
* #DiscriminatorMap({"Type1" = "Something1", "Type2" = "Something2"})
*/
abstract class ListKey
{
/**
* #OneToMany(targetEntity="KeyListValue", mappedBy="listKey", cascade={"persist", "remove"}, orphanRemoval=true)
*/
private Collection $listValues;
/**
* #ManyToOne(targetEntity="KeyListValue")
* #JoinColumn(name="defaultKeyListValueId")
*/
private ?KeyListValue $defaultKeyListValue = null;
}
With the list options defined as:
/**
* #Entity
* #Table(name="keyListValues")
*/
class KeyListValue
{
/**
* #Column(type="string")
*/
private $label;
/**
* #ManyToOne(targetEntity="ListKey", inversedBy="listValues", cascade={"persist"})
* #JoinColumn(name="caKeyId")
*/
private ListKey $listKey;
}
Before adding list values to a key, persisting and flushing worked ok, so the key would get inserted first after the commit order calculation. But once I added a new column default key list value, the commit order changes, and key list values try to get inserted first so the transaction fails.
Workaround is that I use flush() after creating new key and the adding the list values but this is problematic since ListKey also has association with some other entities which are not persisted yet at the time of flush so cascades would have to be declared and I don't want that. Any suggestion on how I can redefine this relationship better or a better workaround so the commit order would first insert keys?
I have a many-to-many-relation, and when I load an entity that is on one side this relation, I expect to see as its property the ArrayCollection of related entities on another side. However, this does not happen - the ArrayCollection loaded has no elements in it, while in the database I can see the related entries. What could be the reason?
Here is my code:
One side of the relation, ConsolidatedReport class:
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="P24\Response", inversedBy="consolidatedReports")
* #ORM\JoinTable(name="con_rprt_responses")
*/
private $responses;
Another side of the relation, Response class:
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="P24\ConsolidatedReport\ConsolidatedReport", mappedBy="responses")
*/
private $consolidatedReports;
Here is the function I run to get an instance of ConsolidatedReport. This function sits inside a service that is being called from container:
/**
* Picks the consolidated report with given id.
*
* #param string $id
*
* #return ConsolidatedReport
*
* #throws NonExistentConsolidatedReportException if the survey doesn't exist
*/
public function pick($id)
{
$report = $this->repository->findOneBy(array('id' => $id));
if (!$report) {
throw new NonExistentConsolidatedReportException($id);
}
return $report;
}'
In the database, there is "con_rprt_responses" table with two columns "consolidated_reports_id" and "response_id". However, in profiler I do not see any queries to that table.
What could go wrong here?
UPDATE:
Please see my answer to this question below, that worked for me.
I added fetch="EAGER" to the $responses property of ConsolidatedReport class, and it worked.
The code now looks like this:
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="P24\Response", inversedBy="consolidatedReports", fetch="EAGER")
* #ORM\JoinTable(name="con_rprt_responses")
*/
private $responses;
More info here:
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-objects.html#by-eager-loading
Still if someone knows why the collection of related entity would not load without explicitly specifying EAGER fetching - please share your knowledge, it is highly appreciated!
If you specify the joinColumns, does this solve your problem?
/**
* #ORM\ManyToMany(targetEntity="P24\Response", inversedBy="consolidatedReports")
* #ORM\JoinTable(name="con_rprt_responses",
* joinColumns={#ORM\JoinColumn(name="consolidated_reports_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="response_id", referencedColumnName="id")}
* )
*/
The *toMany properties have to be initialized with an ArrayCollection.
public function __construct() {
$this->responses = new \Doctrine\Common\Collections\ArrayCollection();
$this-> consolidatedReports = new \Doctrine\Common\Collections\ArrayCollection();
}
In case you have more then single query to fetch the same objects using Doctrine try to use:
$entityManager->clear();
in between, to fix "missing" entities. It isn't solution "as is", however can give you an idea something wrong in chain of your queries.
So let's say we use a User and a Ticket class. They are normal entities, nothing fancy.
The User class contains this lines:
/**
* #ORM\ManyToMany(targetEntity="Ticket", mappedBy="collaborateurs")
**/
private $tickets;
The Ticket class contains this:
/**
* #ORM\ManyToMany(targetEntity="User", inversedBy="tickets")
* #ORM\JoinTable(name="users_to_tickets")
**/
private $collaborateurs;
To get all ticket's a user has I can just call the getTickets() function created by Symfony. As far as good. The Ticket class has a few additional fields like updated which is a DateTime field or status which is an integer. I would like to sort those tickets by status DESC and updated DESC
I know I could just make a function in the repository like findTicketsByUserOrderedByFooBar($user), but I'm wondering if there isn't a better way.
If you always want your tickets to be in that order you can set and orderBy on the association.
/**
* #ORM\ManyToMany(targetEntity="Ticket", mappedBy="collaborateurs")
* #ORM\OrderBy({"status" = "DESC", "updated" = "DESC"})
**/
private $tickets;
You can add an Helper method to your User entity and sort/filter DIRECTLY on the ArrayCollection with doctrine2 criteria. Something like this:
/**
* this return a ArrayCollection
*/
public function getTicketsByUserOrderedByFooBar()
{
$criteria = Criteria::create()
->orderBy(array('foo'=>'DESC','bar' =>'ASC'))
return $this->tickets->matching($criteria);
}
/**
* this return a ArrayCollection
*/
public function getTicketsByUserOrderedBytitle()
{
$criteria = Criteria::create()
->orderBy(array('title'=>'DESC'))
return $this->tickets->matching($criteria);
}
See also this
Hope this help.
Creating a function the way you suggested would be the suggested approach.
I am trying to create a many-to-many foreign key table relation targeting the same entity.
I have successfully created relations with other entities but I'm having trouble when targeting the same entity.
I read a few stack overflow questions and answers and saw what I was doing was possible..
I based my class of this example - the table unit_relations is empty when i add a parent, but works when I add a child to a unit. I'm assuming because the field has the inversedBy annotation.
What do I need to add to allow bi-drectional updating/inserting?
I tried swapping the joinColums like this answer - nothing...
--
/**
* Unit
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Acme\DemoBundle\Entity\UnitRepository")
*/
class Unit
{
....
/**
* #ORM\ManyToMany(targetEntity="Unit", inversedBy="parents")
* #ORM\JoinTable(name="unit_relations",
* joinColumns={#ORM\JoinColumn(name="unit_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="child_unit_id", referencedColumnName="id")}
* )
*/
private $children;
/**
* #ORM\ManyToMany(targetEntity="Unit", mappedBy="children")
*/
private $parents;
}
is adding inversedBy instead of having mappedBy, with the join columns also swapped, the proper way to do it?
Can someone explain this?
/**
* #ORM\ManyToMany(targetEntity="Unit", inversedBy="parents")
* #ORM\JoinTable(name="unit_relations",
* joinColumns={#ORM\JoinColumn(name="unit_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="child_unit_id", referencedColumnName="id")}
* )
*/
private $children;
/**
* #ORM\ManyToMany(targetEntity="Unit", inversedBy="children")
* #ORM\JoinTable(name="unit_relations",
* joinColumns={#ORM\JoinColumn(name="child_unit_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="unit_id", referencedColumnName="id")}
* )
*/
private $parents;
EDIT
as requested here's the code showing how I create the relation. I just realized it may because the entity doesn't have an id yet since I'm adding the relation on its creation...
$unit = new \Acme\DemoBundle\Entity\Unit();
/* #var $parentUnit \Acme\DemoBundle\Entity\Unit */
$parentUnit = $this->getDoctrine()->getRepository('AcmeDemoBundle:Unit')->findById($request->get('unitId'));
$unit->addParent($parentUnit);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($unit);
$entityManager->flush();
It doesn't matter, that there is no ID, when you add a parent relations.
I cant in detail explain why this happens, but i think the main problem is, that in Many-To-Many Self-Referencing the attribute with JoinTable annotation is potentially the Master-Entity. You can say, that it "holds" all other relations to this Entity.
You can recieve the bi-directional updating/inserting while changing the function $unit->addParent($parent). Change it as follows:
public function addParent($parent)
{
$this->parents[] = $parent;
$parent->addChild($this); // Add the relation in the proper way
}
That should work fine!
Regards!
I have two entities: AudioPlaylist and AudioTrack.
AudioPlaylist.php:
/**
* #ORM\ManyToMany(targetEntity = "AudioTrack", inversedBy = "audioPlaylists")
* #ORM\JoinTable(name = "audioplaylist_audiotrack")
*
* #var ArrayCollection
*/
protected $audioTracks;
AudioTrack.php:
/**
* #ORM\ManyToMany(targetEntity = "AudioPlaylist", mappedBy = "audioTracks")
*
* #var ArrayCollection
*/
protected $audioPlaylists;
My problem is that when I call $audioTrack->addAudioPlaylist($audioPlaylist), the audioplaylist_audiotrack table doesn't get updated. I'm expecting a new row to be added to the table signifying the relationship between the two entities. Everything works fine for the inverse though $audioPlaylist->addAudioTrack($audioTrack) adds a new row.
I'm making sure to persist $audioTrack and flush the entity manager, but no luck, so I assume there must be something wrong with my annotations (I'm using this example from the Doctrine docs). Any ideas?
This is probably because you have not set the cascade property for your inverse side. You must define cascading explicitly for Doctrine2 to persist any related entities.
/**
* #ORM\ManyToMany(targetEntity = "AudioPlaylist",
* mappedBy = "audioTracks",
* cascade = {"persist", "remove"})
*
* #var ArrayCollection
*/
protected $audioPlaylists;
Make sure you also add your AudioTrack to AudioPlaylist as well, when calling AudioTrack::addAudioPlaylist():
public function addAudioPlaylist(AudioPlaylist $playlist)
{
$this->getAudioPlaylists()->add($playlist);
$playlist->getAudioTracks()->add($this);
}