I use doctrine entity manager in my script, select and update works always, so entity manager is initialized correctly:
$article = $entityManager->find('Models\Article', 5);
echo $article->getTitle();
or:
$article->setTitle('Updated!');
but when I try to create/save new element then the page breaks, the code is:
$item = new Article();
$item->setAuthorId(1);
$item->setTitle('Created item!');
$entityManager->persist($item);
$entityManager->flush();
It's created like on official documentation page
What I do wrong here?
Seems you can't specify the relation of the object with the Author entity:
$item->setAuthorId(1);
Probably your entity Article Have a relation with the entity Author. In this case you should have a proper setter method (simple setAuthor(Author $author) ) that assign the reference of an Author object. In this case you could use the following:
$item->setAuthor($entityManager->find('Models\Author', 1););
Or Better
$item->setAuthor($entityManager->getReference('Models\Author', 1););
You could also use a short way of reference the class object with the class keyword, as example:
$item->setAuthor($entityManager->getReference(Author::class, 1););
Hope this help
Related
I have an object $user that has a one to many relation with $establishment. I can use:
$user->getEstablishments();
The user can select a stablishment to work on. I have this method that I call in the controller:
$user->setCurrentEstablishment($establishment);
And this one that I call in the view:
$establishment = $user->getCurrentEstablishment();
I want to be able to call:
$user->setCurrentEstablishmentBy Slug($establishment_slug);
where the slug is a string, and let the user object look for the establishment.
Doctrine discourages the practice of accessing the Entity Manager inside the Entity object, but I think that using it in the controller is even worse.
I suspect that some special Doctrine annotation exists that takes care of non persistent relations like this, or some method other than serving the Entity Manager through a service should be used here. Some easy way of referencing other entities from inside the model.
¿Is there any? ¿How could I do that?
There is no Annotation in Doctrine which could convert slug into object.
What can help You is ParamConverter, with it you can automatically convert slug from query into object. But it still must be used in Controller.
Example usage:
/**
* #Route("/some-route/{slug}")
* #ParamConverter("object", class="AppBundle:Establishment", options={"id" = "slug", "repository_method" = "findEstablishmentBySlug"})
*/
public function slugAction(Establishment $object)
{
...
Docs about param converter: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
Is it possible to check if field was changed on preUpdate hook? I'm looking for something like preUpdate hasChangedField($fieldName) Doctrine functionality. Any ideas?
This question is a bit similar to this one
Your solution is just to compare the field of the old object with the new one and see where it differs.
So for example:
public function preUpdate($newObject)
{
$em = $this->getModelManager()->getEntityManager($this->getClass());
$originalObject = $em->getUnitOfWork()->getOriginalEntityData($newObject);
if ($newObject->getSomeField() !== $originalObject['fieldName']) {
// Field has been changed
}
}
For me the best approach is this in Sonata Admin:
$newField = $this->getForm()->get('field')->getData();
$oldField = $this->getForm()->get('field')->getConfig()->getData();
You shouldn't use unit of work unless there is no option. Also, if you have a not mapped field, you can't access it by entity object.
In a normal Doctrine lyfe cycle event, the best option is Doctrine preupdate event doc
I have a basic Symfony2/Doctrine2 question. I have two entities the first called "Column" that has OneToMany issues, entity "Issue". And the Issue entity has a ManyToOne relationship with the entity Column. When I create a new Issue I wish to assign a default value for the column.
If I create a hidden field in IssueType.php and assigned a default value I cannot save the submitted form because I get an error about assigning a string to setColumn and not an instance of the Column entity as defined in my Issue entity (see below).
public function setColumn(\WebConfection\ServiceDeskBundle\Entity\Column $column)
{
$this->column = $column;
return $this;
}
Can anybody please advise on the best way to accomplish this? I have read a few articles but am a tad confused and not sure which way to jump. An idiot friendly answer would be greatly appreciated.
You don't really need a hidden field for this to work. Just set the right (default) Column on the Issue you want to add within your action,
// ...
$issue = new Issue();
$issue->setColumn($yourDefaultColumn);
$form = $this->createForm('your_issue_form', $issue);
// ...
You know that in Symfony2 a new entity can be defined as in the following example:
use Acme\StoreBundle\Entity\Product;
public function defaultController() {
$product = new Product();
$product->setName('Pippo');
$product->setPrice(19.99);
....
// Use Doctrine EntityManager to store the Product object
}
Suppose that you know that the Product class has the following namespace: "AcmeHomeBundle:Product". It would by nice to create the $product object by using the namespace (e.g. by using the EntityManager or something similar).
public function defaultController() {
$item = createObjectFromNamespace("AcmeHomeBundle:Product");
$item->setName('Pippo');
$item->setPrice(19.99);
....
// Use Doctrine EntityManager to store the Item object
}
Do you know if this is possible?
Suppose that you have a string that provides the entity type
You should do this...
$entityInfo = $this->em->getClassMetadata("entityNameSpace:entityName");
$entityMember = $entityInfo->newInstance();
If you wanna use a setter method by string:
$entitySetMethod = "set".\ucfirst("entityDataMemberName");
\call_user_func(array($entityMember, $entitySetMethod), $parameter);
If you really want to, you can do this:
$product = new Acme\JournalBundle\Entity\Product();
$article = new Acme\JournalBundle\Entity\Article();
But you'd have to type it out every time you wanted to create a new entity in that namespace. If you simply used a use statement at the top of you class:
use Acme\JournalBundle\Entity\Product,
Acme\JournalBundle\Entity\Article;
You could then create new articles and products with a simple:
$product = new Product();
$article = new Article();
They do the same thing.
Acme\StoreBundle\Entity\Product IS the namespace of your entity. AcmeStoreBundle:Product is just an alias for the namespace to be used in DQL as a shorter alternative to the real namespace.
Why would you want to create objects with aliased namespace? I suppose you could create some kind of a factory using alias to map it to a real namespace, create an object and return it. But what's the point?
Entity aliases are defined via Configuration: http://www.doctrine-project.org/api/orm/2.2/source-class-Doctrine.ORM.Configuration.html#153
you can not only set them but also retrieve, so if you really need this functionality you should be able to do this with Configuration instance.
It's hard to find anything about entity aliases in Doctrine docs. Symfony docs explain the purpose of it a little:
alias - Doctrine offers a way to alias entity namespaces to simpler, shorter names to be used in DQL queries or for Repository access. When using a bundle the alias defaults to the bundle name.
My relation in entity:
/**
* #ORM\ManyToOne(targetEntity="Group")
*/
protected $group;
now I have a setter method setGroup() to set related entity, but there seems no method setGroupId() to set group_id without the entity object. How can I set group_id directly?
I suggest you have a look at Doctrine EntityManager ->getReference() method.
$user->setGroup($em->getReference('Group', 10));
Use a custom repository to create a specific method that will fetch the group, and then set it with setGroup.
Edit: You can even directly add/update the id via a SQL query: https://stackoverflow.com/a/10215061
But that's dirty.
Try defining another field (groupId) and map it directly ot your field in the database.