I have a problem, I have a table (downloads) with two fields: Token (primary key) and value.
I have my entity Downloads with these methods (only show token methods, value works right):
/**
* #var string
*
* #ORM\Column(name="token", type="string", length=45, nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $token;
/**
* Set token
*
* #param string $token
* #return Downloads
*/
public function setToken($token)
{
$this->token = $token;
return $this;
}
/**
* Get token
*
* #return string
*/
public function getToken()
{
return $this->token;
}
But, when I do this in my controller:
$em = $this->getDoctrine()->getManager();
$Download = new Downloads();
$Download->setToken($token);
$Download->setValid($now);
$em->persist($Download);
$em->flush();
Object is well created, but in my database Valid is stored correctly, and token is store empty!!
if I see the values, util $em->flush(); object download has two correct values, but after this, token (primary key) disappear his value.
How can I do?
try to remove the #ORM\GeneratedValue
(strategy="IDENTITY") because it is the one that causes doctrine to generate value for Token.
hope it helps :)
you have to create auto increment for your columns like this
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
Stupid answer, but have you tried:
Clearing your Symfony cache
Restarting Apache
It might have to do with Doctrine caching.
Related
As I cannot post the real code here, im using a substitute, that basically is the same, so please dont wonder if you find syntactic errors.
I have the following setup:
PHP 7.0,Symphony,Doctrine which is working with a MySQL database.
The classes are as following:
/*
* #ORM\Table(name="Postoffice")
* #ORM\Entity(repositoryClass="\AppBundle\Repsoitory\PostOfficeRepository")
*/
class Postoffice
{
/**
* Holds the Doctrine entity manager for database interaction
* #var EntityManager $em
*/
protected $em;
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(stragegy="AUTO")
*/
private $id;
/** #var ArrayCollection
* #ORM\ManyToMany(targetEntity="MailBox")
* #ORM\JoinTable(name="PostOfficeToMailBoxMapping",
* joinColumns={#ORM\JoinColumn(name="PostOfficeId",referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="MailBoxId",referencedColumnName="id",unique=true)})
*/
private $packets;
public function __construct(EntityManager $em)
{
$this->$packets = new ArrayCollection();
$this->em = $em;
}
}
/*
* #ORM\Table(name="PostStorage")
* #ORM\Entity(repositoryClass="\AppBundle\Repsoitory\PoststorageRepository")
*/
class Poststorage
{
/**
* Holds the Doctrine entity manager for database interaction
* #var EntityManager $em
*/
protected $em;
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(stragegy="AUTO")
*/
private $id;
/** #var ArrayCollection
* #ORM\ManyToMany(targetEntity="MailBox")
* #ORM\JoinTable(name="PostStorageToMailBoxesMapping",
* joinColumns={#ORM\JoinColumn(name="PoststorageId",referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="MailBoxId",referencedColumnName="id",unique=true)})
*/
private $MailBoxes;
public function __construct(EntityManager $em)
{
$this->MailBoxes = new ArrayCollection();
$this->em = $em;
}
public function delete()
{
//remove each box on its own
foreach ($this->Mailboxes as $iterMailBox)
$this->em->remove($iterMailBox);
$this->em->remove($this);
$this->em->flush();
}
}
/*
* #ORM\Table(name="MailBox")
* #ORM\Entity(repositoryClass="\AppBundle\Repsoitory\MailBoxRepository")
*/
class MailBox
{
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(stragegy="AUTO")
*/
private $id;
/** #var ArrayCollection
* #ORM\ManyToMany(targetEntity="Letter")
* #ORM\JoinTable(name="MailBoxToLetterMapping",
* joinColumns={#ORM\JoinColumn(name="MailBoxId",referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="LetterId",referencedColumnName="id",unique=true)})
*/
private $mailsInBox;
__construct()
{
$mailsInBox = new ArrayCollection();
}
}
class Letter
{
/**
* Holds the Doctrine entity manager for database interaction
* #var EntityManager $em
*/
protected $em;
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(stragegy="AUTO")
*/
private $id;
//lets assume this is a string
private $letterContent;
}
Now what im trying to model here is the following:
The Mailbox is somethinglike a container for a bunch of letters.
And a single mailbox can be at a certain point in its life only ba at one place at a time, and only at one. But the containers can be moved in between these two places. i.e. the Postoffice and the PostStorage.
The creation of these Mappings in the SQL database are not the Problem.
Letter N ------ 1 Mailbox (unidirectional with Join Tables)
MailBox N ------1 PostOffice or PostStorage (unidirectional with Join Tables)
The problem comes with the following feature. I want to be able to delete/merge/split individual containers and letters to and from containers and letters.
If im simply trying to delete a letter or Mailbox by using:
$em->remove($InstanceOfLetterOrMailBox);
$em->flush();
im getting the, in the title mentioned, "Integrity constraint violation".
As the Mailboxes can be at different places, i would really like to avoid to add refereces to the owner in the class, as it would bloat up the size of the class code very much, because i would like to add more places for the mailboxes to reside at in the future.
Ive spend the last few hours trying out different combinations of
Ondelete = CASCADE on different classes, but all I managed to do was either delete all classes from the db or not making a single delete, if im not getting the mentioned Error message back.
If you need more information let me know.
Thanks in advance.
I've found a solution to the problem. The problem was not that I was using the Cascade options incorrectly, but that i was trying to delete from an empty mailbox. In other words, I've been using a wrong index for my delete operation. The correct settings i am using now :
"cascade={"remove","persist"},orphanRemoval=true"
as a part of the many to many tag above the collection
There is probably something I did understand with Doctrine association.
I have a first class :
class FitComments
{
/**
* #var integer
*
* #ORM\Column(name="ID", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="SEQ_FIT_COMMENTS", allocationSize=1, initialValue=1)
*/
private $id;
/**
*
* #ORM\OneToMany(targetEntity="FitCommentsId",mappedBy="comments",cascade={"persist"})
*
*/
private $elements;
/****/
public function __construct()
{
$this->elements=new ArrayCollection();
}
public function getElements()
{
return $this->elements;
}
....
}
And a another Class, the list of elements ID that the comments is link.
/**
* FitCommentsId
* #ORM\Entity
*/
class FitCommentsId
{
/**
* #var integer
*
* #ORM\Column(name="ID", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="SEQ_FIT_COMMENTS_ID", allocationSize=1, initialValue=1)
*/
private $id;
/**
*
* #ORM\ManyToOne(targetEntity="FitComments",inversedBy="elements")
* #ORM\JoinColumn(name="COMMENTS_ID",referencedColumnName="ID")
*/
private $comments;
....
}
I use :
$comments=new FitComment();
$commentId=new FitCommentId();
....
$comments->getElements()->add($commentId);
....
$entityManager->persist($comment);
$entityManager->flush();
But I have a error. $commentId->comments is null. It must be filled with $comment->id normally.
If I must filled manually $commentId->comments, association is not very usefull.
Perhaps I don't understand mechanism.
Note : the SGDB is Oracle.
Try persisting the $commentId also like this:
$comment = new FitComment();
$commentId = new FitCommentId();
....
$comment->getElements()->add($commentId);
....
$entityManager->persist($commentId);
$entityManager->persist($comment);
$entityManager->flush();
No I can't do a 'persist' to $commentId first, because 'persist' to $comment class initiate Oracle sequence for the Id of $comments. (I'm not sure it's very clean what I say....)
'commentID->comments' is link to 'comment->id', and is not null.
I must create $comment at first, and after, create the $commentId.
I know that Doctrine use Sequence before saving record, in persist command. Perhaps I can do a persist without flush at first, and at the end of $commentId recording, do a flush.
I have a table with some fields and the first is my primary key, called token.
I need that token isn't automatically, so, I want to set this value. For example,
$em = $this->getDoctrine()->getManager();
$object->setToken("first");
$object->setValue("123");
$em->persist($object);
$em->flush();
But, in my DB, always token is null, why?
When I do flush, token value disappear.
In my entity, token is declared:
/**
* #var string
*
* #ORM\Column(name="token", type="string", length=45, nullable=false)
* #ORM\Id
*/
private $token;
/**
* Set token
*
* #param string $token
* #return Downloads
*/
public function setToken($token)
{
$this->token = $token;
return $this;
}
/**
* Get token
*
* #return string
*/
public function getToken()
{
return $this->token;
}
Try with ORM\GeneratedValue
/**
* #var string
*
* #ORM\Column(name="token", type="string", length=45, nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $token;
Maybe this could help Doctrine2 Primary Key.
And if you did not create your table using the doctrine command check if $token set to Primary Key in your database.
I have a user object I am trying to insert via Doctrine.
The key fields are
/**
* #ORM\Column(type="integer", name="id")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $userId;
/**
* #ORM\Id
* #ORM\Column(type="string", name="login_name")
*/
private $loginName;
/**
* #ORM\Column(type="string", name="display_name")
*/
private $name;
In my controller code I can echo out the value of the $loginName field via the getLoginName() method on the object.
/**
* #param mixed $loginName
*/
public function setLoginName($loginName)
{
$this->loginName = $loginName;
}
/**
* #return mixed
*/
public function getLoginName()
{
return $this->loginName;
}
You can see the Controller code to do the insert here.
if ($request->getMethod() == 'POST') {
$form->bind($request);
$login = $form->getData();
$factory = $this->get('security.encoder_factory');
echo($login->getLoginName());
$encoder = $factory->getEncoder($login);
$login->setPassword($encoder->encodePassword($login->getPassword(), $login->getSalt()));
$em = $this->getDoctrine()->getManager();
$em->persist($login);
$em->flush();
$this->get('session')->setFlash(
'success',
'Account Successfully Created'
);
However, when I call persist and flush on my entity, the login_name field is getting '' put into it (empty space). I can't understand why the value is getting nulled out (I changed a DB setting to error when it comes in as non-unique).
There are associations against this class, but this is the primary so I am creating it first.
Any thoughtS?
I don't get what you're doing here. You want table.id to be an auto-generated ID but you want table.login_name to be the primary key? Because that's how you have it setup
#Id is for primary keys
#GeneratedValue defines how priamry keys are created
What I personally think you should want is for table.id to be the primary key, and for table.login_name to be unique
/**
* #ORM\Column(type="integer", name="id")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $userId;
/**
* #ORM\Column(type="string", name="login_name", length=255, unique=true)
*/
private $loginName;
So in testing I identified that you can't apply a generatedValue attribute to an Non-ID field. Once I removed that from the userID field (and allowed Mysql to handle that on it's own) things started to work again.
I am creating small application with just two entities, Order and Shipment.
The Shipment entity is as follows: (methods removed to keep it short)
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $username
*
* #ORM\Column(name="username", type="string", length=255)
*/
private $username;
/**
* #var string $password
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #var integer $order_id
*
* #ORM\Column(name="order_id", type="integer")
*/
private $order_id;
/**
* #var smallint $payment_type
*
* #ORM\Column(name="payment_type", type="smallint")
*/
private $payment_type;
In my controller I am trying to query using the order_id but my findOneByOrderId method is not working.
$orderExists = $this->getDoctrine()
->getRepository('ShipBundle:Shipment')
->findOneByOrderId($orderId);
var_dump($orderExists); die();
The error I get is:
Entity 'ShipBundle\Entity\Shipment' has no field 'orderId'. You can therefore not call 'findOneByOrderId' on the entities' repository.
If I am not wrong, Doctrine find methods join the variables at underscores and capitalize them. What am I doing wrong?
I managed to solve the problem with the hint from pomaxa and Doctrine2 documentation.
The correct code would be:
$orderExists = $this->getDoctrine()
->getRepository('ShipBundle:Shipment')
->findOneBy(array('order_id' => $orderId));
explained at: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#by-simple-conditions
Thanks everyone for the help. I appreciate it.
You could use the inbuilt relationship capabilities of Doctrine2 instead of using an id of order in your entity Shipment manually
That way you would have a relationship Doctrine is aware of.
$orders = $shipment->getOrders();
Look here: http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html
Problem in this line
private $order_id;
Use it
private $orderId;
It is ok. For db you will have order_id.
Just to clarify, the reason for the error was that you needed to pass an Array into the findOneBy();
This is wrong: , ->findOneByOrderId($orderId); in
$orderExists = $this->getDoctrine()
->getRepository('ShipBundle:Shipment')
->findOneByOrderId($orderId);
An array must be passed. array('order_id' => $orderId)
$orderExists = $this->getDoctrine()
->getRepository('ShipBundle:Shipment')
->findOneBy(array('order_id' => $orderId));
OR SHORTHAND ['order_id'=> $orderId] as long as you are in PHP >= 5.4
$orderExists = $this->getDoctrine()
->getRepository('ShipBundle:Shipment')
->findOneBy(['order_id'=> $orderId]);