Symfony Doctrine Fixture unexpected Null Value - symfony

I can't figure out why this code sends a null value instead of an actual reference to another object entity/record.. This is the message I get in my console while generating my fixtures:
Does anyone know why I get the null value there, instead the actual value ? By the way, don't waste your time looking for an issue in the data looping. It's fine. I have tested this code without data arrays and loop the issue was exactly the same on single entry. That is an unexpected null value.
doctrine:fixtures:load
[Doctrine\DBAL\Exception\NotNullConstraintViolationException] An
exception occurred while executing 'INSERT INTO car_model (model,
inserted_at, last_edited_at, image, fk_car_mark) VALUES (?, ?, ?, ?,
?)' with params ["A3", "2016-07-19 10:27:21", "2016-07-19 10:27:21",
"img", null]: SQLSTATE[23000]: Integrity constraint violation: 1048
Column 'fk_car_mark' cannot be null
This is my code:
DataFixtures->ORM->LoadCarMarkData.php
<?php
namespace AdminBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use AdminBundle\Entity\CarModel;
class LoadCarModelData extends AbstractFixture implements OrderedFixtureInterface
{
public function load(ObjectManager $manager)
{
foreach($this->data as $mark => $modelArray){
// New Entry ----
foreach($modelArray as $model){
$carModel = new CarModel();
$carModel->setModel($model);
$carModel->setImage('img');
$carModel->getFkCarMark($this->getReference($mark));
$manager->persist($carModel);
$manager->flush();
}
}
}
public function getOrder()
{
// the order in which fixtures will be loaded
// the lower the number, the sooner that this fixture is loaded
return 4;
}
private $data = [
'AUDI' => [
'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8',
'Q2', 'Q3', 'Q5', 'Q7',
'TT', 'R8'
],
'SKODA' => [
'Yeti', 'Roomster', 'Superb', 'Rapid', 'Fabia', 'Mission', 'Joyster',
],
];
}
DataFixtures->ORM->LoadCarModelData.php
<?php
namespace AdminBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use AdminBundle\Entity\CarMark;
class LoadCarMarkData extends AbstractFixture implements OrderedFixtureInterface
{
public function load(ObjectManager $manager)
{
foreach($this->data as $entry){
$carMark = new CarMark();
$carMark->setMark(str_replace([' ','/','\\'], ['_'], $entry['mark']));
$manager->persist($carMark);
$manager->flush();
$this->addReference(str_replace([' ','/','\\'], ['_'], $entry['mark']), $carMark);
}
}
public function getOrder() {
return 3;
}
private $data = [
['mark'=>'ACURA'],
['mark'=>'ALFA ROMEO'],
['mark'=>'AMC'],
['mark'=>'ARIEL'],
['mark'=>'ASTON MARTIN'],
['mark'=>'AUDI'],
['mark'=>'AUSTIN HEALEY'],
['mark'=>'BENTLEY'],
['mark'=>'BMW'],
['mark'=>'BUGATTI'],
['mark'=>'BUICK'],
['mark'=>'CADILLAC'],
['mark'=>'CALLAWAY'],
['mark'=>'CATERHAM'],
['mark'=>'CHEVROLET'],
['mark'=>'CHRYSLER'],
['mark'=>'CITROEN'],
['mark'=>'DAEWOO'],
['mark'=>'DAIHATSU'],
['mark'=>'DATSUN'],
['mark'=>'DE TOMASO'],
['mark'=>'DODGE'],
['mark'=>'EAGLE'],
['mark'=>'FERRARI'],
['mark'=>'FIAT'],
['mark'=>'FISKER'],
['mark'=>'FORD'],
['mark'=>'GENESIS'],
['mark'=>'GEO'],
['mark'=>'GMC'],
['mark'=>'HOLDEN'],
['mark'=>'HONDA'],
['mark'=>'HUMMER'],
['mark'=>'HYUNDAI'],
['mark'=>'INFINITI'],
['mark'=>'ISUZU'],
['mark'=>'JAGUAR'],
['mark'=>'JEEP'],
['mark'=>'KIA'],
['mark'=>'KOENIGSEGG'],
['mark'=>'LAMBORGHINI'],
['mark'=>'LANCIA'],
['mark'=>'LAND ROVER'],
['mark'=>'LEXUS'],
['mark'=>'LINCOLN'],
['mark'=>'LOTUS'],
['mark'=>'MASERATI'],
['mark'=>'MAYBACH'],
['mark'=>'MAZDA'],
['mark'=>'MCLAREN'],
['mark'=>'MERCEDES'],
['mark'=>'MERCURY'],
['mark'=>'MG'],
['mark'=>'MINI'],
['mark'=>'MITSUBISHI'],
['mark'=>'MORGAN'],
['mark'=>'MOSLER / ROSSION'],
['mark'=>'NISSAN'],
['mark'=>'NOBLE'],
['mark'=>'OLDSMOBILE'],
['mark'=>'OPEL'],
['mark'=>'PAGANI'],
['mark'=>'PEUGEOT'],
['mark'=>'PLYMOUTH'],
['mark'=>'PONTIAC'],
['mark'=>'PORSCHE'],
['mark'=>'PROTON'],
['mark'=>'RAM'],
['mark'=>'RENAULT'],
['mark'=>'ROLLS-ROYCE'],
['mark'=>'SAAB'],
['mark'=>'SALEEN'],
['mark'=>'SATURN'],
['mark'=>'SCION'],
['mark'=>'SEAT'],
['mark'=>'SHELBY'],
['mark'=>'SKODA'],
['mark'=>'SMART'],
['mark'=>'SSANGYONG'],
['mark'=>'SUBARU'],
['mark'=>'SUZUKI'],
['mark'=>'TESLA'],
['mark'=>'TOYOTA'],
['mark'=>'TRIUMPH'],
['mark'=>'VAUXHALL'],
['mark'=>'VW'],
['mark'=>'VOLVO'],
['mark'=>'WESTFIELD'],
];
}
Entity->CarModel.php
<?php
namespace AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AdminBundle\Entity\CarMark;
/**
* CarModel
*
* #ORM\Table(name="car_model")
* #ORM\Entity(repositoryClass="AdminBundle\Repository\CarModelRepository")
* #ORM\HasLifecycleCallbacks
*/
class CarModel
{
/**
* #var string
*
* #ORM\Column(name="model", type="string", length=255)
* #ORM\Id
*
*/
private $model;
/**
* #var \DateTime
* #ORM\Column(name="inserted_at", type="datetime", nullable=true)
*/
private $insertedAt;
/**
* #var \DateTime
* #ORM\Column(name="last_edited_at", type="datetime", nullable=true)
*/
private $lastEditedAt;
/**
* #var string
*
* #ORM\Column(name="image", type="string", length=255)
*/
private $image;
/**
* #ORM\ManyToOne(targetEntity="CarMark", inversedBy="mark")
* #ORM\JoinColumn(name="fk_car_mark", referencedColumnName="mark", nullable=false)
*/
private $fkCarMark;
/**
* Set insertedAt
*
* #param \DateTime $insertedAt
*
* #return CarMark
*/
public function setInsertedAt(\DateTime $insertedAt)
{
$this->insertedAt = $insertedAt;
return $this;
}
/**
* Get insertedAt
*
* #return \DateTime
*/
public function getInsertedAt()
{
return $this->insertedAt;
}
/**
* Set lastEditedAt
*
* #param \DateTime $lastEditedAt
*
* #return CarMark
*/
public function setLastEditedAt(\DateTime $lastEditedAt)
{
$this->lastEditedAt = $lastEditedAt;
return $this;
}
/**
* Get lastEditedAt
*
* #return \DateTime
*/
public function getLastEditedAt()
{
return $this->lastEditedAt;
}
/**
*
* #ORM\PrePersist
* #ORM\PreUpdate
*/
public function updatedTimestamps()
{
$this->setLastEditedAt(new \DateTime('now'));
if ($this->getInsertedAt() == null) {
$this->setInsertedAt(new \DateTime('now'));
}
}
/**
* Set model
*
* #param string $model
*
* #return CarModel
*/
public function setModel($model)
{
$this->model = $model;
return $this;
}
/**
* Get model
*
* #return string
*/
public function getModel()
{
return $this->model;
}
/**
* Set image
*
* #param string $image
*
* #return CarModel
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set fkCarMark
*
* #param \AdminBundle\Entity\CarMark $fkCarMark
*
* #return CarModel
*/
public function setFkCarMark(\AdminBundle\Entity\CarMark $fkCarMark)
{
$this->fkCarMark = $fkCarMark;
return $this;
}
/**
* Get fkCarMark
*
* #return \AdminBundle\Entity\CarMark
*/
public function getFkCarMark()
{
return $this->fkCarMark;
}
public function __toString() {
return $this->getModel();
}
}

