I am trying to set some translatable contents in Symfony2 with Gedmo Translatable but seems I am doing something wrong or missing something.
I included the line in the composer.json file:
"gedmo/doctrine-extensions": "2.3.*#dev"
And also, I added this lines in the config.yml file:
stof_doctrine_extensions:
orm:
alopatria:
timestampable: true
sluggable: true
translatable: true
The entity class is set like this:
<?php
namespace ...;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Translatable\Translatable;
/**
* ...\Entity
*
* #ORM\Table(name="content")
* #ORM\HasLifecycleCallbacks
* #ORM\Entity(repositoryClass="...\Entity\ContentRepository")
*/
class Content implements Translatable
{
/**
*
* #ORM\Column(name="id", type="bigint", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #Gedmo\Translatable
* #ORM\Column(name="title", type="string", length=32, nullable=false)
*/
protected $title;
/**
* #Gedmo\Translatable
* #ORM\Column(name="text", type="text", nullable=false)
*/
protected $text;
/**
* #var datetime $created
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(type="datetime")
*/
private $created;
/**
* #var datetime $updated
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(type="datetime")
*/
private $updated;
/**
* #var datetime $contentChanged
*
* #ORM\Column(name="content_changed", type="datetime", nullable=true)
* #Gedmo\Timestampable(on="change", field={"title", "text"})
*/
private $contentChanged;
/**
* #Gedmo\Slug(fields={"title"})
* #ORM\Column(length=128, unique=true)
*/
private $slug;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
* #return Content
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set text
*
* #param string $text
* #return Content
*/
public function setText($text)
{
$this->text = $text;
return $this;
}
/**
* Get text
*
* #return string
*/
public function getText()
{
return $this->text;
}
/**
* Set created
*
* #param \DateTime $created
* #return Content
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* #param \DateTime $updated
* #return Content
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* #return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Set contentChanged
*
* #param \DateTime $contentChanged
* #return Content
*/
public function setContentChanged($contentChanged)
{
$this->contentChanged = $contentChanged;
return $this;
}
/**
* Get contentChanged
*
* #return \DateTime
*/
public function getContentChanged()
{
return $this->contentChanged;
}
/**
* Set slug
*
* #param string $slug
* #return Content
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
}
When I try to create a translatable content in my controller:
$content = new Content();
$content->setTitle('Content example');
$content->setText('Content example...');
$em = $this->getDoctrine()->getEntityManager();
$em->persist($content);
$em->flush();
$content->setTranslatableLocale('fr'); // change locale
$em->persist($content);
$em->flush();
This is the error:
The class 'Gedmo\Translatable\Entity\Translation' was not found in the chain configured namespaces ...\Entity, FOS\UserBundle\Model
Any help? Thanks!!!
You need to configure the translatable Entity to use as well. In config.yml:
orm:
auto_generate_proxy_classes: %kernel.debug%
mappings:
translatable:
type: annotation
is_bundle: false
prefix: Gedmo\Translatable\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
alias: GedmoTranslatable
Related
In my Symfony 3.4 project (vich/uploader-bundle: "^1.4"), I need to upload 3 kinds of files and for two of them it's work, but for the third even if i use the same process it doesn't work...? When the form is submitted, i get this exception:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'document_name' cannot be null
when i dumped, i can see that my Setter "vichuploader document name" not work and can't persisted.
This is the context:
*Everythings is ok on my local version...Files are uploaded but on my production version it's doesn't work.
*I have one Entity (NoteFrais) with OneToOne relation with another Entity (Justificatif).
*The Justificatif entity has the #vich\uploadable annotation
I followed the documentation, read many tuto, ask question on stackverflow, cleared cache and updated doctrine schema many times, tried many things...
******config.yml********
parameters:
locale: fr
app.path.logos: /uploads/logos
app.path.imports: /uploads/imports
app.path.documents: /uploads/documents
vich_uploader:
db_driver: orm
mappings:
logo:
uri_prefix: '%app.path.logos%'
upload_destination: '%kernel.root_dir%/../web%app.path.logos%' //========IT'S WORK FINE FOR THIS ONE==========//
namer: vich_uploader.namer_uniqid
inject_on_load: false
delete_on_update: true
delete_on_remove: true
import:
uri_prefix: '%app.path.imports%'
upload_destination: '%kernel.root_dir%/../web%app.path.imports%' //=========IT'S WORK FINE THIS ONE=========//
namer: vich_uploader.namer_uniqid
# inject_on_load: true important!!
inject_on_load: false
delete_on_update: true
delete_on_remove: true
document:
uri_prefix: '%app.path.documents%'
upload_destination: '%kernel.root_dir%/../web%app.path.documents%'
namer: vich_uploader.namer_uniqid
# inject_on_load: true important!!
inject_on_load: false
delete_on_update: true
delete_on_remove: true
******JustificatifType*******
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('justificatifFile', FileType::class, array( //========= I TRIED WITH FILETYPE OR VICHFILETYPE =======//
//'data_class' => null, //======== NOTE:USALLY I USE TO FILETYPE AND IT'S WORK FINE ==============//
'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"]',
)
));
}
******NoteFraisType**********
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
//=======OTHERS FIELDS===========//
->add('justificatif', JustificatifType::class, array(
'required' => false));
}
*****Justificatif.php (Entity)*****
<?php
namespace MKG\MystiBundle\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;
/**
* Justificatif
*
* #ORM\Table(name="justificatif")
* #ORM\Entity(repositoryClass="MKG\MystiBundle\Repository\JustificatifRepository")
* #vich\Uploadable
*/
class Justificatif
{
/**
* #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="document", fileNameProperty="documentName")
*
* #var File
*/
private $justificatifFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $documentName;
/**
* #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 $justificatif
*/
public function setJustificatifFile(File $justificatif = null)
{
$this->justificatifFile = $justificatif;
if ($justificatif) {
$this->updatedAt = new \DateTime('now');
}
}
/**
* #return File|null
*/
public function getJustificatifFile()
{
return $this->justificatifFile;
}
/**
*
* #param $documentName
*
* #return $this
*/
public function setDocumentName($documentName)
{
$this->documentName = $documentName;
return $this;
}
/**
* #return string|null
*/
public function getDocumentName()
{
return $this->documentName;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
*
* #return Justificatif
*/
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;
}
}
*******NoteFrais (Entity)*********
<?php
namespace MKG\MystiBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* NoteFrais
*
* #ORM\Table(name="note_frais")
* #ORM\Entity(repositoryClass="MKG\MystiBundle\Repository\NoteFraisRepository")
*/
class NoteFrais
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="MKG\MystiBundle\Entity\Mission", cascade={"persist"})
* #ORM\JoinColumn(name="mission_id", referencedColumnName="id", onDelete="CASCADE", nullable=true)
*/
private $mission;
/**
* #ORM\ManyToOne(targetEntity="MKG\MystiBundle\Entity\CodeComptable", cascade={"persist"})
* #ORM\JoinColumn(name="compte_comptable_id", referencedColumnName="id", onDelete="SET NULL", nullable=true)
*/
private $compteComptable;
/**
* #var string
*
* #ORM\Column(name="montant_defraiement_max", type="string", length=255, nullable=false)
*/
private $montantDefraiementMax;
/**
* #var string
*
* #ORM\Column(name="refacturation_client", type="string", length=255, nullable=true)
*/
private $refacturationClient;
/**
* #var string
*
* #ORM\Column(name="total_defraiement", type="string", length=255, nullable=true)
*/
private $totalDefraiement;
/**
* #var string
*
* #ORM\Column(name="total_refacturation", type="string", length=255, nullable=true)
*/
private $totalRefacturation;
/**
* #var string
*
* #ORM\Column(name="compte_avances_et_acomptes", type="string", length=255, nullable=true)
*/
private $compteAvancesEtAcomptes;
/**
* #var string
*
* #ORM\Column(name="admin_current_user", type="string", length=255, nullable=true)
*/
private $currentUser;
/**
* #var string
*
* #ORM\Column(name="code_affaire", type="string", length=255, nullable=true)
*/
private $codeAffaire;
/**
* #var string
*
* #ORM\Column(name="etat", type="string", length=255, nullable=true)
*/
private $etat;
/**
* #ORM\OneToOne(targetEntity="Justificatif", cascade={"persist"})
* #ORM\JoinColumn(name="justificatif_id", referencedColumnName="id", onDelete="CASCADE", nullable=true)
*/
private $justificatif;
/**
* #var \DateTime
*
* #ORM\Column(name="dateCreation", type="datetime")
*/
private $dateCreation;
public function __construct() {
$this->dateCreation = new \DateTime;
$this->etat = "0";
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set montantDefraiementMax
*
* #param string $montantDefraiementMax
*
* #return NoteFrais
*/
public function setMontantDefraiementMax($montantDefraiementMax)
{
$this->montantDefraiementMax = $montantDefraiementMax;
return $this;
}
/**
* Get montantDefraiementMax
*
* #return string
*/
public function getMontantDefraiementMax()
{
return $this->montantDefraiementMax;
}
/**
* Set refacturationClient
*
* #param string $refacturationClient
*
* #return NoteFrais
*/
public function setRefacturationClient($refacturationClient)
{
$this->refacturationClient = $refacturationClient;
return $this;
}
/**
* Get refacturationClient
*
* #return string
*/
public function getRefacturationClient()
{
return $this->refacturationClient;
}
/**
* Set compteAvancesEtAcomptes
*
* #param string $compteAvancesEtAcomptes
*
* #return NoteFrais
*/
public function setCompteAvancesEtAcomptes($compteAvancesEtAcomptes)
{
$this->compteAvancesEtAcomptes = $compteAvancesEtAcomptes;
return $this;
}
/**
* Get compteAvancesEtAcomptes
*
* #return string
*/
public function getCompteAvancesEtAcomptes()
{
return $this->compteAvancesEtAcomptes;
}
/**
* Set currentUser
*
* #param string $currentUser
*
* #return NoteFrais
*/
public function setCurrentUser($currentUser)
{
$this->currentUser = $currentUser;
return $this;
}
/**
* Get currentUser
*
* #return string
*/
public function getCurrentUser()
{
return $this->currentUser;
}
/**
* Set codeAffaire
*
* #param string $codeAffaire
*
* #return NoteFrais
*/
public function setCodeAffaire($codeAffaire)
{
$this->codeAffaire = $codeAffaire;
return $this;
}
/**
* Get codeAffaire
*
* #return string
*/
public function getCodeAffaire()
{
return $this->codeAffaire;
}
/**
* Set etat
*
* #param string $etat
*
* #return NoteFrais
*/
public function setEtat($etat)
{
$this->etat = $etat;
return $this;
}
/**
* Get etat
*
* #return string
*/
public function getEtat()
{
return $this->etat;
}
/**
* Set dateCreation
*
* #param \DateTime $dateCreation
*
* #return NoteFrais
*/
public function setDateCreation($dateCreation)
{
$this->dateCreation = $dateCreation;
return $this;
}
/**
* Get dateCreation
*
* #return \DateTime
*/
public function getDateCreation()
{
return $this->dateCreation;
}
/**
* Set mission
*
* #param \MKG\MystiBundle\Entity\Mission $mission
*
* #return NoteFrais
*/
public function setMission(\MKG\MystiBundle\Entity\Mission $mission = null)
{
$this->mission = $mission;
return $this;
}
/**
* Get mission
*
* #return \MKG\MystiBundle\Entity\Mission
*/
public function getMission()
{
return $this->mission;
}
/**
* Set compteComptable
*
* #param \MKG\MystiBundle\Entity\CodeComptable $compteComptable
*
* #return NoteFrais
*/
public function setCompteComptable(\MKG\MystiBundle\Entity\CodeComptable $compteComptable = null)
{
$this->compteComptable = $compteComptable;
return $this;
}
/**
* Get compteComptable
*
* #return \MKG\MystiBundle\Entity\CodeComptable
*/
public function getCompteComptable()
{
return $this->compteComptable;
}
/**
* Set justificatif
*
* #param \MKG\MystiBundle\Entity\Justificatif $justificatif
*
* #return NoteFrais
*/
public function setJustificatif(\MKG\MystiBundle\Entity\Justificatif $justificatif = null)
{
$this->justificatif = $justificatif;
return $this;
}
/**
* #return File
*/
public function getJustificatif()
{
return $this->justificatif;
}
/**
* Set totalDefraiement
*
* #param string $totalDefraiement
*
* #return NoteFrais
*/
public function setTotalDefraiement($totalDefraiement)
{
$this->totalDefraiement = $totalDefraiement;
return $this;
}
/**
* Get totalDefraiement
*
* #return string
*/
public function getTotalDefraiement()
{
return $this->totalDefraiement;
}
/**
* Set totalRefacturation
*
* #param string $totalRefacturation
*
* #return NoteFrais
*/
public function setTotalRefacturation($totalRefacturation)
{
$this->totalRefacturation = $totalRefacturation;
return $this;
}
/**
* Get totalRefacturation
*
* #return string
*/
public function getTotalRefacturation()
{
return $this->totalRefacturation;
}
}
********* newAction in NoteFraisController *********
/**
* Creates a new noteFrais entity.
*
*/
public function newAction(Request $request)
{
// === RECUPERE LA MISSION
$em = $this->getDoctrine()->getManager();
$mission = $em->getRepository('MKGMystiBundle:Mission')->findOneBy(array('id' => $request->get('idMission')));
$lignesNoteFrais = $em->getRepository('MKGMystiBundle:NoteFrais')->findBy(array('mission' => $mission->getId()));
$noteFrais = new Notefrais();
$form = $this->createForm('MKG\MystiBundle\Form\NoteFraisType', $noteFrais);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//$noteFrais->setMission($mission);
$em = $this->getDoctrine()->getManager();
$em->persist($noteFrais);
//dump($noteFrais);die();
$em->flush();
$this->addFlash('notice', 'Une ligne a été ajouté à la note de frais!');
return $this->redirect($request->getUri());
}
return $this->render('#MKGMysti/Notefrais/new.html.twig', array(
'lignesNoteFrais' => $lignesNoteFrais,
'mission' => $mission,
'noteFrais' => $noteFrais,
'form' => $form->createView(),
));
}
Thank you very much your time!!!!
I'm using Sylius 1.0.0-dev and created model called Trainee
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use SyliusExtensionBundle\Entity\Product;
use SyliusExtensionBundle\Entity\Order;
use Sylius\Component\Resource\Model\ResourceInterface;
/**
* Trainee
*
* #ORM\Table(name="smartbyte_trainee")
* #ORM\Entity()
*/
class Trainee implements ResourceInterface
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="firstName", type="string", length=255)
*/
private $firstName;
/**
* #var string
*
* #ORM\Column(name="secondName", type="string", length=255)
*/
private $secondName;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255)
*/
private $email;
/**
* #var string
*
* #ORM\Column(name="phone", type="string", length=255)
*/
private $phone;
/**
* #var boolean
*
* #ORM\Column(name="is_resignated", type="boolean")
*/
private $isResignated = false;
/**
* #var boolean
*
* #ORM\Column(name="is_present", type="boolean")
*/
private $isPresent = false;
/**
* #var Product
*
* #ORM\ManyToOne(targetEntity="SyliusExtensionBundle\Entity\Product")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $product;
/**
* #var Order
*
* #ORM\ManyToOne(targetEntity="SyliusExtensionBundle\Entity\Order", inversedBy="trainees")
* #ORM\JoinColumn(name="order_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $order;
public function __toString() {
return $this->firstName.' '.$this->secondName;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set firstName
*
* #param string $firstName
* #return Trainee
*/
public function setFirstName($firstName)
{
$this->firstName = $firstName;
return $this;
}
/**
* Get firstName
*
* #return string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* Set secondName
*
* #param string $secondName
* #return Trainee
*/
public function setSecondName($secondName)
{
$this->secondName = $secondName;
return $this;
}
/**
* Get secondName
*
* #return string
*/
public function getSecondName()
{
return $this->secondName;
}
/**
* Set email
*
* #param string $email
* #return Trainee
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set phone
*
* #param string $phone
* #return Trainee
*/
public function setPhone($phone)
{
$this->phone = $phone;
return $this;
}
/**
* Get phone
*
* #return string
*/
public function getPhone()
{
return $this->phone;
}
/**
* #var string
*/
private $condition;
/**
* Set isResignated
*
* #param boolean $isResignated
* #return Trainee
*/
public function setIsResignated($isResignated)
{
$this->isResignated = $isResignated;
return $this;
}
/**
* Get isResignated
*
* #return boolean
*/
public function getIsResignated()
{
return $this->isResignated;
}
/**
* Set condition
*
* #param string $condition
* #return Trainee
*/
public function setCondition($condition)
{
$this->condition = $condition;
return $this;
}
/**
* Get condition
*
* #return string
*/
public function getCondition()
{
return $this->condition;
}
/**
* Set product
*
* #param Product $product
* #return Trainee
*/
public function setProduct(Product $product = null)
{
$this->product = $product;
return $this;
}
/**
* Get product
*
* #return Product
*/
public function getProduct()
{
return $this->product;
}
/**
* Set order
*
* #param Order $order
* #return Trainee
*/
public function setOrder(Order $order = null)
{
$this->order = $order;
return $this;
}
/**
* Get order
*
* #return Order
*/
public function getOrder()
{
return $this->order;
}
/**
* Set isPresent
*
* #param boolean $isPresent
* #return Trainee
*/
public function setIsPresent($isPresent)
{
$this->isPresent = $isPresent;
return $this;
}
/**
* Get isPresent
*
* #return boolean
*/
public function getIsPresent()
{
return $this->isPresent;
}
}
Then I configure it with config.yml:
sylius_resource:
resources:
app.trainee:
classes:
model: AppBundle\Entity\Trainee
repository: AppBundle\Repository\TraineeRepository
and routing.yml:
app_trainee:
resource: |
alias: app.trainee
section: admin
type: sylius.resource
prefix: /admin
according to the docs. Unfortunately instead of crud template I get :
Unable to find template "/index.html.twig" (looked into: /home/krzysztof/Dokumenty/praca/smartbyte/eventmanager2/vendor/symfony/symfony/src/Symfony/Bridge/Twig/Resources/views/Form, /home/krzysztof/Dokumenty/praca/smartbyte/eventmanager2/vendor/knplabs/knp-menu/src/Knp/Menu/Resources/views).
I know there is SyliusAdminBundle with crud templates for resources but by the last version I was using (0.18) sylius evolved much it's completely different from that.
You should compare your routing.yml code to other resources in the AdminBundle routing files.
This is the product declaration in the routing/product.yml file
sylius_admin_product:
resource: |
alias: sylius.product
section: admin
templates: SyliusAdminBundle:Crud
except: ['show']
redirect: update
grid: sylius_admin_product
permission: true
vars:
all:
subheader: sylius.ui.manage_your_product_catalog
templates:
form: SyliusAdminBundle:Product:_form.html.twig
index:
icon: cube
type: sylius.resource
You should probably put the templates: declaration in
I tried to install and use the extension Tree Gedmo with Category entity but when I add a new category I have this error:
Root cannot be changed manually, change parent instead
500 Internal Server Error - UnexpectedValueException.
I have followed this link and I did everything as indicated: https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/symfony2.md
I have created app/config/doctrine_extensions.yml and src/Project/StoreBundle/Listener/DoctrineExtensionListener.php also
app/conifg.yml
# Doctrine Configuration
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
# if using pdo_sqlite as your database driver, add the path in parameters.yml
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
# path: "%database_path%"
orm:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
mappings:
translatable:
type: annotation
alias: Gedmo
prefix: Gedmo\Translatable\Entity
# make sure vendor library location is correct
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
loggable:
type: annotation
alias: Gedmo
prefix: Gedmo\Loggable\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Loggable/Entity"
tree:
type: annotation
alias: Gedmo
prefix: Gedmo\Tree\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity"
//..........
# Stof\DoctrineExtensionBundle configuration
stof_doctrine_extensions:
orm:
default:
sluggable: true
tree: true
Entity/Category.php
<?php
namespace Project\StoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Category
* #Gedmo\Tree(type="nested")
* #ORM\Table()
* #ORM\Entity(repositoryClass="Project\StoreBundle\Entity\CategoryRepository")
* #ORM\HasLifeCycleCallbacks()
*/
class Category
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*
*#Assert\NotBlank(message="Please enter the name of category.")
*/
private $name;
/**
* #Gedmo\slug(fields={"name"}, unique_base="uniqueBase")
* #ORM\Column(name="slug",length=255, unique=false)
*/
private $slug ;
/**
* #ORM\Column(name="uniqueBase", type="integer")
*/
private $uniqueBase ;
/**
* #ORM\Column(name="description", type="text", nullable=true)
*/
private $description;
/**
* #ORM\Column(name="metaDescription", type="string", length=255, nullable=true)
*
* #Assert\Length(
* max=255,
* maxMessage="message."
* )
*/
private $metaDescription;
/**
* #ORM\Column(name="metaKeywords", type="string", length=255, nullable=true)
*
* #Assert\Length(
* max=255,
* maxMessage="message."
* )
*/
private $metaKeywords;
/**
* #ORM\Column(name="enabled", type="boolean", nullable=false)
*/
private $enabled;
/**
* #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="Category", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="Category", mappedBy="parent")
* #ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
/**
* #ORM\ManyToOne(targetEntity="Project\StoreBundle\Entity\Store", inversedBy="categories", cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
*/
private $store ;
/**
* Constructor
*/
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Category
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set slug
*
* #param string $slug
* #return Category
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Set uniqueBase
*
* #param integer $uniqueBase
* #return Category
*/
public function setUniqueBase($uniqueBase)
{
$this->uniqueBase = $uniqueBase;
return $this;
}
/**
* Get uniqueBase
*
* #return integer
*/
public function getUniqueBase()
{
return $this->uniqueBase;
}
/**
* Set description
*
* #param string $description
* #return Category
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set metaDescription
*
* #param string $metaDescription
* #return Category
*/
public function setMetaDescription($metaDescription)
{
$this->metaDescription = $metaDescription;
return $this;
}
/**
* Get metaDescription
*
* #return string
*/
public function getMetaDescription()
{
return $this->metaDescription;
}
/**
* Set metaKeywords
*
* #param string $metaKeywords
* #return Category
*/
public function setMetaKeywords($metaKeywords)
{
$this->metaKeywords = $metaKeywords;
return $this;
}
/**
* Get metaKeywords
*
* #return string
*/
public function getMetaKeywords()
{
return $this->metaKeywords;
}
/**
* Set enabled
*
* #param boolean $enabled
* #return Category
*/
public function setEnabled($enabled)
{
$this->enabled = $enabled;
return $this;
}
/**
* Get enabled
*
* #return boolean
*/
public function getEnabled()
{
return $this->enabled;
}
/**
* Set parent
*
* #param \Project\StoreBundle\Entity\Category $parent
* #return Category
*/
public function setParent(\Project\StoreBundle\Entity\Category $parent = null)
{
$this->parent = $parent;
return $this;
}
/**
* Get parent
*
* #return \Project\StoreBundle\Entity\Category
*/
public function getParent()
{
return $this->parent;
}
/**
* Set lft
*
* #param integer $lft
* #return Category
*/
public function setLft($lft)
{
$this->lft = $lft;
return $this;
}
/**
* Get lft
*
* #return integer
*/
public function getLft()
{
return $this->lft;
}
/**
* Set lvl
*
* #param integer $lvl
* #return Category
*/
public function setLvl($lvl)
{
$this->lvl = $lvl;
return $this;
}
/**
* Get lvl
*
* #return integer
*/
public function getLvl()
{
return $this->lvl;
}
/**
* Set rgt
*
* #param integer $rgt
* #return Category
*/
public function setRgt($rgt)
{
$this->rgt = $rgt;
return $this;
}
/**
* Get rgt
*
* #return integer
*/
public function getRgt()
{
return $this->rgt;
}
/**
* Set root
*
* #param integer $root
* #return Category
*/
public function setRoot($root)
{
$this->root = $root;
return $this;
}
/**
* Get root
*
* #return integer
*/
public function getRoot()
{
return $this->root;
}
/**
* Add children
*
* #param \Project\StoreBundle\Entity\Category $children
* #return Category
*/
public function addChild(\Project\StoreBundle\Entity\Category $children)
{
$this->children[] = $children;
return $this;
}
/**
* Remove children
*
* #param \Project\StoreBundle\Entity\Category $children
*/
public function removeChild(\Project\StoreBundle\Entity\Category $children)
{
$this->children->removeElement($children);
}
/**
* Get children
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getChildren()
{
return $this->children;
}
/**
* Set store
*
* #param \Project\StoreBundle\Entity\Store $store
* #return Category
*/
public function setStore(\Project\StoreBundle\Entity\Store $store = null)
{
$this->store = $store;
return $this;
}
/**
* Get store
*
* #return \Project\StoreBundle\Entity\Store
*/
public function getStore()
{
return $this->store;
}
}
Upgrade doctrine/orm at least to version 2.4.2 (see https://github.com/Atlantic18/DoctrineExtensions/issues/1026)
I develop store using SyliusSandbox bundle.
Sylius uses xml files to store ORM schema for entities.
I've copied its xml definitions to my Bundle and use it there.
But for my own entities, I'd like to use annotations. So, basically I need to mix two types of definitions in one bundle.
If I try to persist an entity which is using annotations, I get an error that xml file for this entity was not found:
No mapping file found named
'ShopBundle\Resources\config\doctrine/ProductLocalized.orm.xml' for
class '\ShopBundle\Entity\ProductLocalized'.
My entity looks like this:
<?php
namespace Pixeljets\ShopBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Pixeljets\ShopBundle\Entity\ProductLocalized
*
* #ORM\Table(name="product_localized")
* #ORM\Entity
*/
class ProductLocalized
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Product", inversedBy="localized")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
protected $product;
/**
* #var integer $product_id
*
* #ORM\Column(name="product_id", type="integer")
*/
private $product_id;
/**
* #var string $title
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string $url
*
* #ORM\Column(name="url", type="string", length=255)
*/
private $url;
/**
* #var string $keywords
*
* #ORM\Column(name="keywords", type="string", length=255, nullable=true)
*/
private $keywords;
/**
* #var string $description
*
* #ORM\Column(name="description", type="string", length=255, nullable=true)
*/
private $description;
/**
* #var string $body
*
* #ORM\Column(name="body", type="text", nullable=true)
*/
private $body;
/**
* #var boolean $published
*
* #ORM\Column(name="published", type="boolean")
*/
private $published;
/**
* #var string $lang
*
* #ORM\Column(name="lang", type="string", length=2)
*/
private $lang;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set product_id
*
* #param integer $productId
* #return ProductLocalized
*/
public function setProductId($productId)
{
$this->product_id = $productId;
return $this;
}
/**
* Get product_id
*
* #return integer
*/
public function getProductId()
{
return $this->product_id;
}
/**
* Set title
*
* #param string $title
* #return ProductLocalized
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set url
*
* #param string $url
* #return ProductLocalized
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* Get url
*
* #return string
*/
public function getUrl()
{
return $this->url;
}
/**
* Set keywords
*
* #param string $keywords
* #return ProductLocalized
*/
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 ProductLocalized
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set body
*
* #param string $body
* #return ProductLocalized
*/
public function setBody($body)
{
$this->body = $body;
return $this;
}
/**
* Get body
*
* #return string
*/
public function getBody()
{
return $this->body;
}
/**
* Set published
*
* #param boolean $published
* #return ProductLocalized
*/
public function setPublished($published)
{
$this->published = $published;
return $this;
}
/**
* Get published
*
* #return boolean
*/
public function getPublished()
{
return $this->published;
}
/**
* Set lang
*
* #param string $lang
* #return ProductLocalized
*/
public function setLang($lang)
{
$this->lang = $lang;
return $this;
}
/**
* Get lang
*
* #return string
*/
public function getLang()
{
return $this->lang;
}
/**
* Set product
*
* #param Pixeljets\ShopBundle\Entity\Product $product
* #return ProductLocalized
*/
public function setProduct(\Pixeljets\ShopBundle\Entity\Product $product = null)
{
$this->product = $product;
return $this;
}
/**
* Get product
*
* #return Pixeljets\ShopBundle\Entity\Product
*/
public function getProduct()
{
return $this->product;
}
}
?>
How can I 'tell' symfony to use annotation approach for schema?
You cannot mix metadata formats inside of a bundle:
From: http://symfony.com/doc/current/book/doctrine.html
A bundle can accept only one metadata definition format. For example, it's not
possible to mix YAML metadata definitions with annotated PHP entity class definitions.
You will need to use two bundles or stick with one format.
You should think about using Translatable behavior from DoctrineExtensions to make your products support i18n. Should be much easier than creating another entity for that.
I'm getting this error on my production environnent: (from prod.log)
[2012-01-30 17:00:51] request.CRITICAL: Doctrine\ORM\Mapping\MappingException: Class Gitek\UdaBundle\Entity\Curso is not a valid entity or mapped super class. (uncaught exception) at /home/uda/shared/vendor/doctrine/lib/Doctrine/ORM/Mapping/MappingException.php line 142 [] []
But in my development environnent everything works fine.
And this is my Curso entity:
<?php
namespace Gitek\UdaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Gitek\UdaBundle\Entity\Curso
*
* #ORM\Table(name="Curso")
* #ORM\HasLifecycleCallbacks
* #ORM\Entity(repositoryClass="Gitek\UdaBundle\Entity\CursoRepository")
*/
class Curso
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $nombre
*
* #ORM\Column(name="nombre", type="string", length=255)
*/
private $nombre;
/**
* #var string $version
*
* #ORM\Column(name="version", type="string", length=255, nullable=true)
*/
private $version;
/**
* #var integer $orden
*
* #ORM\Column(name="orden", type="integer", nullable=true, nullable=true)
*/
private $orden;
/**
* #var integer $tiempo
*
* #ORM\Column(name="tiempo", type="integer", nullable=true, nullable=true)
*/
private $tiempo;
/**
* #ORM\OneToMany(targetEntity="Detcurso", mappedBy="curso", cascade={"remove"})
* #ORM\OrderBy({"orden" = "ASC"})
*/
private $detcursos;
/**
* #ORM\OneToMany(targetEntity="Historial", mappedBy="curso", cascade={"remove"})
*/
private $historiales;
/**
* #ORM\Column(type="datetime")
*/
protected $created;
/**
* #ORM\Column(type="datetime")
*/
protected $updated;
public function __construct()
{
$this->detcursos = new \Doctrine\Common\Collections\ArrayCollection();
$this->setCreated(new \DateTime());
$this->setUpdated(new \DateTime());
}
public function __toString()
{
return $this->getNombre();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nombre
*
* #param string $nombre
*/
public function setNombre($nombre)
{
$this->nombre = $nombre;
}
/**
* Get nombre
*
* #return string
*/
public function getNombre()
{
return $this->nombre;
}
/**
* Set version
*
* #param string $version
*/
public function setVersion($version)
{
$this->version = $version;
}
/**
* Get version
*
* #return string
*/
public function getVersion()
{
return $this->version;
}
/**
* Set orden
*
* #param integer $orden
*/
public function setOrden($orden)
{
$this->orden = $orden;
}
/**
* Get orden
*
* #return integer
*/
public function getOrden()
{
return $this->orden;
}
/**
* Set created
*
* #param datetime $created
*/
public function setCreated($created)
{
$this->created = $created;
}
/**
* Get created
*
* #return datetime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* #param datetime $updated
*/
public function setUpdated($updated)
{
$this->updated = $updated;
}
/**
* Get updated
*
* #return datetime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Add detcursos
*
* #param Gitek\UdaBundle\Entity\Detcurso $detcursos
*/
public function addDetcurso(\Gitek\UdaBundle\Entity\Detcurso $detcursos)
{
$this->detcursos[] = $detcursos;
}
/**
* Get detcursos
*
* #return Doctrine\Common\Collections\Collection
*/
public function getDetcursos()
{
return $this->detcursos;
}
/**
* Add historiales
*
* #param Gitek\UdaBundle\Entity\Historial $historiales
*/
public function addHistorial(\Gitek\UdaBundle\Entity\Historial $historiales)
{
$this->historiales[] = $historiales;
}
/**
* Get historiales
*
* #return Doctrine\Common\Collections\Collection
*/
public function getHistoriales()
{
return $this->historiales;
}
/**
* Get historial
*
* #return Doctrine\Common\Collections\Collection
*/
public function getHistorial()
{
return $this->historial;
}
/**
* Set tiempo
*
* #param integer $tiempo
*/
public function setTiempo($tiempo)
{
$this->tiempo = $tiempo;
}
/**
* Get tiempo
*
* #return integer
*/
public function getTiempo()
{
return $this->tiempo;
}
}
As I said, in app_dev works correctly.
You can have different metadata cache configurations depending on which environment you are in. For example apc can cause troubles if not correctly refreshed.
Anyway, you will have to warmup your cache in prod environment, like this:
php app/console cache:clear --env=prod
If this still doesn't work, try to change your doctrine cache configuration:
orm:
auto_generate_proxy_classes: false
default_entity_manager: default
entity_managers:
default:
metadata_cache_driver: array
query_cache_driver: array
result_cache_driver: array
This will use the array cache driver, which is refreshed once at every request.
You shouldn't use this in production, but it can help you to understand where you problem comes from.
In my case the problem was solved by changing my servers cache from eAccelerator to APC. Apparently eAccelerator strips all the comments from files which breaks your annotations.