Doctrine2 entity , tell not update certain columns - php

I don't want to update certain columns for the table.
In the Questions table, I just want to update the question column:
question:
id
question
created_by
created_at
modified_by
modified_at
is_Active
In the above table column, I don't need to update the create_at, created_by, modified_by, modified_at, is_active columns. This is the entity I am using.
Entity:
<?php
namespace Library\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Base class for all the Entities
* This class maps id, active, created and modified columns
*
* #author
*/
/**
* #ORM\MappedSuperclass
*/
class BaseEntity {
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(name="id", type="integer")
* #var integer
*/
protected $id;
/**
* #ORM\Column(name="is_active", type="boolean")
* #var boolean
*/
protected $active;
/**
* #ORM\Column(name="created_at", type="datetime")
* #var datetime
*/
protected $createdAt;
/**
* #ORM\Column(name="created_by", type="integer", nullable=true)
* #var integer
*/
protected $createdBy;
/**
* #ORM\Column(name="modified_at", type="datetime")
* #var datetime
*/
protected $modifiedAt;
/**
* #ORM\Column(name="modified_by", type="integer")
* #var integer
*/
protected $modifiedBy;
public function getId() {
return $this->id;
}
public function getActive() {
return $this->active;
}
public function getCreatedAt() {
return $this->createdAt;
}
public function getCreatedBy() {
return $this->createdBy;
}
public function getModifiedAt() {
return $this->modifiedAt;
}
public function getModifiedBy() {
return $this->modifiedBy;
}
public function setId($id) {
$this->id = $id;
}
public function setActive($active) {
$this->active = $active;
}
public function setCreatedAt($createdAt) {
$this->createdAt = $createdAt;
}
public function setCreatedBy($createdBy) {
$this->createdBy = $createdBy;
}
public function setModifiedAt($modifiedAt) {
$this->modifiedAt = $modifiedAt;
}
public function setModifiedBy($modifiedBy) {
$this->modifiedBy = $modifiedBy;
}
}
This is my Question Entity:
<?php
namespace Survey\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Library\Entity\BaseEntity;
use Survey\Entity\Survey;
/**
* Description of Survey Questions
*
* #author Mubarak
*/
/**
* #ORM\Entity
* #ORM\Table(name="survey_questions")
*/
class Question extends BaseEntity{
/**
* #ORM\Column(name="question", type="string")
* #var string
*/
protected $question;
/**
* #ORM\ManyToOne(targetEntity="Survey\Entity\Survey", inversedBy="questions")
* #ORM\JoinColumn(name="survey_id", referencedColumnName="id")
*/
private $surveys;
public function getQuestion() {
return $this->question;
}
public function setQuestion($question) {
$this->question = $question;
}
public function getSurveys() {
return $this->surveys;
}
// public function setSurveys(ArrayCollection $survey) {
public function setSurveys(Survey $surveys = null) {
$this->surveys = $surveys;
}
// public function __toString() {
// return __CLASS__ . ": [id: {$this->id}, name: {$this->name}]";
// }
}
Here is my update function:
public function updateQuestion($userId, $data ) {
try{
$surveyId = 1;
$survey = $this->entityManager->getRepository('Survey\Entity\Survey')->find($surveyId);
$question = new Question();
$question->setQuestion($data['question']);
$question->setSurveys($survey);
$question->setId(1);
$this->entityManager->merge($question);
$this->entityManager->flush();
} catch (Exception $ex) {
throw new Exception("Couldnt update the Question");
}
Below is my error message i am getting:
An exception occurred while executing 'UPDATE survey_questions SET is_active = ?, created_at = ?, created_by = ?, modified_at = ?, modified_by = ? WHERE id = ?' with params [null, null, null, null, null, 1]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1048 Column 'created_at' cannot be null
Here is my insert Operation:
public function insertQuestion($userId, $survey, $questionArr) {
try{
$question = new Question();
$question->setQuestion($questionArr['question']);
$question->setSurveys($survey);
$question->setActive(1);
$question->setCreatedBy($userId);
$question->setCreatedAt($this->createdAt);
$question->setModifiedBy($userId);
$question->setModifiedAt($this->modifiedAt);
$this->entityManager->persist($question);
$this->entityManager->flush();
return $question;
}catch(Exception $ex){
throw new Exception("Couldnt insert the question");
}
}

The problem is that you are creating a new entity, Question.
When calling EntityManager::flush() Doctrine computes the changesets of all the currently managed entities and saves the differences to the database. In case of object properties (#Column(type=”datetime”) or #Column(type=”object”)) these comparisons are always made BY REFERENCE.
"By reference" is important because your new entity has null values for all date time fields (rather than the previously set \DateTime instances). When flush() is called Doctrine correctly detects that these fields are changed and performs the query which fails at the database level.
The merge() operation isn't required in Doctrine when 'editing' entities, these are used for detached instances that need to be managed again.
To solve this you should load the managed instance of the entity first; then modify the fields and flush.
$question = $entityManager->find(1);
$question->setQuestion($data['question']);
$entityManager->flush();

Related

Symfony Doctrine Insert: cannot insert into column "id"

I'm modeling a vending machine where I got 3 Entities (Milk, Sugar, Coffee) and one table that lists all my coffee machines.
Now I want to insert a new value for the amount of milk left. The coffee machines are foreign keys in the resources tables.
However, I get this error, which does not seem to make sense, as I am just setting a foreign key field:
An exception occurred while executing a query: SQLSTATE[428C9]: <<Unknown error>>: 7 ERROR: cannot insert into column "id"
DETAIL: Column "id" is an identity column defined as GENERATED ALWAYS.
HINT: Use OVERRIDING SYSTEM VALUE to override.
Here are the tables (Postgres) (only coffee listed - milk and sugar have the same architecture):
create table coffee (
id integer not null generated always as identity primary key,
request_id bigint,
logdate timestamp(0) without time zone not null,
vmc_no integer,
amount integer not null,
constraint fk_request
foreign key(request_id)
references energyomat.request(id),
constraint fk_vmc_company
foreign key(vmc_no)
references energyomat.vmc_company(vmc_no)
);
create table vmc_company (
vmc_no integer not null unique primary key,
register_date timestamp(0) without time zone not null
);
I've set the primitive fields and got the Entity of VmcCompany and set it as the foreign value (setVmcNo).
public function updateResources($vmcNo, $milkAmount, $sugarAmount, $coffeeAmount)
{
$milk = new Milk();
$sugar = new Sugar();
$coffee = new Coffee();
if($milkAmount != null) {
$milk->setAmount($milkAmount);
$milk->setLogdate(new \DateTime());
$vmc = $this->doctrine->getRepository(VmcCompany::class)->find($vmcNo);
$milk->setVmcNo($vmc);
$manager = $this->doctrine->getManager();
$manager->persist($milk);
}
if($sugarAmount != null) {
$sugar->setAmount($sugarAmount);
$sugar->setLogdate(new \DateTime());
$vmc = $this->doctrine->getRepository(VmcCompany::class)->find($vmcNo);
$sugar->setVmcNo($vmc);
$manager = $this->doctrine->getManager();
$manager->persist($sugar);
}
if($coffeeAmount != null) {
$coffee->setAmount($coffeeAmount);
$coffee->setLogdate(new \DateTime());
$vmc = $this->doctrine->getRepository(VmcCompany::class)->find($vmcNo);
$coffee->setVmcNo($vmc);
$manager = $this->doctrine->getManager();
$manager->persist($coffee);
}
$manager->flush();
}
Here are the Entity classes:
Coffee:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Coffee
*
* #ORM\Table(name="coffee", indexes={#ORM\Index(name="IDX_538529B3427EB8A5", columns={"request_id"}), #ORM\Index(name="IDX_538529B3651BF703", columns={"vmc_no"})})
* #ORM\Entity
*/
class Coffee
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="coffee_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var \DateTime
*
* #ORM\Column(name="logdate", type="datetime", nullable=false)
*/
private $logdate;
/**
* #var int
*
* #ORM\Column(name="amount", type="integer", nullable=false)
*/
private $amount;
/**
* #var \Request
*
* #ORM\ManyToOne(targetEntity="Request")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="request_id", referencedColumnName="id")
* })
*/
private $request;
/**
* #var \VmcCompany
*
* #ORM\ManyToOne(targetEntity="VmcCompany")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="vmc_no", referencedColumnName="vmc_no")
* })
*/
private $vmcNo;
public function getId(): ?int
{
return $this->id;
}
public function getLogdate(): ?\DateTimeInterface
{
return $this->logdate;
}
public function setLogdate(\DateTimeInterface $logdate): self
{
$this->logdate = $logdate;
return $this;
}
public function getAmount(): ?int
{
return $this->amount;
}
public function setAmount(int $amount): self
{
$this->amount = $amount;
return $this;
}
public function getRequest(): ?Request
{
return $this->request;
}
public function setRequest(?Request $request): self
{
$this->request = $request;
return $this;
}
public function getVmcNo(): ?VmcCompany
{
return $this->vmcNo;
}
public function setVmcNo(?VmcCompany $vmcNo): self
{
$this->vmcNo = $vmcNo;
return $this;
}
}
VmcCompany:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* VmcCompany
*
* #ORM\Table(name="vmc_company")
* #ORM\Entity
*/
class VmcCompany
{
/**
* #var int
*
* #ORM\Column(name="vmc_no", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="vmc_company_vmc_no_seq", allocationSize=1, initialValue=1)
*/
private $vmcNo;
/**
* #var \DateTime
*
* #ORM\Column(name="register_date", type="datetime", nullable=false)
*/
private $registerDate;
public function getVmcNo(): ?int
{
return $this->vmcNo;
}
public function getRegisterDate(): ?\DateTimeInterface
{
return $this->registerDate;
}
public function setRegisterDate(\DateTimeInterface $registerDate): self
{
$this->registerDate = $registerDate;
return $this;
}
}
I'm new to Symfony / Doctrine and so I guess I'm overseeing something, but just cannot find out what it is. Thanks for your help in advance.
If someone else runs into this problem:
You need to declare the id field in the database table as follows:
id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
The emphasis lies on BY DEFAULT instead of ALWAYS.
Otherwise Symfony runs into a conflict with Postgres while auto-incrementing.

Doctrine insert into Oracle 12c DB table with auto generated id

Im trying to insert into my database (Oracle 12c) table a new entry but im failing to do that
The following is my entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Divisions
*
* #ORM\Table(name="DIVISIONS")
* #ORM\Entity
*/
class Divisions
{
/**
* #var int
*
* #ORM\Column(name="DIVISIONID", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="DIVISIONS_DIVISIONID_seq", allocationSize=1, initialValue=1)
*/
public $divisionid = '"SPECIFICATIONS"."ISEQ$$_79111".nextval';
/**
* #var string|null
*
* #ORM\Column(name="DIVISIONNAME", type="string", length=500, nullable=true)
*/
public $divisionname;
/**
* #var int|null
*
* #ORM\Column(name="SORTORDER", type="integer", nullable=true, options={"default"="1"})
*/
public $sortorder = '1';
/**
* #var int|null
*
* #ORM\Column(name="ISDELETED", type="integer", nullable=true)
*/
public $isdeleted = '0';
public function getDivisionid(): ?int
{
return $this->divisionid;
}
public function getDivisionname(): ?string
{
return $this->divisionname;
}
public function setDivisionname(?string $divisionname): self
{
$this->divisionname = $divisionname;
return $this;
}
public function getSortorder(): ?int
{
return $this->sortorder;
}
public function setSortorder(?int $sortorder): self
{
$this->sortorder = $sortorder;
return $this;
}
public function getIsdeleted(): ?int
{
return $this->isdeleted;
}
public function setIsdeleted(?int $isdeleted): self
{
$this->isdeleted = $isdeleted;
return $this;
}
}
And here is my controller that is trying to "POST" and add a new Division
<?php
namespace App\Controller;
use App\Entity\Divisions;
use App\Form\DivisionsType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
/**
* #Route("api/divisions")
*/
class DivisionsController extends AbstractController
{
/**
* #Route("", name="divisions_add", methods={"POST"})
*/
public function addDivisions(Request $request)
{
$em = $this->getDoctrine()->getManager();
$division = new Divisions();
$division->setDivisionname('TestDiv');
$em->persist($division);
$em->flush();
return new Response(
Response::HTTP_OK
);
}
}
when i try to call this the following Error message will appear:
An exception occurred while executing 'INSERT INTO DIVISIONS (DIVISIONID, DIVISIONNAME, SORTORDER, ISDELETED) VALUES (?, ?, ?, ?)' with params [16, "TestDiv", "1", "0"]:
ORA-32795: cannot insert into a generated always identity column
For some reason no matter what i try the DivisionID column will be called.. is there a way to insert without calling some certain columns?
Or is there a way to send it as 'INSERT INTO DIVISIONS (DIVISIONNAME, SORTORDER, ISDELETED) VALUES (?, ?, ?)' with params ["TestDiv", "1", "0"]'
PS: Entity is auto generated from database
If anybody wants more info ill happily provide
Ok so if anybody reaches this point and is still stuck i find kind of a work around:
I changed my Entity to look like that:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Divisions
*
* #ORM\Table(name="DIVISIONS")
* #ORM\Entity
*/
class Divisions
{
/**
* #var int
*
* #ORM\Column(name="DIVISIONID", type="integer", nullable=false)
* #ORM\Id
*/
public $divisionid;
/**
* #var string|null
*
* #ORM\Column(name="DIVISIONNAME", type="string", length=500, nullable=true)
*/
public $divisionname;
/**
* #var int|null
*
* #ORM\Column(name="SORTORDER", type="integer", nullable=true, options={"default"="1"})
*/
public $sortorder = '1';
/**
* #var int|null
*
* #ORM\Column(name="ISDELETED", type="integer", nullable=true)
*/
public $isdeleted = '0';
public function getDivisionid(): ?int
{
return $this->divisionid;
}
public function getDivisionname(): ?string
{
return $this->divisionname;
}
public function setDivisionname(?string $divisionname): self
{
$this->divisionname = $divisionname;
return $this;
}
public function getSortorder(): ?int
{
return $this->sortorder;
}
public function setSortorder(?int $sortorder): self
{
$this->sortorder = $sortorder;
return $this;
}
public function getIsdeleted(): ?int
{
return $this->isdeleted;
}
public function setIsdeleted(?int $isdeleted): self
{
$this->isdeleted = $isdeleted;
return $this;
}
}
Then in the Controller i added the following function:
private function getMaxDivisionIdNumber() {
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery('SELECT MAX(u.divisionid) FROM App\Entity\Divisions u');
$res = $query->getResult();
return $res[0][1];
}
Now this function is used to get the Max id number.. so my controller would look something like that:
<?php
namespace App\Controller;
use App\Entity\Divisions;
use App\Form\DivisionsType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
/**
* #Route("api/divisions")
*/
class DivisionsController extends AbstractController
{
/**
* #Route("", name="divisions_add", methods={"POST"})
*/
public function addDivisions(Request $request)
{
$em = $this->getDoctrine()->getManager();
$content = $request->getContent();
$content = json_decode($content);
$division = new Divisions();
foreach ($content as $key => $value) {
$division->$key = $value;
}
$maxId = (int) $this->getMaxDivisionIdNumber();
$division->divisionid = $maxId + 1;
$em->persist($division);
$em->flush();
return new Response(
Response::HTTP_OK
);
}
private function getMaxDivisionIdNumber() {
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery('SELECT MAX(u.divisionid) FROM App\Entity\Divisions u');
$res = $query->getResult();
return $res[0][1];
}
}

Symfony3 Doctrine Single Table Inhertiance SQLSTATE[23000]: Integrity constraint violation

I am new to Symfony and I am trying to do a simple Blog. I have users in my database as authors of Comments and 2 types of comments - PostComment and ReplyComment which both extend abstract class Comments. I am trying to save comment to the DB, but I am stuck with this error :
An exception occurred while executing 'INSERT INTO comment (text,
author_id, post_id, comment_type) VALUES (?, ?, ?, ?)' with params
["Lorem ipsum", 1, 1, "post_comment"]:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails
(blog_symfony.comment, CONSTRAINT FK_9474526CDB1174D2 FOREIGN
KEY (post_comment_id) REFERENCES comment (id))
This is abstract Comment Class :
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity()
* #ORM\Table(name="comment")
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="comment_type", type="string")
* #ORM\DiscriminatorMap({"post_comment" = "PostComment", "reply_comment" = "ReplyComment"})
*/
abstract class Comment
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="userComments")
*/
protected $author;
/**
* #ORM\Column(type="string")
*/
protected $text;
/**
* #return integer $id
*/
public function getId()
{
return $this->id;
}
/**
* #return string $author
*/
public function getAuthor()
{
return $this->author;
}
/**
* #param string $author
*/
public function setAuthor($author)
{
$this->author = $author;
}
/**
* #return string $text
*/
public function getText()
{
return $this->text;
}
/**
* #param string $text
*/
public function setText($text)
{
$this->text = $text;
}
}
This is a post comment class
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\PostCommentRepository")
*/
class PostComment extends Comment
{
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Post", inversedBy="comments")
* #ORM\JoinColumn(nullable=true, onDelete="SET NULL")
*/
private $post;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\ReplyComment", mappedBy="postComment", cascade={"remove"}, orphanRemoval=true)
* #ORM\OrderBy({"id"="DESC"})
*/
private $replyComments;
/**
* #return replyComment[] reply comments
*/
public function getReplyComments()
{
return $this->replyComments;
}
/**
* #param replyComment[] reply comments
*/
public function setReplyComments($replyComments)
{
$this->replyComments = $replyComments;
}
/**
* #return Post post
*/
public function getPost()
{
return $this->post;
}
/**
* #param Post post
*/
public function setPost($post)
{
$this->post = $post;
}
}
And finally this is the code in controller runnig logic
if ($postCommentForm->isSubmitted() && $postCommentForm->isValid())
{
/** #var PostComment $comment */
$comment = $postCommentForm->getData();
$comment->setPost($post);
$author = $this->getDoctrine()->getRepository('AppBundle:User')->findOneBy([
'email' => $comment->getAuthor()
]);
$comment->setAuthor($author);
$em = $this->getDoctrine()->getManager();
$em->persist($comment);
$em->flush();
return $this->redirectToRoute("single_post", [
'id' => $post->getId()
]);
}
At first your base class don't need to be abstract. Instead you have to insert this annotation above the class, so doctrine will get it:
#MappedSuperclass()
remove all other doctrine annotations from base entity, all of them belongs to the entity class.
use Doctrine\ORM\Mapping as ORM;
/**
*#MappedSuperclass()
*/
class Comment
{
and entity have all other annotations:
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\PostCommentRepository")
* #ORM\Table(name="comment")
*/
class PostComment extends Comment
{
this should help

Doctrine2 dont want to insert the columns in the table

Here is my Insert Query, how can I tell that, created_at(current time-stamp), is_active(default 1) set in the mysql db structure needs to be taken.
When I omit the $question->setCreatedAt($this->createdAt); in the insert operation it shows me an Integrity constraint violation, do you know what is the issue?
In the Questions table:
question:
id
question
created_by
created_at
modified_by
modified_at
is_Active
Entity:
<?php
namespace Library\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Base class for all the Entities
* This class maps id, active, created and modified columns
*
* #author
*/
/**
* #ORM\MappedSuperclass
*/
class BaseEntity {
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(name="id", type="integer")
* #var integer
*/
protected $id;
/**
* #ORM\Column(name="is_active", type="boolean")
* #var boolean
*/
protected $active;
/**
* #ORM\Column(name="created_at", type="datetime")
* #var datetime
*/
protected $createdAt;
/**
* #ORM\Column(name="created_by", type="integer", nullable=true)
* #var integer
*/
protected $createdBy;
/**
* #ORM\Column(name="modified_at", type="datetime")
* #var datetime
*/
protected $modifiedAt;
/**
* #ORM\Column(name="modified_by", type="integer")
* #var integer
*/
protected $modifiedBy;
public function getId() {
return $this->id;
}
public function getActive() {
return $this->active;
}
public function getCreatedAt() {
return $this->createdAt;
}
public function getCreatedBy() {
return $this->createdBy;
}
public function getModifiedAt() {
return $this->modifiedAt;
}
public function getModifiedBy() {
return $this->modifiedBy;
}
public function setId($id) {
$this->id = $id;
}
public function setActive($active) {
$this->active = $active;
}
public function setCreatedAt($createdAt) {
$this->createdAt = $createdAt;
}
public function setCreatedBy($createdBy) {
$this->createdBy = $createdBy;
}
public function setModifiedAt($modifiedAt) {
$this->modifiedAt = $modifiedAt;
}
public function setModifiedBy($modifiedBy) {
$this->modifiedBy = $modifiedBy;
}
}
This is my Question Entity:
<?php
namespace Survey\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Library\Entity\BaseEntity;
use Survey\Entity\Survey;
/**
* Description of Survey Questions
*
* #author Mubarak
*/
/**
* #ORM\Entity
* #ORM\Table(name="survey_questions")
*/
class Question extends BaseEntity{
/**
* #ORM\Column(name="question", type="string")
* #var string
*/
protected $question;
/**
* #ORM\ManyToOne(targetEntity="Survey\Entity\Survey", inversedBy="questions")
* #ORM\JoinColumn(name="survey_id", referencedColumnName="id")
*/
private $surveys;
public function getQuestion() {
return $this->question;
}
public function setQuestion($question) {
$this->question = $question;
}
public function getSurveys() {
return $this->surveys;
}
// public function setSurveys(ArrayCollection $survey) {
public function setSurveys(Survey $surveys = null) {
$this->surveys = $surveys;
}
// public function __toString() {
// return __CLASS__ . ": [id: {$this->id}, name: {$this->name}]";
// }
}
Here is my insert Operation:
public function insertQuestion($userId, $survey, $questionArr) {
try{
$question = new Question();
$question->setQuestion($questionArr['question']);
$question->setSurveys($survey);
$question->setActive(1);
$question->setCreatedBy($userId);
$question->setCreatedAt($this->createdAt);
$question->setModifiedBy($userId);
$question->setModifiedAt($this->modifiedAt);
$this->entityManager->persist($question);
$this->entityManager->flush();
return $question;
}catch(Exception $ex){
throw new Exception("Couldnt insert the question");
}
}
This is Ok, its working properly, but i dont want to insert the Created_at, modified_at
public function insertQuestion($userId, $survey, $questionArr) {
try{
$question = new Question();
$question->setQuestion($questionArr['question']);
$question->setSurveys($survey);
$question->setActive(1);
$question->setCreatedBy($userId);
$question->setModifiedBy($userId);
$this->entityManager->persist($question);
$this->entityManager->flush();
return $question;
}catch(Exception $ex){
throw new Exception("Couldnt insert the question");
}
}
If you want to set default values it is best to set them in your object model where possible.
/**
* #ORM\Column(name="is_active", type="boolean")
* #var boolean
*/
protected $active = true;
For time-stamps though it is a bit of a different story...
I would suggest to take a look at the Gedmo doctrine extensions library which includes solutions for createdAt and other common columns for your model. No need to reinvent the wheel... .

symfony2 : user password set to empty after running this method

this methodi use it to add a new job but when i add a job the password of the that current user get its password set to empty cus the user object that i retrieve has no password and
symfony behaves like so for to secure the password any help would be much appreciated
` public function addJobAction(){
if(false === $this->get('security.context')
->isGranted('ROLE_ANNOUNCER')
)
{
throw new AccessDeniedException();
}
$job = new Job() ;
$jobForm = $this->createForm( new JobType() ,$job) ;
$request = $this->getRequest();
if( $request->getMethod() == 'GET'){
return
$this->render('MyJobBundle:Job:addJob.html.twig' ,
array('form'=> $jobForm->createView() )
) ;
}
if( $request->getMethod() == 'POST'){
$jobForm->bindRequest($request);
if( $jobForm->isValid() ){
$user = $this->get('security.context')->getToken()
->getUser();
$job->setAnnouncer($user);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($job) ;
$em->flush() ;
return
$this->redirect($this->generateUrl('show_job' ,
array('id'=> $job->getId() ) )
);
}else{
return
new Response('no');
}
}
}
heres my job entity
namespace My\JobBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use My\UserBundle\Entity\User ;
use Symfony\Component\Validator\Constraints as Assert;
/**
* My\JobBundle\Entity\Job
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="My\JobBundle\Entity\JobRepository")
*/
class Job
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $title
*
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string $content
*
*
* #ORM\Column(name="content", type="text")
*/
private $content;
/**
* #var string $city
*
* #ORM\Column(name="city", type="string", length=255)
*
*/
private $city;
/**
* #var datetime $created_at
*
* #ORM\Column(name="created_at", type="datetime")
*/
private $created_at;
/**
* #var string $salary
*
* #ORM\Column(name="salary", type="string", length=255)
*
*
*/
private $salary;
/**
* #ORM\ManyToOne(targetEntity="My\UserBundle\Entity\User")
*/
private $announcer ;
/**
* link a job to a user
*/
public function setAnnouncer(User $a)
{
$this->announcer = $a;
}
/**
* return a user from a job object
*/
public function getAnnouncer()
{
return $this->announcer;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set content
*
* #param string $content
*/
public function setContent($content)
{
$this->content = $content;
}
/**
* Get content
*
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set created_at
*
* #param datetime $createdAt
*/
public function setCreatedAt($createdAt)
{
$this->created_at = $createdAt;
}
/**
* Get created_at
*
* #return datetime
*/
public function getCreatedAt()
{
return $this->created_at;
}
/**
* Set salary
*
* #param string $salary
*/
public function setSalary($salary)
{
$this->salary = $salary;
}
/**
* Get salary
*
* #return string
*/
public function getSalary()
{
return $this->salary;
}
public function setCity($c)
{
$this->city = $c;
}
public function getCity()
{
return $this->city ;
}
public function __construct(){
$this->created_at = new \DateTime() ;
}
}
heres my jobType
namespace My\JobBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class JobType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('title')
->add('content','textarea' )
//->add('created_at')
->add('salary')
->add('city')
//->add('announcer')
;
}
public function getName()
{
return 'my_jobbundle_jobtype';
}
}
and heres my log where i see the password updated
INSERT INTO Job (title, content, city, created_at, salary, announcer_id) VALUES (?, ?, ?, ?, ?, ?) ({"1":"lfdgdfl;","2":";lkl;fdlgkdfl;","3":"lklkl;;l","4":{"date":"2012-02-05 23:39:16","timezone_type":3,"timezone":"Europe\/Paris"},"5":"333","6":1})
UPDATE User SET password = ? WHERE id = ? ([null,1])
well i found the issue it was caused by that eraseCredential method of the UserInterface in my User entity
<?php
public function eraseCredential(){
$this->password = null ;
}
i just had to empty it as it was doin to my password by commenting that line ; ]
2 kosaidpo
Your solution works because eraseCredentials() method is used to clear user sensitive data (means NOT secret, but the one that can be restored, the sense is like __sleep()) when serializing user object or saving it to database (that is what manual says). So when you attach user to job object and call #flush(), doctrine will check for changes in all objects connected with job and find that user object has changed because eraseCredentials() has erased password. That is why your user gets updated.
There is one more solution which could help you:
The Solution:
Change Tracking Policies from Doctrine documentation.
In short, you can add #ChangeTrackingPolicy("DEFERRED_EXPLICIT") annotation (as I did, because I'm using annotations. Captain Obvious =) ) to UserInterface implementation (in my case I'm using User class) and this will tell Doctrine not to check all 'connected' to job objects.
In this case doctrine will not check user object and save it with erased password, unless you will force it to do it with calling #persist(User object) manually.
But anyway, you should not do $this->password = null in your eraseCredentials() method.
It does seem strange, but you could always retrieve User object prior to binding it to a newly created job:
$token = $this->get('security.context')->getToken();
$user_repo = $this->getDoctrine()->getRepository('**NAMESPACE**:User');
$user = $user_repo->find($token->getUser()->getId());
$job->setAnnouncer($user);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($job) ;
$em->flush();
Also, I'm not really sure but I read somewhere that token isn't supposed to carry password due to it's security nature.... maybe that is your problem...

Categories