You're only calling the getter getFkCarMark(), but never it's actual setter. By the look of it you need to replace:
$carModel->getFkCarMark($this->getReference($mark));
With:
$carModel->setFkCarMark($this->getReference($mark));
So it actually sets the car mark it has fetched.

Related

Error persisting stof doctrine extension uploadble. Symfony 2.3

This is my controller - right from documentation
<?php
namespace Votes\VotesBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Votes\VotesBundle\Entity\File as File;
class FileController extends Controller
{
/**
* #Template()
*/
public function newAction()
{
$file = new File();
$form = $this->createFormBuilder($file)
->add('name')
->add('file','file')
->getForm()
;
if ($this->getRequest()->getMethod() === 'POST') {
$form->bind($this->getRequest());
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($file);
$uploadableManager = $this->get('stof_doctrine_extensions.uploadable.manager');
// Here, "getMyFile" returns the "UploadedFile" instance that the form bound in your $myFile property
$uploadableManager->markEntityToUpload($file, $file->getFile());
$em->flush();
$this->redirect($this->generateUrl('/file/new'));
}
}
return array('form' => $form->createView());
}
}
Here's my File entity
<?php
se Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* File
*
* #ORM\Table(name="files")
* #ORM\Entity
* #Gedmo\Uploadable( allowOverwrite=true, appendNumber=true, filenameGenerator="SHA1")
*/
class File
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="path", type="string")
* #Gedmo\UploadableFilePath
*/
private $path;
/**
* #ORM\Column(name="name", type="string")
* #Gedmo\UploadableFileName
*/
private $name;
/**
* #ORM\Column(name="mime_type", type="string")
* #Gedmo\UploadableFileMimeType
*/
private $mimeType;
/**
* #ORM\Column(name="size", type="decimal")
* #Gedmo\UploadableFileSize
*/
private $size;
private $file;
public function setFile($file)
{
$this->file = $file;
return $this;
}
public function getFile()
{
return $this->file;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set path
*
* #param string $path
* #return File
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set name
*
* #param string $name
* #return File
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set mimeType
*
* #param string $mimeType
* #return File
*/
public function setMimeType($mimeType)
{
$this->mimeType = $mimeType;
return $this;
}
/**
* Get mimeType
*
* #return string
*/
public function getMimeType()
{
return $this->mimeType;
}
/**
* Set size
*
* #param string $size
* #return File
*/
public function setSize($size)
{
$this->size = $size;
return $this;
}
/**
* Get size
*
* #return string
*/
public function getSize()
{
return $this->size;
}
}
I get this error when submit form:
An exception occurred while executing 'INSERT INTO files (path, name, mime_type, size) VALUES (?, ?, ?, ?)' with params [null, "asdasdasd", null, null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'path' cannot be null
If I'm correct - the uploadable extension - must fill my File entity with
correct data in events? I'm right?

Knp DoctrineBehaviors throws ContextErrorException: Warning: call_user_func_array() expects parameter 1 to be a valid callback

I use symfony2.4 and KNP doctrine behaviors translatable.
I have entity Site (for ID, host, enabled) and entity SiteTranslation (for translated fields: name, descriptions, …).
I use query to get results
$qb = $this->createQueryBuilder('s')
->addSelect('translation') // to eager fetch translations (optional)
->leftJoin('s.translations', 'translation') // or innerJoin ?
->orderBy('s.root', 'ASC')
->addOrderBy('s.lft', 'ASC');
I would like to print result in Twig. For ID, host and enabled fields from Site entity it's easy:
{{ item.id }}
But I can't print translated fields (name, description, …)
{{ item.name }}
It doesn't work.
Error message:
ContextErrorException: Warning: call_user_func_array() expects parameter 1 to be a valid >callback, class 'Net\ConBundle\Entity\SiteTranslation' does not have a method 'name' in >D:\Users...\vendor\knplabs\doctrine->behaviors\src\Knp\DoctrineBehaviors\Model\Translatable\TranslatableMethods.php line 140
Getters and setters for translatable fields are in SiteTranslation entity.
UPDATE:
I still didn't find a solution for an error.
Here is Site entity:
<?php
namespace Pnet\ConlocoBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* #UniqueEntity("host", message="site.host.unique", groups={"edit"})
* #Gedmo\Tree(type="nested")
* #ORM\Entity(repositoryClass="Pnet\ConlocoBundle\Entity\Repository\SiteRepository")
* #ORM\Table(name="site")
*/
class Site
{
use ORMBehaviors\Translatable\Translatable; // knp translatable strategy
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=40, unique=true)
* #Assert\NotBlank(message="site.host.notBlank", groups={"edit"})
* #Assert\Length(max = "40", maxMessage = "site.host.maxLength", groups={"edit"})
*/
protected $host;
/**
* #ORM\Column(type="string", length=255, nullable=true)
* #Assert\Image()
*/
protected $image;
/**
* #ORM\Column(type="boolean")
* #Assert\Choice(choices = {"1", "0"}, message = "site.isDefault.choice", groups={"edit"})
*/
protected $isDefault;
/**
* #ORM\Column(type="boolean")
* #Assert\Choice(choices = {"1", "0"}, message = "site.enabled.choice", groups={"edit"})
*/
protected $enabled;
/**
* #ORM\Column(type="string", length=64, nullable=true)
*/
protected $analytics;
/**
* #Gedmo\TreeLeft
* #ORM\Column(name="lft", type="integer")
*/
private $lft;
/**
* #Gedmo\TreeLevel
* #ORM\Column(name="lvl", type="integer")
*/
private $lvl;
/**
* #Gedmo\TreeRight
* #ORM\Column(name="rgt", type="integer")
*/
private $rgt;
/**
* #Gedmo\TreeRoot
* #ORM\Column(name="root", type="integer", nullable=true)
*/
private $root;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(targetEntity="Site", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="Site", mappedBy="parent")
* #ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
private $file;
public $idByFilter;
public $nameByFilter;
/**
* Proxy translations (Knp/Doctrine Behaviors)
* An extra feature allows you to proxy translated fields of a translatable entity.
* You can use it in the magic __call method of you translatable entity so that when
* you try to call getName (for example) it will return you the translated value
* of the name for current locale:
*/
public function __call($method, $arguments)
{
return $this->proxyCurrentLocaleTranslation($method, $arguments);
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set host
*
* #param string $host
* #return Site
*/
public function setHost($host)
{
$this->host = $host;
return $this;
}
/**
* Get host
*
* #return string
*/
public function getHost()
{
return $this->host;
}
/**
* Set isDefault
*
* #param boolean $isDefault
* #return Site
*/
public function setIsDefault($isDefault)
{
$this->isDefault = $isDefault;
return $this;
}
/**
* Get isDefault
*
* #return boolean
*/
public function getIsDefault()
{
return $this->isDefault;
}
/**
* Set enabled
*
* #param boolean $enabled
* #return Site
*/
public function setEnabled($enabled)
{
$this->enabled = $enabled;
return $this;
}
/**
* Get enabled
*
* #return boolean
*/
public function getEnabled()
{
return $this->enabled;
}
/**
* Set analytics
*
* #param string $analytics
* #return Site
*/
public function setAnalytics($analytics)
{
$this->analytics = $analytics;
return $this;
}
/**
* Get analytics
*
* #return string
*/
public function getAnalytics()
{
return $this->analytics;
}
/**
* Get ID from Filter
*
* #return string
*/
public function getIdByFilter()
{
return $this->idByFilter;
}
/**
* Get name from Filter
*
* #return string
*/
public function getNameByFilter()
{
return $this->nameByFilter;
}
/**
* Set image
*
* #param string $image
* #return Site
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set file
*
* #param string $file
* #return Site
*/
public function setFile($file)
{
$this->file = $file;
return $this;
}
/**
* Get file
*
* #return string
*/
public function getFile()
{
return $this->file;
}
/**
*
* Tree functions
*/
public function setParent(Site $parent = null)
{
$this->parent = $parent;
}
public function getParent()
{
return $this->parent;
}
public function getRoot()
{
return $this->root;
}
public function getLvl()
{
return $this->lvl;
}
public function getChildren()
{
return $this->children;
}
public function getLft()
{
return $this->lft;
}
public function getRgt()
{
return $this->rgt;
}
/**
* Add a method to the entity class that shows the name indented by nesting level
*/
public function getLeveledName()
{
return str_repeat(
html_entity_decode(' ', ENT_QUOTES, 'UTF-8'),
($this->getLvl()) * 3
) . $this->getName();
}
public function getLeveledPosition()
{
return str_repeat(
html_entity_decode(' ', ENT_QUOTES, 'UTF-8'),
($this->getLvl()) * 3
);
}
}
And here is SiteTranslation entity:
namespace Pnet\ConlocoBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* #ORM\Entity
*/
class SiteTranslation
{
use ORMBehaviors\Translatable\Translation;
/**
* #ORM\Column(type="string", length=60)
* #Assert\NotBlank(message="site.name.notBlank", groups={"edit"})
* #Assert\Length(max = "60", maxMessage = "site.name.maxLength", groups={"edit"})
*/
protected $name;
/**
* #ORM\Column(type="string", length=100)
* #Assert\NotBlank(message="site.title.notBlank", groups={"edit"})
* #Assert\Length(max = "100", maxMessage = "site.title.maxLength", groups={"edit"})
*/
protected $title;
/**
* #ORM\Column(type="string", length=200)
* #Assert\NotBlank(message="site.longTitle.notBlank", groups={"edit"})
* #Assert\Length(max = "200", maxMessage = "site.longTitle.maxLength", groups={"edit"})
*/
protected $longTitle;
/**
* #ORM\Column(type="string", length=250, nullable=true)
* #Assert\Length(max = "250", maxMessage = "site.keywords.maxLength", groups={"edit"})
*/
protected $keywords;
/**
* #ORM\Column(type="string", length=500, nullable=true)
* #Assert\Length(max = "500", maxMessage = "site.description.maxLength", groups={"edit"})
*/
protected $description;
/**
* Set name
*
* #param string $name
* #return Site
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set title
*
* #param string $title
* #return Site
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set longTitle
*
* #param string $longTitle
* #return Site
*/
public function setLongTitle($longTitle)
{
$this->longTitle = $longTitle;
return $this;
}
/**
* Get longTitle
*
* #return string
*/
public function getLongTitle()
{
return $this->longTitle;
}
/**
* Set keywords
*
* #param string $keywords
* #return Site
*/
public function setKeywords($keywords)
{
$this->keywords = $keywords;
return $this;
}
/**
* Get keywords
*
* #return string
*/
public function getKeywords()
{
return $this->keywords;
}
/**
* Set description
*
* #param string $description
* #return Site
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
}
TL;DR:
As a (probably dirty) workaround, use
{{ item.getName }}
in your Twig template instead of
{{ item.name }}
Explanation:
I came across the same issue and i think that this should be considered a bug in the Knp DoctrineBehaviors documentation when used with Twig. When you call this in your Twig template :
{{ item.name }}
This is what Twig does behind the scenes to get the name property :
try to get the name public property of the item object
if not found, checks for the name public method of the item object
if not found, checks for the getName() public method of the "item" object
if not found, checks for the __call() magic method (and calls it with the name parameter)
The problem here is step 4. The magic __call() method that you defined (as recommended by the official DoctrineBehaviors documentation) is called with the name parameter instead of getName. It then calls the proxyCurrentLocaleTranslation() method who tries to call the name public method of your translation class. Of course, it doesn't exist because you only have a getName() method.
See this issue in Twig : https://github.com/twigphp/Twig/issues/342
By using directly the {{ item.getName }} code in Twig, the proper method name will be called.
This work for me:
public function __call($method, $arguments)
{
try {
return $this->proxyCurrentLocaleTranslation($method, $arguments);
} catch (\Symfony\Component\Debug\Exception\ContextErrorException $e) {
return $this->proxyCurrentLocaleTranslation('get' . ucfirst($method), $arguments);
}
}
You haven't moved all the translatable properties/methods to your <Name>Translation class.
The exception clearly states that there is no name/getName method in your SiteTranslation class.
Please read my answer over here to see how Knp\DoctrineBehaviors's magic translation proxy is used correctly.

Cannot set form with populated Entity object get The form's view data is expected to be of type scalar, array or an instance of \ArrayAccess

I have created the EntityClass:
<?php
namespace Rota\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\component\OptionsResolver\OptionsResolverIntrerface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* RotaObj
*
* #ORM\Table()
* #ORM\Entity
*/
class RotaMain
{
public function __construct()
{
$this->rotaShifts = new ArrayCollection();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="MyUserId", type="integer")
*/
private $myUserId;
/**
* #var date
*
* #ORM\Column(name="RotaStartDate", type="date")
*/
private $startDate;
/**
* #var date
*
* #ORM\Column(name="RotaReviewDate", type="date")
*/
private $reviewDate;
/**
* #var integer
*
* #ORM\Column(name="RotaRollingWeeks", type="integer")
*/
private $rollingWeeks;
/**
* #var integer
*
* #ORM\Column(name="restDayCount", type="integer")
*/
private $restDayCount;
/**
* #var integer
*
* #ORM\Column(name="totalDayCount", type="integer")
*/
private $totalDayCount;
/**
* #ORM\OneToMany(targetEntity="RotaShift",mappedBy="rotaMain",cascade={"persist"})
*/
protected $rotaShifts;
/**
* #var string
*
* #ORM\Column(name="shiftOrder",type="string",length=4000,nullable=true)
*/
private $shiftOrder;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set myUserId
*
* #param integer $myUserId
* #return RotaObj
*/
public function setMyUserId($myUserId)
{
$this->myUserId = $myUserId;
return $this;
}
/**
* Get myUserId
*
* #return integer
*/
public function getMyUserId()
{
return $this->myUserId;
}
/**
* Set startDate
*
* #param \DateTime $startDate
* #return RotaObj
*/
public function setStartDate($startDate)
{
$this->startDate = $startDate;
return $this;
}
/**
* Get startDate
*
* #return \DateTime
*/
public function getStartDate()
{
return $this->startDate;
}
/**
* Set reviewDate
*
* #param \DateTime $reviewDate
* #return RotaObj
*/
public function setReviewDate($reviewDate)
{
$this->reviewDate = $reviewDate;
return $this;
}
/**
* Get reviewDate
*
* #return \DateTime
*/
public function getReviewDate()
{
return $this->reviewDate;
}
/**
* Set rollingWeeks
*
* #param integer $rollingWeeks
* #return RotaObj
*/
public function setRollingWeeks($rollingWeeks)
{
$this->rollingWeeks = $rollingWeeks;
return $this;
}
/**
* Get rollingWeeks
*
* #return integer
*/
public function getRollingWeeks()
{
return $this->rollingWeeks;
}
/**
* Add rotaShifts
*
* #param \Rota\Bundle\Entity\RotaShift $rotaShifts
* #return RotaMain
*/
public function addRotaShift(\Rota\Bundle\Entity\RotaShift $rotaShift)
{
$this->rotaShifts[] = $rotaShift;
return $this;
}
/**
* Remove rotaShifts
*
* #param \Rota\Bundle\Entity\RotaShift $rotaShifts
*/
public function removeRotaShift(\Rota\Bundle\Entity\RotaShift $rotaShifts)
{
$this->rotaShifts->removeElement($rotaShifts);
}
/**
* Get rotaShifts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getRotaShifts()
{
return $this->rotaShifts;
}
/**
* Set restDayCount
*
* #param integer $restDayCount
* #return RotaMain
*/
public function setRestDayCount($restDayCount)
{
$this->restDayCount = $restDayCount;
return $this;
}
/**
* Get restDayCount
*
* #return integer
*/
public function getRestDayCount()
{
return $this->restDayCount;
}
/**
* Set totalDayCount
*
* #param integer $totalDayCount
* #return RotaMain
*/
public function setTotalDayCount($totalDayCount)
{
$this->totalDayCount = $totalDayCount;
return $this;
}
/**
* Get totalDayCount
*
* #return integer
*/
public function getTotalDayCount()
{
return $this->totalDayCount;
}
/**
* Set shiftOrder
*
* #param string $shiftOrder
* #return RotaMain
*/
public function setShiftOrder($shiftOrder)
{
$this->shiftOrder = $shiftOrder;
return $this;
}
/**
* Get shiftOrder
*
* #return string
*/
public function getShiftOrder()
{
return $this->shiftOrder;
}
}
This class holds collection of:
<?php
namespace Rota\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* RotaShift
*
* #ORM\Table()
* #ORM\Entity
*/
class RotaShift
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $_id;
/**
* #var integer
*
* #ORM\Column(name="startTime", type="integer")
*/
private $_startTime;
/**
* #var integer
*
* #ORM\Column(name="endTime", type="integer")
*/
private $endTime;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=50)
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="RotaMain", inversedBy="rotaShifts")
*/
private $rotaMain;
/**
* Get _id
*
* #return integer
*/
public function getId()
{
return $this->_id;
}
/**
* Set _startTime
*
* #param integer $startTime
* #return RotaShift
*/
public function setStartTime($startTime)
{
$this->_startTime = $startTime;
return $this;
}
/**
* Get _startTime
*
* #return integer
*/
public function getStartTime()
{
return $this->_startTime;
}
/**
* Set endTime
*
* #param integer $endTime
* #return RotaShift
*/
public function setEndTime($endTime)
{
$this->endTime = $endTime;
return $this;
}
/**
* Get endTime
*
* #return integer
*/
public function getEndTime()
{
return $this->endTime;
}
/**
* Set name
*
* #param string $name
* #return RotaShift
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set rotaMain
*
* #param \Rota\Bundle\Entity\RotaMain $rotaMain
* #return RotaShift
*/
public function setRotaMain(\Rota\Bundle\Entity\RotaMain $rotaMain = null)
{
$this->rotaMain = $rotaMain;
return $this;
}
/**
* Get rotaMain
*
* #return \Rota\Bundle\Entity\RotaMain
*/
public function getRotaMain()
{
return $this->rotaMain;
}
}
I have then created a Form EntityType class for the RotaMain object as follows:
<?php
namespace Rota\Bundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class RotaMainType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder-> add('ReviewDate','date');
$builder->add('RollingWeeks','integer');
$builder->add('StartDate','date');
$builder->add('RestDayCount','integer',array('label' => 'Number of rest days'));
$builder->add('TotalDayCount','integer',array('label' => 'Total number of days in shift pattern'));
$builder->add('rotaShifts','collection',array('type'=> new RotaShiftType(),'label' => false,'allow_add' => true,));
$builder->add('Save','submit');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Rota\Bundle\Entity\RotaMain',
));
}
public function getName()
{
return 'rotaMain';
}
}
When I try to set a form with a fully populated RotaMain object:
$form = $this->createForm(new RotaMainType(),$RotaMain);
I get the following error:
The form's view data is expected to be of type scalar, array or an instance of
\ArrayAccess, but is an instance of class Rota\Bundle\Entity\RotaMain. You can avoid
this error by setting the "data_class" option to "Rota\Bundle\Entity\RotaMain" or by
adding a view transformer that transforms an instance of class
Rota\Bundle\Entity\RotaMain to scalar, array or an instance of \ArrayAccess.
I have set the data_class in the RotaMainType object so am not sure where I am going wrong? If I pass an empty RotaMain object to the form it builds as expected.
The population of RotaMain happens in the controller. The form is part one of two part process. If user has completed first part gone away and come back I want reutnr the first part fo them to review before going onto the second part of the process. Controller action:
public function setRotaAction(Request $request,$userId)
{
//Check to see if user has part set up a rota - return completed form for review
$RotaMainRepos = $this->getDoctrine()->getManager()->getRepository("RotaBundle:RotaMain");
$id = $this->getUser()->getID();
$criteria = array("myUserId"=>$id);
$result = $RotaMainRepos->findBy($criteria);
if($result == null)
{
$RotaMain = new RotaMain();
$RotaMain->setmyUserId($userId);
$form = $this->createForm(new RotaMainType(),$RotaMain);
}
else
{
$RotaMain = $result[0];
$rotashiftRepo = $this->getDoctrine()->getManager()->getRepository("RotaBundle:RotaShift");
$rotaShifts = $rotashiftRepo->findByRotaMain($RotaMain);
foreach($rotaShifts as $rotaShift)
{
$RotaMain->addRotaShift($rotaShift);
}
$form = $this->createForm(new RotaMainType(),$RotaMain);
}
$form->handleRequest($request);
if($form->isValid())
{
$early = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($early);
$shifts = $early->getRotaShifts();
foreach($shifts as $shift)
{
$shift->setRotaMain($early);
$em->persist($shift);
}
$em->flush();
$shiftOrder = new ShiftOrder($shifts,$early->getRestDayCount(),$early->getTotalDayCount());
return $this->render("RotaBundle:Default:shiftOrder.html.twig",array("shiftOrder" => $shiftOrder));
}
return $this->render('RotaBundle:Default:setRota.html.twig',array("form" => $form->createView(),));
}
You have to bind a newly created or existing entity/object of the same type as the configured data_class to your form.
If you don't set the variable you're passing to your form to an object of the expected data_class symfony won't create the object but throw this exception.
In your case you might want to use a SensioFrameworkExtraBundle's #ParamConverter to fetch your entity from database and have your controller cleaned up.
/**
* #Route("/whatever/{id}")
* #ParamConverter("rotaMain", class="RotaBundle:RotaMain", options={"mapping": {"MyUserId": "id"}})
*/
public function editAction(RotaMain $rotaMain, Request $request)
{
$form = $this->createForm(new RotaMainType(), $rotaMain);
$form->handleRequest($request);
if ($form->isValid()) {
//
}
}
... or ...
public function newAction(Request $request)
{
$form = $this->createForm(new RotaMainType(), $rotaMain = new RotaMain());
$form->handleRequest($request);
if ($form->isValid()) {
//
}
}
Found the answer to this - it was the way I was accessing and setting MyRotaShift entities in RotaMain. My addRotashift() function was not correctly adding rotaShifts to the Doctrine ArrayColleciton. On changing my controller code to:
foreach($rotaShifts as $rotaShift)
{
$RotaMain->getRotaShifts()->add($rotaShift);
}
it all works. Thought I was going mad for a while!!!
Turns out not mad but I should have read the Doctrine docs before pushing ahead. If I had I would have realized that is uses Lazy loading and saved myself a load of bother!!!
Have accepted nifr's answer as it provides a good way to do what I was trying to accomplish

