I am working with my database already a month. Suddenly i started to get the error:
[Symfony\Component\Debug\Exception\ContextErrorException]
Notice: Array to string conversion
, when loading fixtures. Finally, i deleted all database, rerun migrations, left only 1 fixtures file (thus i commented our OrderedFIxturesInterface, and of course i cleared the cache, but the error remains).
C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj2_27\src\MeetingBundle\DataFixtures\ORM\LoadUsers01.php
<?php
namespace MeetingBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use MeetingBundle\Entity\User;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
class LoadUsers01 extends AbstractFixture
#implements OrderedFixtureInterface
{
public function load(ObjectManager $manager)
{
for ($i = 1; $i <= 10; $i++) {
$fuser = new User();
$fuser->setUsername('name'.$i);
$fuser->setEmail('g.statkute'.$i.'#gmail.com');
$fuser->setIsActive(True); // i also used 1
$fuser->setPassword('pswd'.$i);
$manager->persist($fuser);
# $this->addReference('fuser:name'.$i, $fuser);
}
$manager->flush();
}
public function getOrder()
{
return 1;
}
}
.
C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj2_27\src\MeetingBundle\Entity\User.php
..
/**
* User
*
* #ORM\Table(name="tuser")
* #ORM\Entity()
*/
class User implements AdvancedUserInterface, \Serializable
..
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=255, unique=true)
*/
private $username;
/**
* #ORM\Column(name="email", type="string", nullable=true, unique=true)
*
* #var string
*/
private $email;
/**
* #var bool
*
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255, unique=true)
*/
private $password;
..
/**
* Set username
*
* #param string $username
*
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* #param boolean $isActive
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
Table contains varchar fields except of tinyint for boolean IsActive. There is only one tabel with name users.
--
-- Table structure for table `tuser`
--
CREATE TABLE IF NOT EXISTS `tuser` (
`id` int(11) NOT NULL,
`username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`phone` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`roles` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`is_active` tinyint(1) NOT NULL,
`gravatar` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`webpages` longtext COLLATE utf8_unicode_ci NOT NULL COMMENT '(DC2Type:json_array)',
`createdAtInt` decimal(10,0) DEFAULT NULL,
`loggedInInt` decimal(10,0) DEFAULT NULL,
`loggedOutInt` decimal(10,0) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `tuser`
--
ALTER TABLE `tuser`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `UNIQ_66A7B847F85E0677` (`username`);
THE VERBOSE ERROR:
c:\Bitnami\wampstack-5.5.30-0\sym_prog\proj3_27>php app/console doctrine:fixture
s:load -vv
[2015-12-18 05:45:10] event.DEBUG: Notified event "console.command" to listener
"Symfony\Component\HttpKernel\EventListener\DebugHandlersListener::configure".
[2015-12-18 05:45:10] event.DEBUG: Notified event "console.command" to listener
"Symfony\Bridge\Monolog\Handler\ConsoleHandler::onCommand".
[2015-12-18 05:45:10] event.DEBUG: Notified event "console.command" to listener
"Symfony\Bridge\Monolog\Handler\ConsoleHandler::onCommand".
Careful, database will be purged. Do you want to continue y/N ?y
> purging database
> loading [1] MeetingBundle\DataFixtures\ORM\LoadUsers01
[Symfony\Component\Debug\Exception\ContextErrorException]
Notice: Array to string conversion
Exception trace:
() at C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj3_27\vendor\doctrine\dbal\lib\
Doctrine\DBAL\Driver\PDOStatement.php:67
Symfony\Component\Debug\ErrorHandler->handleError() at n/a:n/a
PDOStatement->bindValue() at C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj3_27\ve
ndor\doctrine\dbal\lib\Doctrine\DBAL\Driver\PDOStatement.php:67
Doctrine\DBAL\Driver\PDOStatement->bindValue() at C:\Bitnami\wampstack-5.5.30-0
\sym_prog\proj3_27\vendor\doctrine\dbal\lib\Doctrine\DBAL\Statement.php:120
Doctrine\DBAL\Statement->bindValue() at C:\Bitnami\wampstack-5.5.30-0\sym_prog\
proj3_27\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersi
ster.php:277
Doctrine\ORM\Persisters\Entity\BasicEntityPersister->executeInserts() at C:\Bit
nami\wampstack-5.5.30-0\sym_prog\proj3_27\vendor\doctrine\orm\lib\Doctrine\ORM\U
nitOfWork.php:1018
Doctrine\ORM\UnitOfWork->executeInserts() at C:\Bitnami\wampstack-5.5.30-0\sym_
prog\proj3_27\vendor\doctrine\orm\lib\Doctrine\ORM\UnitOfWork.php:378
Doctrine\ORM\UnitOfWork->commit() at C:\Bitnami\wampstack-5.5.30-0\sym_prog\pro
j3_27\vendor\doctrine\orm\lib\Doctrine\ORM\EntityManager.php:356
Doctrine\ORM\EntityManager->flush() at C:\Bitnami\wampstack-5.5.30-0\sym_prog\p
roj3_27\src\MeetingBundle\DataFixtures\ORM\LoadUsers01.php:32
MeetingBundle\DataFixtures\ORM\LoadUsers01->load() at C:\Bitnami\wampstack-5.5.
30-0\sym_prog\proj3_27\vendor\doctrine\data-fixtures\lib\Doctrine\Common\DataFix
tures\Executor\AbstractExecutor.php:121
Doctrine\Common\DataFixtures\Executor\AbstractExecutor->load() at C:\Bitnami\wa
mpstack-5.5.30-0\sym_prog\proj3_27\vendor\doctrine\data-fixtures\lib\Doctrine\Co
mmon\DataFixtures\Executor\ORMExecutor.php:83
Doctrine\Common\DataFixtures\Executor\ORMExecutor->Doctrine\Common\DataFixtures
\Executor\{closure}() at n/a:n/a
call_user_func() at C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj3_27\vendor\doct
rine\orm\lib\Doctrine\ORM\EntityManager.php:233
Doctrine\ORM\EntityManager->transactional() at C:\Bitnami\wampstack-5.5.30-0\sy
m_prog\proj3_27\vendor\doctrine\data-fixtures\lib\Doctrine\Common\DataFixtures\E
xecutor\ORMExecutor.php:85
Doctrine\Common\DataFixtures\Executor\ORMExecutor->execute() at C:\Bitnami\wamp
stack-5.5.30-0\sym_prog\proj3_27\vendor\doctrine\doctrine-fixtures-bundle\Comman
d\LoadDataFixturesDoctrineCommand.php:118
Doctrine\Bundle\FixturesBundle\Command\LoadDataFixturesDoctrineCommand->execute
() at C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj3_27\vendor\symfony\symfony\src
\Symfony\Component\Console\Command\Command.php:256
Symfony\Component\Console\Command\Command->run() at C:\Bitnami\wampstack-5.5.30
-0\sym_prog\proj3_27\vendor\symfony\symfony\src\Symfony\Component\Console\Applic
ation.php:846
Symfony\Component\Console\Application->doRunCommand() at C:\Bitnami\wampstack-5
.5.30-0\sym_prog\proj3_27\vendor\symfony\symfony\src\Symfony\Component\Console\A
pplication.php:189
Symfony\Component\Console\Application->doRun() at C:\Bitnami\wampstack-5.5.30-0
\sym_prog\proj3_27\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Con
sole\Application.php:96
Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at C:\Bitnami\wamps
tack-5.5.30-0\sym_prog\proj3_27\vendor\symfony\symfony\src\Symfony\Component\Con
sole\Application.php:120
Symfony\Component\Console\Application->run() at C:\Bitnami\wampstack-5.5.30-0\s
ym_prog\proj3_27\app\console:27
The problem was with roles field, which i changed yesterday evening to the string instead of array. But i forget to remove initialization $roles = array();
/**
* #var string
*
* #ORM\Column(name="roles", type="string", nullable=true)
*/
private $roles; // it was $roles= array();
Thus if you see this error, search for keyword "array" in related files and check if assign variable is supposed to be equal to array, etc..
This is the fourth time when i have redone all project because of simple error. The conclusion is that better it to keep thinking where can be a mistake. On the other hand, when doctrine was not generating crud, reinstalling the project with different Symfony version helped.
private $roles; // = array();
Related
CREATE TABLE `languages` (
`id` int(4) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`status` INT(1) NOT NULL DEFAULT '0',
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `languages_content` (
`language_id` int(4) UNSIGNED NOT NULL,
`language` int(4) UNSIGNED NOT NULL,
`label` varchar(50) NOT NULL,
PRIMARY KEY (`language_id`,`language`),
KEY `language` (`language`),
CONSTRAINT `languages_content_idfk_1` FOREIGN KEY (`language_id`) REFERENCES `languages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `languages_content_idfk_2` FOREIGN KEY (`language`) REFERENCES `languages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Is posible to do that? I already try many-to-many relationship, but this remove the 'label' field from the 'languages_content' table.
/**
* Languages
*
* #ORM\Table(name="languages")
* #ORM\Entity
*/
class Languages
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false, options={"unsigned"=true})
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=50, nullable=false)
*/
private $name;
/**
* #var int
*
* #ORM\Column(name="status", type="integer", nullable=false)
*/
private $status = '0';
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=false)
*/
private $createdAt;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Languages", inversedBy="language")
* #ORM\JoinTable(name="languages_content",
* joinColumns={
* #ORM\JoinColumn(name="language_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="language", referencedColumnName="id")
* }
* )
*/
private $language = array();
I also try with many-to-one relationship, but this option add an autoincremential field (id) that doesn't exist in languages_content table, as you can see the languages_content is used to relate the translations with the languages in the languages table.
#[ORM\Entity(repositoryClass: LanguagesRepository::class)]
class Languages
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 50, nullable: false)]
private ?string $name = null;
#[ORM\Column(nullable: true)]
private ?int $status = 0;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $createdAt = null;
#[ORM\OneToMany(mappedBy: 'languages', targetEntity: LanguagesContent::class)]
private Collection $language;
Thanks in advance for your help or sugestions.
Doctrine's ManyToMany does not support additional fields so you need to make the join table (i.e. languages_content) yourself
To get rid of the autoincremented ID simply remove the $id and its getter from the entity then add a #[ORM\Id] annotation to both ManyToOnes, if you make a migration this will create a composite primary key like in your SQL example.
Here is an example from the doctrine documentation https://www.doctrine-project.org/projects/doctrine-orm/en/2.13/tutorials/composite-primary-keys.html#use-case-3-join-table-with-metadata
I have register form.
When I save the user, i want to add row in other database table. The second table is for role and it has only 2 fields: user_id and role_id.
This is my structure of database:
CREATE TABLE `roles` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
PRIMARY KEY (`id`),
UNIQUE INDEX `UNIQ_B63E2EC75E237E06` (`name`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=3
;
CREATE TABLE `users` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`userName` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`password` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`fullName` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`email` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
PRIMARY KEY (`id`),
UNIQUE INDEX `UNIQ_1483A5E9586CA949` (`userName`),
UNIQUE INDEX `UNIQ_1483A5E9E7927C74` (`email`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=5
;
CREATE TABLE `user_roles` (
`user_id` INT(11) NOT NULL,
`role_id` INT(11) NOT NULL,
PRIMARY KEY (`user_id`, `role_id`),
INDEX `IDX_54FCD59FA76ED395` (`user_id`),
INDEX `IDX_54FCD59FD60322AC` (`role_id`),
CONSTRAINT `FK_54FCD59FA76ED395` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
CONSTRAINT `FK_54FCD59FD60322AC` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;
So, here is my UserController, where I am saving the user:
namespace AppBundle\Controller;
use AppBundle\Entity\User;
use AppBundle\Form\UserType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserController extends Controller
{
/**
* #Route("/register", name="user_register")
* #param Request $request
* #param UserPasswordEncoderInterface $passwordEncoder
* #return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function registerAction(Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
$password = $passwordEncoder->encodePassword($user,$user->getPlainPassword());
$user->setPassword($password);
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirectToRoute("cat_index");
}
return $this->render('users/register.html.twig',
array('form' => $form->createView()));
}
}
I want every user to have role with id=1. So every registered user will have ROLE_USER.
In my Entity User i have not a setter for role. i have only getter. How to add and setter which is checking for role with id 1 and set the role for the user?
Here is my User Entity:
<?php
namespace AppBundle\Entity;
use AppBundle\AppBundle;
use AppBundle\Controller\SecurityController;
use AppBundle\Repository\RoleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use AppBundle\Entity\Role;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use AppBundle\Repository;
/**
* User
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User implements UserInterface, \Serializable
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="userName", type="string", length=255, unique=true)
*/
private $userName;
/**
* #var string
*/
private $plainPassword;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #var string
*
* #ORM\Column(name="fullName", type="string", length=255)
*/
private $fullName;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, unique=true)
*/
private $email;
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Role")
* #ORM\JoinTable(name="user_roles",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="role_id", referencedColumnName="id")})
* #var Collection|Role[]
*/
private $roles;
/**
* User constructor.
*/
public function __construct()
{
$this->roles = new ArrayCollection();
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set userName
*
* #param string $userName
*
* #return User
*/
public function setUserName($userName)
{
$this->userName = $userName;
return $this;
}
/**
* Get userName
*
* #return string
*/
public function getUserName()
{
return $this->userName;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set fullName
*
* #param string $fullName
*
* #return User
*/
public function setFullName($fullName)
{
$this->fullName = $fullName;
return $this;
}
/**
* Get fullName
*
* #return string
*/
public function getFullName()
{
return $this->fullName;
}
/**
* Set email
*
* #param string $email
*
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* #return array
*/
public function getRoles()
{
$roles = [];
foreach ($this->roles as $role){
$roles[] = $role->getName();
}
if(empty($roles)){
$roles[] = 'ROLE_USER';
}
return $roles;
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* #return string|null The salt
*/
public function getSalt()
{
// TODO: Implement getSalt() method.
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
public function serialize()
{
return serialize([
$this->getId(),
$this->getUserName(),
$this->getPassword()
]);
}
public function unserialize($serialized)
{
list(
$this->id,
$this->userName,
$this->password
) = unserialize($serialized);
}
/**
* #return string
*/
public function getPlainPassword(): string
{
return $this->plainPassword.'';
}
/**
* #param string $plainPassword
*/
public function setPlainPassword(string $plainPassword)
{
$this->plainPassword = $plainPassword;
}
}
I am using symfony 3
How to do it? Thanks!
On your UserType you can set your roles field to use EntityType documentation. That will automatically save the roles entity on flush.
I execute migrations to create the database, after that, I want to fill database with some data. Why generate id strategy is not working?
bin/console doctrine:migrations:migrate
Migrations
WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)y
Migrating up to 20160510103145 from 0
++ migrating 20160510103145
-> CREATE TABLE navieras (id INTEGER NOT NULL, nombre VARCHAR(255) NOT NULL)
++ migrated (0.14s)
------------------------
++ finished in 0.14s
++ 1 migrations executed
++ 1 sql queries
bin/console doctrine:fixtures:load
Careful, database will be purged. Do you want to continue y/N ?y
> purging database
> loading AppBundle\DataFixtures\ORM\LoadNavieraData
[Doctrine\DBAL\Exception\NotNullConstraintViolationException]
An exception occurred while executing 'INSERT INTO navieras (nombre) VALUES (?)' with params ["Royal Caribbean"]:
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: navieras.id
[Doctrine\DBAL\Driver\PDOException]
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: navieras.id
[PDOException]
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: navieras.id
Fixture load function
public function load(ObjectManager $manager)
{
$naviera = new Naviera();
$naviera->setNombre('aaaaaaaaaaaaaaa');
$naviera2 = new Naviera();
$naviera2->setNombre('bbbbbbbbbbbbbb');
$manager->persist($naviera);
$manager->persist($naviera2);
$manager->flush();
}
Migration
public function up(Schema $schema)
{
$navieras = $schema->createTable('navieras');
$navieras->addColumn('id', "integer");
$navieras->addColumn('nombre', "string");
}
/**
* #param Schema $schema
*/
public function down(Schema $schema)
{
$schema->dropTable('navieras');
}
Naviera Entity
/**
* Modelo naviera
*
* #Entity
* #Table(name="navieras")
*/
class Naviera
{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue
*/
private $id;
/**
* #Column(type="string");
*/
private $nombre;
/**
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #param integer $id
*/
public function setId($id)
{
$this->$id = $id;
}
/**
* #return string
*/
public function getNombre()
{
return $this->nombre;
}
/**
* #param string $nombre
*/
public function setNombre($nombre)
{
$this->nombre = $nombre;
}
}
I'm using SQLite
Your migration up does not create an auto incrementing id column. Just an integer column. If you change your migration up function to the following it should fix your issue:
public function up(Schema $schema)
{
$navieras = $schema->createTable('navieras');
$navieras->addColumn('id', 'integer', ['Autoincrement' => true]);
$navieras->addColumn('nombre', 'string');
$navieras->setPrimaryKey('id', true);
}
I have a 1:m relationship between Subitem and SubitemColor. Now I would like to save some data inside an onFlush to modify some data for SubitemColor. The problem: I get the error message below when executing the controller you can see below too:
An exception occurred while executing 'INSERT INTO SubitemColor
(code, precio, pvp_recommended, file_name, activado, en_stock, area,
lets_fix_width_or_height_in_list, lets_fix_width_or_height_in_show,
position_level_0, position_level_1, position_brand, subitem_id,
color_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with
params [2]:
SQLSTATE[HY093]: Invalid parameter number: number of bound variables
does not match number of tokens
public function onFlush(Event \OnFlushEventArgs $eventArgs)
{
$em = $eventArgs->getEntityManager();
$uow = $em->getUnitOfWork();
$updates = $uow->getScheduledEntityUpdates();
$insertions = $uow->getScheduledEntityInsertions();
/////////// NEW SUBITEM_IMAGE OR SUBITEM_COLOR UPLOADED //////////
foreach ($insertions as $entity) {
if ($entity instanceof SubitemColor) {
//$entity->setLetsFixWidthOrHeightInList("jander");
//$entity->setLetsFixWidthOrHeightInList('width');
//$entity->setLetsFixWidthOrHeightInShow('width');
$entity->setEnStock(2);
$metaSubitemColor = $em->getClassMetadata(get_class($entity));
$uow->computeChangeSet($metaSubitemColor, $entity);
$uow->persist($entity);
}
}
}
//controller - controller - controller - controller
$subitem = new Subitem();
$em = $this->getDoctrine()->getManager();
$subitem->setNombre("jls");
$subitemColor = new SubitemColor();
$subitem->addSubitemColor($subitemColor);
$em->persist($subitem);
$em->persist($subitemColor);
$metaSubitem = $em->getClassMetadata(get_class($subitem));
$em->flush();
Use recomputeSingleEntityChangeSet method instead of computeChangeSet
computeChangeSet method is supposed to be called by doctrine only and calls once for every entity that marked for persistence on flush operation.
When you load entity from database doctrine saves its data to originalEntityData array, then it checks if no original data exists for entity then this entity is new and doctrine saves its current data as original and fill change set with every field value.
On second call of computeChangeSet doctrine has original data for newly created entity and computes change set only for changed fields since last call of computeChangeSet method.
Thats why you should never call computeChangeSet.
I replicated your problem as you can see in the image below.
The problem is; persist() is being used once in your controller (which you cannot do without it) and once in your onFlush() listener (which you cannot do without it as well!!!) so for that reason you get that error.
Event onFlush is called inside EntityManager#flush() after the
changes to all the managed entities and their associations have been
computed.
You're calling persist in your controller and straight after that you're calling another persist in your listener before even flushing it in your controller.
SOLUTION
Based on what you're trying to do, onFlush is not what you need anyway so the one you should use is prePersist so look at the example below.
CONTROLLER
Please checkout entity examples I added at the bottom. As you noted it is 1:N so since child SubitemColor cannot exist without parent Subitem, we're using $subitemColor->setSubitem($subitem); oppose to your example.
public function createAction()
{
$subitem = new Subitem();
$subitemColor = new SubitemColor();
$subitem->setNombre('jls');
$subitemColor->setSubitem($subitem);
$em = $this->getDoctrine()->getManager();
$em->persist($subitem);
$em->persist($subitemColor);
$em->flush();
}
YML
services:
application_backend.event_listener.subitem:
class: Application\BackendBundle\EventListener\SubitemListener
tags:
- { name: doctrine.event_listener, event: prePersist }
LISTENER
namespace Application\BackendBundle\EventListener;
use Application\BackendBundle\Entity\SubitemColor;
use Doctrine\ORM\Event\LifecycleEventArgs;
class SubitemListener
{
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof SubitemColor) {
$entity->setEnStock(2);
}
}
}
RESULT
mysql> SELECT * FROM subitem;
Empty set (0.00 sec)
mysql> SELECT * FROM subitem_color;
Empty set (0.01 sec)
mysql> SELECT * FROM subitem;
+----+------+
| id | name |
+----+------+
| 1 | jls |
+----+------+
1 row in set (0.00 sec)
mysql> SELECT * FROM subitem_color;
+----+------------+------+----------+
| id | subitem_id | code | en_stock |
+----+------------+------+----------+
| 1 | 1 | NULL | 2 |
+----+------------+------+----------+
1 row in set (0.00 sec)
SUBITEM ENTITY
namespace Application\BackendBundle\Entity;
use Application\BackendBundle\Entity\SubitemColor;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="subitem")
*/
class Subitem
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="name", type="string", length=20)
*/
protected $nombre;
/**
* #ORM\OneToMany(targetEntity="SubitemColor", mappedBy="subitem", cascade={"persist", "remove"})
*/
protected $subitemColor;
/**
* Constructor
*/
public function __construct()
{
$this->subitemColor = new ArrayCollection();
}
/**
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #param string $nombre
* #return Subitem
*/
public function setNombre($nombre)
{
$this->nombre = $nombre;
return $this;
}
/**
* #return string
*/
public function getNombre()
{
return $this->nombre;
}
/**
* #param SubitemColor $subitemColor
* #return Subitem
*/
public function addSubitemColor(SubitemColor $subitemColor)
{
$this->subitemColor[] = $subitemColor;
return $this;
}
/**
* #param SubitemColor $subitemColor
*/
public function removeSubitemColor(SubitemColor $subitemColor)
{
$this->subitemColor->removeElement($subitemColor);
}
/**
* #return Collection
*/
public function getSubitemColor()
{
return $this->subitemColor;
}
}
SUBITEMCOLOR ENTITY
namespace Application\BackendBundle\Entity;
use Application\BackendBundle\Entity\Subitem;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="subitem_color")
*/
class SubitemColor
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="code", type="string", length=20, nullable=true)
*/
protected $code;
/**
* #ORM\Column(name="en_stock", type="integer", length=5, nullable=true)
*/
protected $enStock;
/**
* #ORM\ManyToOne(targetEntity="Subitem", inversedBy="subitemColor")
* #ORM\JoinColumn(name="subitem_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)
*/
protected $subitem;
/**
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #param string $code
* #return SubitemColor
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* #return string
*/
public function getCode()
{
return $this->code;
}
/**
* #param integer $enStock
* #return SubitemColor
*/
public function setEnStock($enStock)
{
$this->enStock = $enStock;
return $this;
}
/**
* #return integer
*/
public function getEnStock()
{
return $this->enStock;
}
/**
* #param Subitem $subitem
* #return SubitemColor
*/
public function setSubitem(Subitem $subitem)
{
$this->subitem = $subitem;
return $this;
}
/**
* #return Subitem
*/
public function getSubitem()
{
return $this->subitem;
}
}
This may or may not solve your problem, but when I do this in my code I call $uow->persist($entity); then I call $uow->computeChangeSet($metaSubitemColor, $entity);
Order seems important here as you have persisted changes that then have to be recalculated in the unit of work. So persisting after calling computeChangeSet seems likely to cause problems.
I want to make a choice dropdown form with three choices:
-favored
-intended
-verified
so i could'nt use a boolean for this.
I have no idea how to set my annotations for my status field in the entity. Any help?
/**
* #var boolean
*
* #ORM\Column(name="status", type="boolean")
*/
private $status;
I don't know if I have really understood your question but in fact the boolean field type for symfony2/doctrine2 is a tinyint(1) in SQL database. So you can put integer values from -128 to 127.
Generally for my entities I use this "rule" :
<?php
class MyEntity
{
const STATUS_FAVORED = 1;
const STATUS_INTENTED = 2;
const STATUS_VERIFIED = 3;
/**
* #var integer
*
* #ORM\Column(name="status", type="boolean")
*/
private $status;
public function __construct()
{
$this->status = self::STATUS_FAVORED;
}
/**
* For ur form by example
*/
public static function getStatusForChoiceFormField()
{
return array(
self::STATUS_FAVORED => 'favored',
self::STATUS_INTENTED => 'intented',
self::STATUS_VERIFIED => 'verified'
);
}
}
?>
See u !