I am trying to use BeelabTagBundle library to implements tags on my website. But I am in a lack of information to do so. Here is where I am at now:
Installed via composer
Created an entity that implements "TaggableInterface" with some personals fields, and the requested ones in the documentation.
/**
* Constructor
*/
public function __construct()
{
$this->keywords = new ArrayCollection();
}
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id = null;
/**
* #ORM\Column(type="string", length=255)
*/
private $type;
/**
* #ORM\Column(type="string", length=255)
*/
private $fileName;
/**
* #ORM\Column(type="boolean")
*/
private $active;
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Tag")
*/
private $keywords;
private $tagsText;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
private $updated;
/**
* {#inheritdoc}
*/
public function addTag(TagInterface $tag)
{
$this->keywords[] = $tag;
}
/**
* {#inheritdoc}
*/
public function removeTag(TagInterface $tag)
{
$this->keywords->removeElement($tag);
}
/**
* {#inheritdoc}
*/
public function hasTag(TagInterface $tag)
{
return $this->keywords->contains($tag);
}
/**
* {#inheritdoc}
*/
public function getTags()
{
return $this->keywords;
}
/**
* {#inheritdoc}
*/
public function getTagNames(): array
{
return empty($this->tagsText) ? [] : array_map('trim', explode(',', $this->tagsText));
}
/**
* #param string
*/
public function setTagsText($tagsText)
{
$this->tagsText = $tagsText;
$this->updated = new \DateTime();
}
/**
* #return string
*/
public function getTagsText()
{
$this->tagsText = implode(', ', $this->keywords->toArray());
return $this->tagsText;
}
Have my route to get the json of my tags (working when calling it but empty)
/**
* #Route("/miseenpage/keywords.json", name="keywords", defaults={"_format": "json"})
*/
public function tagsAction() {
$tags = $this->getDoctrine()->getRepository(Tag::class)->findBy([], ['name' => 'ASC']);
return $this->render('miseenpage/keywords.html.twig', ['tags' => $tags]);
}
I also followed the Javascript enhancement, So I now have created a "TagsTextType"
class TagsTextType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tagsText', TextType::class, ['required' => false, 'label' => 'Tags'])
;
}
/**
* #var RouterInterface $route
*/
private $router;
/**
* #param RouterInterface $router
*/
public function __construct(RouterInterface $router)
{
$this->router = $router;
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'required' => false,
'label' => 'Tags',
'attr' => [
'placeholder' => 'separate tags with comma',
'data-ajax' => $this->router->generate('keywords'),
],
]);
}
/**
* {#inheritdoc}
*/
public function getParent()
{
return TextType::class;
}
}
How can I show my tag field now (alongside with all my other data from my entity) ? This is not detailed in the documentation. Thanks
Related
I created a datatransformer to store dates on unixtime on the database but show it as datetime on the form
this is the transformer
class IntegerToTimestampTransformer implements DataTransformerInterface
{
public function transform($timestamp)
{
/**
* This if sentenceis because when eidt $timestamp is a timestamp(unix)
* but when create is a DateTime ¿¿???
*/
if($timestamp instanceof \DateTime){
return $timestamp;
}
return (new \DateTime())->setTimestamp($timestamp);
}
public function reverseTransform($datetime)
{
if ($datetime === null) {
return $datetime;
}
return $datetime->getTimestamp();
}
}
this is the entity
/**
* Popup
*
* #ORM\Table(name="popup")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PopUpRepository")
*/
class Popup
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #Gedmo\Translatable()
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #Gedmo\Translatable()
* #ORM\Column(name="description", type="text")
*/
private $description;
/**
* #var int
*
* #ORM\Column(name="activation_date", type="integer", nullable=true)
*/
private $activationDate;
/**
* #var int
*
* #ORM\Column(name="deactivation_date", type="integer", nullable=true)
*/
private $deactivationDate;
/**
* #var boolean
*
* #ORM\Column(name="active", type="boolean")
*/
private $active;
/**
* #var Collection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Role")
* #ORM\JoinTable(name="popup_role", joinColumns={#ORM\JoinColumn(name="popup_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="role_id", referencedColumnName="id")})
*/
private $roles;
public function __construct()
{
$this->roles = new ArrayCollection();
}
/**
* #return int
*/
public function getId(): int
{
return $this->id;
}
/**
* #param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
/**
* #return string
*/
public function getTitle():? string
{
return $this->title;
}
/**
* #param string $title
*/
public function setTitle(string $title): void
{
$this->title = $title;
}
/**
* #return string
*/
public function getDescription(): ?string
{
return $this->description;
}
/**
* #param string $description
*/
public function setDescription(string $description): void
{
$this->description = $description;
}
/**
* #return int
*/
public function getActivationDate(): ?int
{
return $this->activationDate;
}
/**
* #param int $activationDate
*/
public function setActivationDate(int $activationDate): void
{
$this->activationDate = $activationDate;
}
/**
* #return int
*/
public function getDeactivationDate(): ?int
{
return $this->deactivationDate;
}
/**
* #param int $deactivationDate
*/
public function setDeactivationDate(int $deactivationDate): void
{
$this->deactivationDate = $deactivationDate;
}
/**
* #return bool
*/
public function isActive(): ?bool
{
return $this->active;
}
/**
* #param bool $active
*/
public function setActive(bool $active): void
{
$this->active = $active;
}
/**
* Add role
*
* #param Role $role
*
* #return Role
*/
public function addRole(Role $role)
{
$this->roles[] = $role;
return $this;
}
/**
* Remove role
*
* #param Role $role
*/
public function removeRole(Role $role)
{
$this->roles->removeElement($role);
}
/**
* Get role
*
* #return Collection
*/
public function getRoles()
{
return $this->roles;
}
}
and the formtype
class PopupType extends AbstractType
{
private $tranformer;
public function __construct(IntegerToTimestampTransformer $tranformer){
$this->tranformer = $tranformer;
}
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$date_array = [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false
];
if(!$options['edit']){
$date_array['data'] = new \DateTime();
}
$builder
->add('title', TextType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
])
->add('description', TextareaType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false
])
->add('activation_date', DateTimeType::class, $date_array)
->add('deactivation_date', DateTimeType::class,$date_array)
->add('active', CheckboxType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false
])
->add('roles', EntityType::class, [
'class' => Role::class,
'expanded' => true,
'multiple' => true,
'required' => true,
'label_attr' => [
'class' => 'font-weight-bold'
],
])
;
$builder->get('activation_date')->addModelTransformer($this->tranformer);
$builder->get('deactivation_date')->addModelTransformer($this->tranformer);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Popup::class,
'edit' => false
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_popup';
}
}
I debugged and I checked that in the transform function when I try to create on the crud the parameter passed to transform is a Datetime the there is no need to transformate the data but when I try to edit the parameter passed to transform is a unixtime integer the the transformation is needed, I don't understant that behaviour.
I'm using Sonata Admin for the first time, I followed doc online and my admin works well, except I have an error when I try to create elements via my admin:
Failed to create object: App\Entity\HomeBlockElement
I have my HomeBlockElement
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\HomeBlockElementRepository")
* #ORM\Table(name="home_block_element")
*/
class HomeBlockElement
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(name="home_element_id",type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="home_element_title", type="string", length=255)
*/
protected $title;
/**
* #var string
*
* #ORM\Column(name="home_element_text_link", type="string", length=255)
*/
protected $textLink;
/**
* #var string
*
* #ORM\Column(name="home_element_shopping_link", type="string", length=255)
*/
protected $shoppingLink;
/**
* #var string
*
* #ORM\Column(name="home_element_marketing_etiquette", type="string", length=255)
*/
protected $marketingEtiquette;
/**
* #var string
*
* #ORM\Column(name="home_element_media", type="text")
*/
protected $media;
/**
* #var bool
*
* #ORM\Column(name="home_element_published", type="boolean")
*/
protected $published = false;
public function getId(): ?int
{
return $this->id;
}
/**
* #return string
*/
public function getTitle(): ?string
{
return $this->title;
}
/**
* #param string $title
* #return HomeBlockElement
*/
public function setTitle(?string $title): HomeBlockElement
{
$this->title = $title;
return $this;
}
/**
* #return string
*/
public function getTextLink(): ?string
{
return $this->textLink;
}
/**
* #param string $textLink
* #return HomeBlockElement
*/
public function setTextLink(?string $textLink): HomeBlockElement
{
$this->textLink = $textLink;
return $this;
}
/**
* #return string
*/
public function getShoppingLink(): ?string
{
return $this->shoppingLink;
}
/**
* #param string $shoppingLink
* #return HomeBlockElement
*/
public function setShoppingLink(?string $shoppingLink): HomeBlockElement
{
$this->shoppingLink = $shoppingLink;
return $this;
}
/**
* #return string
*/
public function getMarketingEtiquette(): ?string
{
return $this->marketingEtiquette;
}
/**
* #param string $categoryLink
* #return HomeBlockElement
*/
public function setMarketingEtiquette(?string $marketingEtiquette): HomeBlockElement
{
$this->marketingEtiquette = $marketingEtiquette;
return $this;
}
/**
* #return bool
*/
public function isPublished(): bool
{
return $this->published;
}
/**
* #param bool $published
* #return Page
*/
public function setPublished(bool $published): HomeBlockElement
{
$this->published = $published;
return $this;
}
}
And my HomeBlockElementAdmin:
<?php
namespace App\Admin;
use App\Entity\Page;
use FOS\CKEditorBundle\Form\Type\CKEditorType;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
final class HomeBlockElementAdmin extends AbstractAdmin
{
protected $datagridValues = array(
'_sort_order' => 'ASC',
'_sort_by' => 'title',
);
/**
* #param $object
* #return string|null
*/
public function toString($object): ?string
{
return $object instanceof Page && $object->getTitle()
? $object->getTitle()
: 'Nouveau bloc élément';
}
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Contenu')
->add('published', CheckboxType::class, ['required' => false, 'label' => 'Publier'])
->add('title', TextType::class, ['required' => true, 'label' => 'Titre'])
->add('marketingEtiquette', TextType::class, ['required' => false, 'label' => 'Etiquette Marketing'])
->add('textLink', TextType::class, ['required' => true, 'label' => 'Texte'])
->add('shoppinglink', TextType::class, ['required' => true, 'label' => 'Lien'])
->end();
}
protected function configureListFields(ListMapper $listMapper)
{
unset($this->listModes['mosaic']);
$listMapper
->addIdentifier('title')
->addIdentifier('marketingEtiquette')
->addIdentifier('textLink')
->addIdentifier('shoppinglink')
->addIdentifier('published')
;
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('title')
->add('marketingEtiquette')
->add('textLink')
->add('shoppinglink')
->add('published');
}
/**
* #param RouteCollection $collection
*/
protected function configureRoutes(RouteCollection $collection)
{
$collection
->remove('delete')
//->remove('create')
->add('move', $this->getRouterIdParameter() . '/move/{position}');
}
}
I then defined this in my services.yaml
admin.element:
class: App\Admin\HomeBlockElementAdmin
arguments: [~, App\Entity\HomeBlockElement, ~]
tags:
- { name: sonata.admin, manager_type: orm, label: 'Element blocs', group: 'app.admin.group.home' }
I've updated the data base with php bin/console doctrine:schema:update to make it match with my code and everything worked fine.From what I saw on the Internet, the error is related to SQL but
I can't see where the error comes from.
In the breadrcumb from the error I can see:
PDOException > PDOException > NotNullConstraintViolationException > ModelManagerException
So the error is because something is null when it shouldn't? But the only thing that is required is the id, and it should be generated automatically... I don't know what to do
I have a problem since 2 days! I try to upload file with vichuploaderBundle on a symfony 3.4 project.
I've already done this many times. But this time...It doesn't work and i don't understand why. On my local version, it work fine but on my production server it doesn't work.
Here is the error message:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'image_name' cannot be null
The file entity is persisted (with an id and a created date but the image name is empty???)it's like the vichuploader mapping doesn't work???
I have an Entity (NoteFrais) and each NoteFrais has a one relation with an another Entity (JustificatifDefraiement).
here is my JustificatifDefraiement entity:
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* JustificatifDefraiement
*
* #ORM\Table(name="justificatif_defraiement")
* #ORM\Entity(repositoryClass="MKG\MystiBundle\Repository \JustificatifDefraiementRepository")
* #vich\Uploadable
*/
class JustificatifDefraiement
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="justificatif", fileNameProperty="imageName")
*
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $imageName;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
private $updatedAt;
/**
* Constructor
*/
public function __construct()
{
$this->updatedAt = new \DateTime();
}
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|UploadedFile $justificatifDefraiement
* #return JustificatifDefraiement
*/
public function setImageFile(File $justificatifDefraiement = null)
{
$this->imageFile = $justificatifDefraiement;
if ($justificatifDefraiement) {
$this->updatedAt = new \DateTime();
}
return $this;
}
/**
* #return File|null
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
*
* #param $imageName
*
* #return $this
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
return $this;
}
/**
* #return string|null
*/
public function getImageName()
{
return $this->imageName;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
*
* #return JustificatifDefraiement
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
}
My form:
class JustificatifDefraiementType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('imageFile', FileType::class, array(
//'data_class' => null,
'label' => false,
'required' => true,
'attr' => array(
'class' => 'NoteFraisBootstrapFileInput',
'type' => 'file',
'placeholder' => 'Selectionner un justificatif (jpeg, png, jpg, pdf)',
'data-preview-file-type' => 'text',
'data-allowed-file-extensions' => '["jpeg", "png", "jpg", "pdf"]',
)
));
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MKG\MystiBundle\Entity\JustificatifDefraiement'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'mkg_mystibundle_justificatifDefraiement';
}
}
The configuration:
parameters:
locale: fr
app.path.logos: /uploads/logos
app.path.imports: /uploads/imports
app.path.justificatifs: /uploads/justificatifs
I have this relation with another entity:
class NoteFrais
{
//.......//
/**
* #ORM\OneToOne(targetEntity="MKG\MystiBundle\Entity\JustificatifDefraiement", cascade={"persist"})
* #ORM\JoinColumn(name="justificatif_defraiement_id", referencedColumnName="id", onDelete="CASCADE", nullable=true)
*/
private $justificatifDefraiement;
//.......//
}
And the noteFraisType:
class NoteFraisType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
//.......//
->add('justificatifDefraiement', JustificatifDefraiementType::class, array(
'required' => false));
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MKG\MystiBundle\Entity\NoteFrais'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'mkg_mystibundle_notefrais';
}
}
Please help me!!
When you use VichUploader then you must use VichFileType inside your FormType
Then your buildForm ...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('imageFile', VichFileType::class, array(
//Options ...
));
}
Why does database records prohibited to show all records when I use drop down field in Symfony 3.
I have form which has EntityType:class, I use this form to display the records from my db into drop down html entity.
The problem is when I set expanded and multiple to false just to set the field in drop down. Not all records are showing. But, if I activated those two parameters in true, complete records are showing.
Here's my code in form.
->add('currency', EntityType::class, [
'class' => BranchCurrency::class,
'choice_value' => 'id',
'choice_label' => function($currency){
return $currency->getName() . ' (' . $currency->getCode() .') - '.$currency->getRate().'';
},
'placeholder' => 'Choose currency',
'query_builder' => function (BranchCurrencyRepository $er) {
return $er->findAllActiveBuyingCurrencies();
},
'multiple' => false, <--- If I set this parameter to false, not all records are showing.
'expanded' => false, <--- If I set this parameter to false, not all records are showing.
])
UPDATE:
In case you need to see the Entity class and Repository class.
/**
* #ORM\Entity
* #ORM\Table(name="branch_currency")
* #UniqueEntity(
* fields={"branch", "currency"},
* message="This currency is already using on this branch.",
* errorPath="branch"
* )
* #ORM\Entity(repositoryClass="MontealBundle\Repository\BranchCurrencyRepository")
* #ORM\HasLifecycleCallbacks()
*/
class BranchCurrency
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Branch", inversedBy="branchCurrency")
* #ORM\JoinColumn(nullable=false)
*/
private $branch;
/**
* #ORM\ManyToOne(targetEntity="Currency", inversedBy="assignedCurrencies")
* #ORM\JoinColumn(nullable=false)
*/
private $currency;
/**
* #ORM\Column(type="decimal", precision=10, scale=4)
* #Assert\NotBlank()
*/
private $rate;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $type;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $code;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $name;
/**
* #ORM\Column(type="datetime")
*/
private $createdAt;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
private $updatedAt;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #return mixed
*/
public function getBranch()
{
return $this->branch;
}
/**
* #param mixed $branch
*/
public function setBranch($branch)
{
$this->branch = $branch;
}
/**
* #return mixed
*/
public function getCurrency()
{
return $this->currency;
}
/**
* #param mixed $currency
*/
public function setCurrency($currency)
{
$this->currency = $currency;
}
/**
* #return mixed
*/
public function getCode()
{
return $this->code;
}
/**
* #param mixed $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* #return mixed
*/
public function getRate()
{
return $this->rate;
}
/**
* #param mixed $rate
*/
public function setRate($rate)
{
$this->rate = $rate;
}
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* #return mixed
*/
public function getType()
{
return $this->type;
}
/**
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* #param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* #param mixed $type
*/
public function setType($type)
{
$this->type = $type;
}
/**
* #ORM\PrePersist
*/
public function setCreatedAt()
{
$this->createdAt = new \DateTime();
}
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* #ORM\PreUpdate()
*/
public function setUpdatedAt()
{
$this->updatedAt = new \DateTime();
}
public function __toString() {
return $this->name;
}
}
Repository
class BranchCurrencyRepository extends EntityRepository
{
public function findAllActiveBuyingCurrencies() {
return $this->createQueryBuilder('bc')
->where('bc.type = :type')
->setParameter('type', 1)
->orderBy('bc.currency', 'ASC');
// $queryBuilder = $this->createQueryBuilder('bc')
// ->orWhere('bc.type =:type')
// ->setParameter('type', 2)
// ->orderBy('bc.currency', 'asc')
// ->setMaxResults(10);
}
}
I have this Entity defined:
namespace CategoryBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* #ORM\Entity
* #ORM\Table(name="category")
*/
class Category {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
*/
protected $id;
/**
*
* #ORM\Column(type="string", length=255, nullable=false)
*/
protected $name;
/**
*
* #ORM\Column(type="integer", nullable=true)
*/
protected $parent;
/**
*
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $description;
/**
*
* #ORM\Column(type="integer")
*/
protected $age_limit;
/**
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="created", type="datetime")
*/
protected $created;
/**
* #Gedmo\Timestampable(on="update")
* #ORM\Column(name="modified", type="datetime")
*/
protected $modified;
public function getId() {
return $this->id;
}
public function setParent(Category $parent = null) {
$this->parent = $parent;
}
public function getParent() {
return $this->parent;
}
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function setDescription($description) {
$this->description = $description;
}
public function getDescription() {
return $this->description;
}
public function setAgeLimit($age_limit) {
$this->age_limit = $age_limit;
}
public function getAgeLimit() {
return $this->age_limit;
}
public function setCreated($created) {
$this->created = $created;
}
public function getCreated() {
return $this->created;
}
public function setModified($modified) {
$this->modified = $modified;
}
public function getModified() {
return $this->modified;
}
}
Then I have this method in my controller for handle form submission:
/**
* Handle category creation
*
* #Route("/category/create", name="category_create")
* #Method("POST")
* #Template("CategoryBundle:Default:new.html.twig")
*/
public function createAction(Request $request) {
$entity = new Category();
$form = $this->createForm(new CategoryType(), $entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('category_list'));
}
return $this->render('CategoryBundle:Default:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
And finally this is my CategoryType.php:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('parent', 'entity', array('class' => 'CategoryBundle:Category', 'property' => 'name', 'required' => false))
->add('name')
->add('description')
->add('age_limit');
}
When I try to save data I get this error:
An exception occurred while executing 'INSERT INTO category (name,
parent, description, age_limit, created, modified) VALUES (?, ?, ?, ?,
?, ?)' with params ["Cat2", {}, null, 2, "2013-08-06 09:58:03",
"2013-08-06 09:58:03"]:
Catchable Fatal Error: Object of class CategoryBundle\Entity\Category
could not be converted to string in
/var/www/html/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php
line 138
What I'm doing wrong? How do I access to the property in my method so I can save the value?
UPDATE
Based on suggestions made by #sybio, I rewrite my Entity so now I have this:
/**
* #ManyToOne(targetEntity="Category")
* #JoinColumn(name="parent", referencedColumnName="id")
*/
protected $parent;
Is that right?
Here what I think :
You are trying to save a Category object as parent, but in the following code :
/**
*
* #ORM\Column(type="integer", nullable=true)
*/
protected $parent;
You said that a parent is an integer, so the framework try to save the parent category as an integer but to feet it it's probably converting the object as a string before, and so it crashes...
I'm not totally sure, but you should rethink your property "$parent".
It should be a self referencing relation.
Example :
/**
* #OneToMany(targetEntity="Category", mappedBy="parent")
*/
private $children;
/**
* #ManyToOne(targetEntity="Category", inversedBy="children")
* #JoinColumn(name="parent_id", referencedColumnName="id")
*/
protected $parent;
public function __construct() {
$this->children = new \Doctrine\Common\Collections\ArrayCollection();
}
Don't forget to refactor your getter / setter :
/**
* Set parent
*
* #param \CategoryBundle\Entity\Category $parent
*/
public function setParent(\CategoryBundle\Entity\Category $parent = null)
{
$this->parent = $parent;
}
/**
* Get parent
*
* #return \CategoryBundle\Entity\Category
*/
public function getParent()
{
return $this->parent;
}
Hope this is the solution !