How to use group

I use FOSUserBundle and 'group' function
At first in my User.php
There were such getter and setter
/**
* Add groups
*
* #param \Acme\UserBundle\Entity\Group $groups
* #return User
*/
public function addGroup(\Acme\UserBundle\Entity\Group $groups)
{
$this->groups[] = $groups;
return $this;
}
/**
* Remove groups
*
* #param \Acme\UserBundle\Entity\Group $groups
*/
public function removeGroup(\Acme\UserBundle\Entity\Group $groups)
{
$this->groups->removeElement($groups);
}
/**
* Get groups
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getGroups()
{
return $this->groups;
}
but,this error happens
FatalErrorException: Compile Error: Declaration of Acme\UserBundle\Entity\User::addGroup() must be compatible with that of FOS\UserBundle\Model\GroupableInterface::addGroup()
in FOS\UserBundle\Model\GroupableInterface
public function addGroup(GroupInterface $group);
in my Acme\UserBundle\Entity\User
public function addGroup(\Acme\UserBundle\Entity\Group $groups)
{
$this->groups[] = $groups;
return $this;
}
How can I adjust the argument type or correct this error?
For now,I have commented out these three function.
at that time it looked works well.
But now ,I use Sonataadmin bundle and in
#SonataAdminBundle/Admin/UserAdmin.php
protected function configureFormFields(FormMapper $formMapper){
$formMapper
->with('General')
->add('groups','entity',array('property' => 'name',
'multiple' => true,
'class' => 'UserBundle:Group',
))
}
it shows this form correctly but when I push submit button to regist,
it shows
Error: Call to a member function contains() on a non-object in ~~~/FOS/UserBundle/Model/User.php line 572
in /FOS/UserBundle/Model/user.php
there is function likt this
public function addGroup(GroupInterface $group)
{
var_dump($group);# I added to check
if (!$this->getGroups()->contains($group)) {
$this->getGroups()->add($group);
}
return $this;
}
var_dump($group) shows
object(Acme\UserBundle\Entity\Group)#923 (3) { ["id":protected]=> int(2) ["name":protected]=> string(12) "TeacherGroup" ["roles":protected]=> array(0) { } }
I guess it has group information correctly..
How can I fix this problem?
my whole user.php
// src/Acme/UserBundle/Entity/User.php
namespace Acme\UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use FOS\UserBundle\Model\GroupableInterface;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
* #ORM\HasLifecycleCallbacks
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
*/
protected $id;
/**
*
* #ORM\OneToOne(targetEntity="Acme\UserBundle\Entity\Lesson", mappedBy="teacher")
*/
private $LessonAsTeacher;
/**
*
* #ORM\OneToMany(targetEntity="Acme\UserBundle\Entity\Lesson", mappedBy="student*removethis : name of the variable in Lesson.php*")
*/
private $LessonAsStudent;
/**
*
* #ORM\ManyToOne(targetEntity="Acme\UserBundle\Entity\Sex", inversedBy="sex*removethis : name of the variable in user.php*")
* #ORM\JoinColumn(name="sex", referencedColumnName="id",nullable=false)
*/
private $sex;
/**
* #ORM\ManyToMany(targetEntity="Acme\UserBundle\Entity\Group")
* #ORM\JoinTable(name="fos_user_user_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
/**
* #ORM\Column(type="string", length=255)
*
* #Assert\NotBlank(message="Please enter your first name.", groups={"Registration", "Profile"})
* #Assert\MinLength(limit="0", message="The name is too short.", groups={"Registration", "Profile"})
* #Assert\MaxLength(limit="255", message="The name is too long.", groups={"Registration", "Profile"})
*/
protected $firstname;
/**
* #ORM\Column(type="string", length=255)
*
* #Assert\NotBlank(message="Please enter your last name.", groups={"Registration", "Profile"})
* #Assert\MinLength(limit="0", message="The name is too short.", groups={"Registration", "Profile"})
* #Assert\MaxLength(limit="255", message="The name is too long.", groups={"Registration", "Profile"})
*/
protected $lastname;
/**
* #ORM\Column(type="date")
*/
protected $birthday;
/**
* #var \DateTime
*
* #ORM\Column(name="createdAt", type="datetime")
*/
private $createdAt;
/**
* #var \DateTime
*
* #ORM\Column(name="updatedAt", type="datetime")
*/
private $updatedAt;
public function __construct()
{
parent::__construct();
// your own logic
}
public function getFirstname()
{
return $this->firstname;
}
public function setFirstname($name)
{
$this->firstname = $name;
return $this;
}
public function getLastname()
{
return $this->lastname;
}
public function setLastname($name)
{
$this->lastname = $name;
return $this;
}
public function getSex()
{
return $this->sex;
}
public function setSex($sex)
{
$this->sex = $sex;
return $this;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set age
*
* #param integer $age
* #return User
*/
public function setAge($age)
{
$this->age = $age;
return $this;
}
/**
* Get age
*
* #return integer
*/
public function getAge()
{
return $this->age;
}
/**
* Set birthday
*
* #param \DateTime $birthday
* #return User
*/
public function setBirthday($birthday)
{
$this->birthday = $birthday;
return $this;
}
/**
* Get birthday
*
* #return \DateTime
*/
public function getBirthday()
{
return $this->birthday;
}
/**
* #ORM\PrePersist
*/
public function prePersist()
{
$this->createdAt = new \DateTime;
$this->updatedAt = new \DateTime;
}
/**
* #ORM\PreUpdate
*/
public function preUpdate()
{
$this->updatedAt = new \DateTime;
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
* #return User
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
* #return User
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Get groups
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getGroups()
{
return $this->groups;
}
/**
* Add groups
*
* #param \Acme\UserBundle\Entity\Group $groups
* #return User
*/
// public function addGroup(\Acme\UserBundle\Entity\Group $groups)
// {
// $this->groups[] = $groups;
// return $this;
// }
/**
* Remove groups
*
* #param \Acme\UserBundle\Entity\Group $groups
*/
// public function removeGroup(\Acme\UserBundle\Entity\Group $groups)
// {
// $this->groups->removeElement($groups);
// }
}
my whole Group.php
namespace Acme\UserBundle\Entity;
use FOS\UserBundle\Entity\Group as BaseGroup;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="fos_group")
*/
class Group extends BaseGroup
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
The problem is that you override getGroups() like this:
/**
* Get groups
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getGroups()
{
return $this->groups;
}
But you never initialized $this->groups, so when you call $this->getGroups()->contains(), it says that $this->getGroups() is a non-object, which is true!
To solve this you have 2 solutions.
You can initialize groups in the constructor of User:
public function __construct()
{
parent::__construct();
&this->groups = new ArrayCollection();
}
Or you can change the getGroups() function to return a new object if groups hasn't been initialized:
public function getGroups()
{
return $this->groups ?: $this->groups = new ArrayCollection();
}
In both cases, don't forget to add use Doctrine\Common\Collections\ArrayCollection; at the beginning of User.php.
I got the same error:
FatalErrorException: Compile Error: Declaration of Acme\UserBundle\Entity\User::addGroup() must be compatible with that of FOS\UserBundle\Model\GroupableInterface::addGroup()
After searching I found out (FOS Git Issue 988) that this special error is a Doctrine 'Bug' or sth.
Doctrine should not generate the method at all because there is an implementation of addGroup() in the base class.
I worked around it by modifying the signature from
public function addGroup(\MyBundleNamespace\Entity\Group $groups)
public function removeGroup(\MyBundleNamespace\Entity\Group $groups)
to
public function addGroup(\FOS\UserBundle\Model\GroupInterface $groups)
public function removeGroup(\FOS\UserBundle\Model\GroupInterface $groups)
This way you prevent Doctrine from generating these two functions with the wrong signature.
Version Infos:
Symfony 2.2.1
DoctrineORM 2.2.3
FOSUserBundle 1.3.1
PHP 5.4.4-14
Maybe this can help someone else!
I came across this problem and the simple solution was to change the declaration of the groups variable from public to protected:
/**
* #var \Doctrine\Common\Collections\Collection
*/
protected $groups;
solution is simply: remove all setters and getters from your own entity in your own userBundle and always run doctrine:generate:entities for specyfic bundle, not for all.

