Persist entity : cannot be null - doctrine-orm

When I use this code, I have this error " Integrity constraint violation: 1048 Column 'ecriture_id' cannot be null " :
$produit = new Produit();
$ecriture = new Ecriture();
$produit->setEcriture($ecriture);
// $this->em->persist($ecriture);
$this->em->persist($produit);
If I uncommented " $this->em->persist($ecriture) " it's work true.
I don't understand because my "Produit" entity have a cascade persist :
Entity "Produit" :
class Produit
{
/**
* #ORM\OneToOne(targetEntity="LogicielBundle\Entity\Ecriture", inversedBy="gestionLocativeProduit", cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
*/
private $ecriture;
public function setEcriture(\LogicielBundle\Entity\Ecriture $ecriture)
{
$ecriture->setGestionLocativeProduit($this);
$this->ecriture = $ecriture;
// Similar problem if I add "$ecriture->setGestionLocativeProduit($this);" right here
return $this;
}
public function getEcriture()
{
return $this->ecriture;
}
Entity "Ecriture" :
class Ecriture
{
/**
* #ORM\OneToOne(targetEntity="LogicielBundle\Entity\GestionLocative\Produit", mappedBy="ecriture")
* #ORM\JoinColumn(nullable=true)
*/
private $gestionLocativeProduit;
public function setGestionLocativeProduit(\LogicielBundle\Entity\GestionLocative\Produit $gestionLocativeProduit)
{
$this->gestionLocativeProduit = $gestionLocativeProduit;
return $this;
}
public function getGestionLocativeProduit()
{
return $this->gestionLocativeProduit;
}

I have always had similair problems when I added new columns to my database, and got liek you the cannot be null error.
What mostly fixed it for me was adding nullable is true, then in twig, controller or form add the required = true attribute. Therefor it always had to be filled.

Related

How to solve the Integrity constraint violation in laravel-8 this occur when i am using form-data in postman only?

when i use raw option to post a data into the database at that time it will work ,it's not showing any error to me at that time when i tried to post a data like a form-data at that time i am getting Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'name' cannot be null error , How to solve this error [How i am passing headers]1 && [How i pass form-data]2
migration table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBooksTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->length(50)->unique();
$table->binary('image');
$table->integer('price')->unsigned();
$table->text('title');
$table->integer('quantity')->length(2)->unsigned();
$table->integer('ratings')->length(2)->unsigned();
$table->string('author');
$table->longText('description');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('books');
}
}
BooksController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Books;
use App\Models\User;
use App\Http\Requests;
use Symfony\Component\HttpFoundation\Response;
use App\Http\Resources\Books as BooksResource;
use App\Http\Middleware\Authenticate;
class BooksController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function DisplayBooks()
{
$books=Books::all();
return User::find($books->user_id=auth()->id())->books;
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function AddBooks(Request $request)
{
$book=new Books();
$book->name=$request->input('name');
$book->image=$request->input('image');
$book->price=$request->input('price');
$book->title=$request->input('title');
$book->quantity=$request->input('quantity');
$book->ratings=$request->input('ratings');
$book->author=$request->input('author');
$book->description=$request->input('description');
$book->user_id = auth()->id();
$book->save();
return new BooksResource($book);
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function ShowBook($id)
{
$book=Books::findOrFail($id);
if($book->user_id==auth()->id())
return new BooksResource($book);
else{
return response()->json([
'error' => 'UnAuthorized/invalid id'], 401);
}
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function UpdateBook(Request $request, $id)
{
$book=Books::findOrFail($id);
if($book->user_id==auth()->id()){
$book->name=$request->input('name');
$book->image=$request->input('image');
$book->price=$request->input('price');
$book->title=$request->input('title');
$book->quantity=$request->input('quantity');
$book->ratings=$request->input('ratings');
$book->author=$request->input('author');
$book->description=$request->input('description');
$book->save();
return new BooksResource($book);
}
else
{
return response()->json([
'error' => ' Book is not available ith id'], 404);
}
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function DeleteBook($id)
{
$book=Books::findOrFail($id);
if($book->user_id==auth()->id()){
if($book->delete()){
return response()->json(['message'=>'Deleted'],201);
}
}
else{
return response()->json([
'error' => ' Method Not Allowed/invalid Book id'], 405);
}
}
}

Add Method not working in a many to many relationship

I have this many to many relationship between bus and driver .
This is the bus entity :
/**
* #var ArrayCollection<Driver> The driver of this bus.
* #ORM\ManyToMany(targetEntity="Driver", inversedBy="bus" , cascade={"persist"})
* #ORM\JoinTable(name="bus_driver")
* #ORM\JoinColumn(name="driver_id", referencedColumnName="id")
* */
private $driver;
public function __construct() {
$this->driver = new \Doctrine\Common\Collections\ArrayCollection();
}
public function addDriver($driver) {
$this->driver[] = $driver;
return $this;
}
And this is the driver entity :
/**
* #var ArrayCollection<Bus> The buses of this driver
* #ORM\ManyToMany(targetEntity="Bus", mappedBy="driver")
* #ORM\JoinTable(name="bus_driver")
* #ORM\JoinColumn(name="bus_id", referencedColumnName="id")
*/
private $bus;
public function __construct() {
$this->bus = new \Doctrine\Common\Collections\ArrayCollection();
}
public function addBus($bus) {
$this->bus[] = $bus;
$bus->addDriver($this);
return $this;
}
My problem is that when I add a bus with a driver the relation is persisted but not when I add a driver whih a bus . It works only from the bus side.
please, consider renaming $driver into $drivers, as there is multiple drivers (same for bus -> buses)
and then you should try that:
#ORM\ManyToMany(targetEntity="xxx", cascade={"persist"})
more details: http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations
Change these (add the null and call it 'drivers'):
use Doctrine\Common\Collections\ArrayCollection;
...
private $drivers = null;
public function __construct() {
$this->drivers = new ArrayCollection();
}
public function addDriver($driver) {
$this->drivers[] = $driver;
return $this;
}
Also, to resolve the problem from the Bus Entity side, you might (but I'm not sure) need this change:
public function addDriver($driver) {
$driver->addBus($this);
$this->drivers[] = $driver;
return $this;
}
Try it, since I have a similar scenario in a ManyToOne relation, and I'm wondering if the above change might work.
The only working scenario was when I had :
A setter for the drivers collection .
An addDriver Method .
A removeDriver Method.
If I remove one of the pervious , addDriver won't even trigger at all .

Cannot save a Doctrine_Collection

I am using Docrine 1.2 with Zend Framework and trying to save a Doctrine Collection.
I am retrieving my collection from my table class with the following code.
public function getAll()
{
return $this->createQuery('e')
->orderBy('e.order ASC, e.eventType ASC')
->execute();
}
I also have the following class to reorder the above event records.
class Admin_Model_Event_Sort extends Model_Abstract
{
/**
* Events collection
* #var Doctrine_Collection
*/
protected $_collection = null;
public function __construct()
{
$this->_collection = Model_Doctrine_EventTypesTable::getInstance()->getAll();
}
public function save($eventIds)
{
if ($this->_collection instanceof Doctrine_Collection) {
foreach ($this->_collection as $record)
{
$key = array_search($record->eventTypeId, $eventIds);
if ($key !== false) {
$record->order = (string)$key;
}
}
return $this->_saveCollection($this->_collection);
} else {
return false;
}
}
}
The _saveCollection method above is as follows
/**
* Attempts to save a Doctrine Collection
* Sets the error message property on error
* #param Doctrine_Collection $collection
* #return boolean
*/
protected function _saveCollection(Doctrine_Collection $collection)
{
try {
$collection->save();
return true;
} catch (Exception $e) {
$this->_errorMessage = $e->getMessage();
OpenMeetings_Logger_ErrorLogger::write('Unable to save Doctrine Collection');
OpenMeetings_Logger_ErrorLogger::vardump($this->_errorMessage);
return false;
}
}
The event id's in the above save method is simply an enumerated array of event id's, I am using the keys of the array to set the sort order of the events using the order field. If I do a var_dump of the collection to an array ($this->_collection->toArray()) I get the correct data. However when I attempt to save the collection I get the following error.
"SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order = '0' WHERE eventtypeid = '3'' at line 1"
Is there anyway I can get Doctrine to expand on this error, the full SQL statement would be a start, also if anyone knows as to why this error is occuring then that would be very helpful.
Many thanks in advance
Garry
EDIT
I have modified my above code to try to work one record at a time but I still get the same problem.
public function save($eventIds)
{
foreach ($eventIds as $key => $eventId) {
$event = Model_Doctrine_EventTypesTable::getInstance()->getOne($eventId);
$event->order = (string)$key;
$event->save();
}
}
Ok I have found the problem. I was using the MYSQL reserved word order as a field name thus the error, changed it to sortOrder and the problem went away.
Hope this helps someone with a similar issue.
Garry

ErrorException: Catchable Fatal Error: Object of class could not be converted to string - Caused by dropdown menu but why?

I have the following code, which retrieves the page slugs from the database which are needed to then create a related sub page:
$builder->add('subtocontentoptions', 'entity', array(
'class' => 'ShoutAdminBundle:Content',
'property' => 'slug',
'query_builder' => function($repository) {
return $repository->createQueryBuilder('p')
->where('p.mainpage = :main')
->setParameter('main', '1')
->orderBy('p.created', 'ASC');
}
));
The code works, as it displays a drop down menu of all the parent pages I have. However, when I go to save the data to the database, I am given the following error:
ErrorException: Catchable Fatal Error: Object of class
Shout\AdminBundle\Entity\Content could not be converted to string in
C:\wamp\www\vendor\doctrine-dbal\lib\Doctrine\DBAL\Statement.php line
131
I have checked the contents of the Content entity file, and here is the variable being declared:
/**
* #var integer $subtocontentoptions
*
* #ORM\Column(name="SubToContentOptions", type="integer", nullable=false)
*/
private $subtocontentoptions;
And lower down the Content entity file:
/**
* Set subtocontentoptions
*
* #param integer $subtocontentoptions
*/
public function setSubtocontentoptions($subtocontentoptions)
{
$this->subtocontentoptions = $subtocontentoptions;
}
/**
* Get subtocontentoptions
*
* #return integer
*/
public function getSubtocontentoptions()
{
return $this->subtocontentoptions;
}
The rest of the code does work, once this drop down has been taken out. I'm not sure why the drop down is causing this error?
Thanks
Was having the same issue with a sf2/doctrine2 project, implementing the __toString method resolved this issue for me :
public function __toString()
{
return strval($this->id);
}

Join table is not updated in ManyToMany association in doctrine 2

I have tow entities Slaplans and Slaholidays and a join table slaplans_slaholidays.
After creating two Slaholidays objects, I persist them both, add them to the Slaplans and flush. The problem is that only the slaplans and slaholidays tables are updated, but the join table isn't.
Slaplans Entity :
<?php
namespace ZC\Entity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Slaplans
*
* #Table(name="slaplans")
* #Entity(repositoryClass="Repositories\Slaplans")
*/
class Slaplans
{
/*
* #ManyToMany(targetEntity="Slaholidays",inversedBy="plans", cascade={"ALL"})
* #JoinTable(name="slaplans_slaholidays",
* joinColumns={#JoinColumn(name="slaplanid" ,referencedColumnName="slaplanid")},
* inverseJoinColumns={#JoinColumn(name="slaholidayid" ,referencedColumnName="slaholidayid")})
* }
*/
private $holidays;
public function __construct()
{
$this->holidays = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getHolidays() {
return $this->holidays;
}
public function setHolidays($holidays)
{
$this->holidays=$holidays;
}
/*public function addHoliday($holiday) {
$this->holidays[]=$holiday;
}*/
}
Slaholidays Entity:
<?php
namespace ZC\Entity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Slaholidays
*
* #Table(name="slaholidays")
* #Entity(repositoryClass="Repositories\Slaholidays")
*/
class Slaholidays
{
/**
* #var integer $slaholidayid
*
* #Column(name="slaholidayid", type="integer", nullable=false)
* #Id
* #GeneratedValue(strategy="IDENTITY")
*/
private $slaholidayid;
/*
* #ManyToMany(targetEntity="Slaplans",mappedBy="holidays", cascade={"ALL"})
*/
private $plans;
/*public function getPlans(){
return $this->plans;
}*/
}
Code to persist the entities:
$allholidays=array();
$holiday=$this->_em->getRepository('ZC\Entity\Slaholidays')->find($value);
$holiday=new ZC\Entity\Slaholidays();
//..sets holiday fields here
$this->_em->persist($holiday);
$allholidays[]=$holiday;
$slaplan->setHolidays($allholidays);
foreach ($slaplan->getHolidays() as $value) {
$this->_em->persist($value);
}
$this->_em->persist($slaplan);
$this->_em->flush();
The are two issues in your code:
The first one: you are persisting each Slaholiday twice: first with
$this->_em->persist($holiday);
and second with
foreach ($slaplan->getHolidays() as $value) {
$this->_em->persist($value);
}
There is no problem actually, as they are not actually persisted in the db until flush are called, but anyway, you don't need that foreach.
The reason why your join table is not updated is in $slaplan->setHolidays method. You are initializing $slaplan->holidays with ArrayCollection (which is right) and in setHolidays you set it to the input parameter (which is $allholidays Array, and this is not right).
So, the correct way to do that is to use add method of the ArrayCollection
public function setHolidays($holidays)
{
//$this->holidays->clear(); //clears the collection, uncomment if you need it
foreach ($holidays as $holiday){
$this->holidays->add($holiday);
}
}
OR
public function addHolidays(ZC\Entity\Slaholiday $holiday)
{
$this->holidays->add($holiday);
}
public function clearHolidays(){
$this->holidays->clear();
}
//..and in the working script...//
//..the rest of the script
$this->_em->persist($holiday);
//$slaplan->clearHolidays(); //uncomment if you need your collection cleaned
$slaplan->addHOliday($holiday);
Although Doctrine checks the owning side of an association for things that need to be persisted, it's always important to keep both sides of the association in sync.
My advise is to have get, add and remove (no set) methods at both sides, that look like this:
class Slaplans
{
public function getHolidays()
{
return $this->holidays->toArray();
}
public function addHoliday(Slaholiday $holiday)
{
if (!$this->holidays->contains($holiday)) {
$this->holidays->add($holiday);
$holiday->addPlan($this);
}
return $this;
}
public function removeHoliday(Slaholiday $holiday)
{
if ($this->holidays->contains($holiday)) {
$this->holidays->removeElement($holiday);
$holiday->removePlan($this);
}
return $this;
}
}
Do the same in Slaplan.
Now when you add a Slaholiday to a Slaplan, that Slaplan will also be added to the Slaholiday automatically. The same goes for removing.
So now you can do something like this:
$plan = $em->find('Slaplan', 1);
$holiday = new Slaholiday();
// set data on $holiday
// no need to persist $holiday, because you have a cascade={"ALL"} all on the association
$plan->addHoliday($holiday);
// no need to persist $plan, because it's managed by the entitymanager (unless you don't use change tracking policy "DEFERRED_IMPLICIT" (which is used by default))
$em->flush();
PS: Don't use cascade on both sides of the association. This will make things slower than necessary, and in some cases can lead to errors. If you create a Slaplan first, then add Slaholidays to it, keep the cascade in Slaplan and remove it from Slaholiday.