Symfony2 form collection

I have this entity (Registro):
<?php
namespace Gitek\RegistroBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Gitek\RegistroBundle\Entity\Registro
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Gitek\RegistroBundle\Entity\RegistroRepository"))
*/
class Registro
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var datetime $fecha
*
* #ORM\Column(name="fecha", type="datetime")
*/
private $fecha;
/**
* #var smallint $comenzado
*
* #ORM\Column(name="comenzado", type="smallint", nullable=true)
*/
private $comenzado;
/**
* #var smallint $completado
*
* #ORM\Column(name="completado", type="smallint", nullable=true)
*/
private $completado;
/**
* #var datetime $created_at
*
* #ORM\Column(name="created_at", type="datetime")
*/
private $created_at;
/**
* #var datetime $updated_at
*
* #ORM\Column(name="updated_at", type="datetime")
*/
private $updated_at;
/** #ORM\ManyToOne(targetEntity="Gitek\UsuarioBundle\Entity\Usuario") */
protected $usuario;
/** #ORM\ManyToOne(targetEntity="Gitek\HotelBundle\Entity\Tipotarea") */
protected $tipotarea;
/** #ORM\ManyToOne(targetEntity="Gitek\HotelBundle\Entity\Habitacion") */
protected $habitacion;
/** #ORM\ManyToOne(targetEntity="Gitek\RegistroBundle\Entity\Master") */
protected $master;
/**
* #ORM\ManyToMany(targetEntity="Gitek\HotelBundle\Entity\Incidencia", inversedBy="registros")
* #ORM\JoinTable(name="incidencia_registro",
* joinColumns={#ORM\JoinColumn(name="registro_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="incidencia_id", referencedColumnName="id")}
* )
*/
protected $incidencias;
public function __construct()
{
$this->created_at = new \DateTime();
$this->updated_at = new \DateTime();
}
// public function __toString()
// {
// return $this->getNombre();
// }
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set fecha
*
* #param datetime $fecha
*/
public function setFecha($fecha)
{
$this->fecha = $fecha;
}
/**
* Get fecha
*
* #return datetime
*/
public function getFecha()
{
return $this->fecha;
}
/**
* Set comenzado
*
* #param smallint $comenzado
*/
public function setComenzado($comenzado)
{
$this->comenzado = $comenzado;
}
/**
* Get comenzado
*
* #return smallint
*/
public function getComenzado()
{
return $this->comenzado;
}
/**
* Set completado
*
* #param smallint $completado
*/
public function setCompletado($completado)
{
$this->completado = $completado;
}
/**
* Get completado
*
* #return smallint
*/
public function getCompletado()
{
return $this->completado;
}
/**
* 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 updated_at
*
* #param datetime $updatedAt
*/
public function setUpdatedAt($updatedAt)
{
$this->updated_at = $updatedAt;
}
/**
* Get updated_at
*
* #return datetime
*/
public function getUpdatedAt()
{
return $this->updated_at;
}
/**
* Set usuario
*
* #param Gitek\UsuarioBundle\Entity\Usuario $usuario
*/
public function setUsuario(\Gitek\UsuarioBundle\Entity\Usuario $usuario)
{
$this->usuario = $usuario;
}
/**
* Get usuario
*
* #return Gitek\UsuarioBundle\Entity\Usuario
*/
public function getUsuario()
{
return $this->usuario;
}
/**
* Set tipotarea
*
* #param Gitek\HotelBundle\Entity\Tipotarea $tipotarea
*/
public function setTipotarea(\Gitek\HotelBundle\Entity\Tipotarea $tipotarea)
{
$this->tipotarea = $tipotarea;
}
/**
* Get tipotarea
*
* #return Gitek\HotelBundle\Entity\Tipotarea
*/
public function getTipotarea()
{
return $this->tipotarea;
}
/**
* Set habitacion
*
* #param Gitek\HotelBundle\Entity\Habitacion $habitacion
*/
public function setHabitacion(\Gitek\HotelBundle\Entity\Habitacion $habitacion)
{
$this->habitacion = $habitacion;
}
/**
* Get habitacion
*
* #return Gitek\HotelBundle\Entity\Habitacion
*/
public function getHabitacion()
{
return $this->habitacion;
}
/**
* Add incidencias
*
* #param Gitek\HotelBundle\Entity\Incidencia $incidencias
*/
public function addIncidencia(\Gitek\HotelBundle\Entity\Incidencia $incidencias)
{
$this->incidencias[] = $incidencias;
}
/**
* Get incidencias
*
* #return Doctrine\Common\Collections\Collection
*/
public function getIncidencias()
{
return $this->incidencias;
}
}
I wanted to save multiple data on a row, so I created a new Entity with only an array propery like this (Master):
<?php
namespace Gitek\RegistroBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
class Master
{
/** #ORM\OneToMany(targetEntity="Gitek\HotelBundle\Entity\Habitacion", mappedBy="master") */
protected $registros;
public function __construct()
{
$this->registros = new ArrayCollection();
}
public function getRegistros()
{
return $this->registros;
}
public function setRegistros(ArrayCollection $registros)
{
$this->registros = $registros;
}
}
I created my MasterType like this:
<?php
namespace Gitek\RegistroBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Doctrine\ORM\EntityRepository;
class MasterType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('registros', 'collection', array(
'type' => new RegistroType(),
'allow_add' => true,
'by_reference' => true,
));
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'Gitek\RegistroBundle\Entity\Master'
);
}
public function getName()
{
return 'master';
}
}
And this is my controller:
public function asignarAction()
{
$master = new Master();
$request = $this->getRequest();
$form = $this->createForm(new MasterType(), $master);
if ('POST' === $request->getMethod()) {
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($master);
$em->flush();
return $this->redirect($this->generateUrl('recepcion_asignar'));
}else {
print_r("ezez");
print_r($form->getErrors());
}
} else {
}
return $this->render('RegistroBundle:Recepcion:asignar.html.twig', array(
'registro' => $master,
'form' => $form->createView()
));
}
The form works ok, and I see the data is submited correctly but it is not persisted, I´m getting this error all the time:
Class Gitek\RegistroBundle\Entity\Master is not a valid entity or mapped super class.
I think that the problem is within de Master entity.
Any help or clue?
You missed the #Entity annotation on your Master class, you will also need a master table on your database for this to work.
If you don't want to create the master table, then you can skip the #Entity annotation, but you can not persist master. Instead you would have to iterate through the collection and persist only the entities in the array.

Resources