Doctrine2: dynamic entity associations, many targetEntity mapped by one field - php

I have a Entity called Event which has
a field "associatedEntity" containing the class name of another Entity in the Bundle
a field "targetId" of that specific "associatedEntity" Entity
I would now like to access this target entity inside my Event-Entity somehow but im now sure how to do it. I'd like to access the different target Entities in a twig template using something like
{% if event.getClassName() == "User" %}
{{ if event.getUser().getName() }}
{% endif %}
Edit: Just to be clear, the only thing im interested so far is how to create the relation properly. Outside a ORM World you would probably use a join statement for this. It is like i have many target Entities mapped by one field.
So far im using the entity repository and DI to load the associated Entities, but i find that ugly knowing there is a JOIN Statement which i could use:
public function getUpcomingEvents(){
$query = $this->createQueryBuilder('E')
->where('E.resolved = false')
->orderBy('E.notify_date', 'ASC')
->setMaxResults( $limit );
$res = $query->getQuery()->getResult();
$res = $this->attachAssociatedObjects($res);
return $res;
}
public function attachAssociatedObjects($res){
foreach ($res as $key => $entity) {
$assocObject = $this->getEntityManager()->getReference('My\Bundle\Entity\\'.$entity->getClassName(), $entity->getTargetId());
$res[$key]->setAssociatedObject($assocObject);
}
return $res;
}

Twig attribute function is what you need.

Related

Symfony relationship get by id in Entity without repository

I have in my Item ORM entity a relationship with Packs.
Now in my code I have a PackId and I have an Item. Now here's what I am trying in my code:
$item->getPackById($pack->getId);
In my Item Entity I try something like this:
public function getPackById(UuidInterface $packId)
{
return $this->packs[$packId];
}
I am not sure If I can do this without a repository or is there a better way?
Normally we try to avoid to much work in an entity but as you are certain that the packs UUID are unique you could try something with an array filter like :
public function getPackById(Uuid $uuid): ?Pack
{
$matching = array_filter((array)$this->packs, fn(Pack $pack) => $pack->getUuid() === $uuid);
return $matching[0];
}

Doctrine One to Many relationship

I got confuse in doctrine one to many relationship.
Question 1:
Correct me if I am wrong. I assume that when I try to
$em = $this->getDoctrine()->getManager();
$product_repo = $em->getRepository('MyBundle:Product');
$products = $product_repo->findAll();
dump($products);
I will see the related features attached to the $features variable, so when I use $products->getFeatures() I will have Feature object in array form. But from the dump debug I didn't not see anything attached to it instead I got this:
On the other end I also do this
$em = $this->getDoctrine()->getManager();
$feature_repo = $em->getRepository('MyBundle:Features');
$features = $product_repo->findAll();
dump($features);
This time I can see the Product object is attached to the $product variable.
My question is, is there any problem why I can't get data from the variable $features? Or doctrine wouldn't load the related data by default.
Question 2:
If we were assumed that the data is able to load into the feature $variable, is it possible that I can filter the data (eg. where feature.name = 'fly') instead of load all of the related feature.
==========================================================================
My Demo Entity
<?php
use Doctrine\Common\Collections\ArrayCollection;
/** #Entity **/
class Product
{
// ...
/**
* #OneToMany(targetEntity="Feature", mappedBy="product")
**/
private $features;
// ...
public function __construct() {
$this->features = new ArrayCollection();
}
}
/** #Entity **/
class Feature
{
// ...
/**
* #ManyToOne(targetEntity="Product", inversedBy="features")
* #JoinColumn(name="product_id", referencedColumnName="id")
**/
private $product;
// ...
}
Product table (in database): id, description, name
Feature table (in database): id, description, name, table_id
Assuming that your dump function is symfony/var-dumper and not a custom function
Question 1
Yes, nested collection are not displayed by default by dump function, its about performance. This is not a Doctrine related issue. Your data are loaded here.
You can play around with advanced use of var-dumper, like casters ( http://symfony.com/doc/current/components/var_dumper/advanced )
Question 2
You have differents ways to solve your question :
In Controller : Create your custom method in Product
Criteria better solution
Product::getFeaturesByName($name='fly'){
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('name', $name));
return $this->features->matching($criteria);
}
Filter
Product::getFeaturesByName($name='fly'){
return $this -> features ->filter(
function($entry) use ($name) {
return $entry->getName() == $name;
}
);
}
);
}
In Twig Template : filter in loop
{% for product in products %} {# start browse products #}
{% for feature in product.features if feature.name='ok' %}{# start browse features #}
{% endfor %}{# end browse features #}
{% endfor %}{# end browse products #}
Hope this will help you
regards

Mapping myself form in Symfony2

I'd like to map an entity of a form by myself. The thing is I'm working with 36 000 cities in a database and Doctrine doesn't return any result when I'm performing a request using findBy. But I set this up by writting my owns methods.
The problem is in a form I need to ask for a city through an entity field (because there are a lot of data, I'm using select2 with remote's data). So far, no problem but when I'm submiting the form, Symfony can't bind the city's id to a database entry because of the none result of the classic method of Doctrine.
So, my question is : How can I tell Symfony to use my repository's method instead of the Doctrine's one to bind my data?
Thank you very much ! And have a good day ;)
The method findBy() request an array parameter sometimes people miss that:
$result = $this->getDoctrine()->getManager()
->getRepository("AcmeDemoBundle")->findBy(array(
"city" => $city)
);
If you want to use repository you just need to map it to your class:
/**
* #ORM\Entity(repositoryClass="Acme/DemoBundle/Repository/CountryRepository")
*/
class Country
{ ... }
Then in
class CountryRepository extends EntityRepository
{
public function getMySpecificCity($city)
{
$qb = $this->createQueryBuilder('c');
$cities = $qb->select(*)
->where("c.city =:city ")->setParameter('city', $city)
->getQuery()
->getResult();
return $cities;
}
...
}
So you can use it as follow:
$result = $this->getDoctrine()->getManager()
->getRepository("AcmeDemoBundle")->getMySpecificCity($city);

symfony2 doctrine findBy id in arrayCollection

Using Symfony2.3.4 and Doctrine.
I have a class Student with a ManyToMany relation with a class Edition.
Now in my StudentController I have this IndexAction($edition_id) to list not all students in the DB but only those related to the given Edition id.
$entities = $em->getRepository('PersonBundle:Student')->findBy(array(
????????
));
I'm thinking of some kind of criteria to use with $edition_id but can't come up with any.
Tips appreciated, thanks.
#dmnptr:
I'm trying that, I'm quite new to this so tell me if I did something wrong.
I put that function you wrote in the controller and in the method IndexAction($edition) I added
$students = this->findAllByEdition($edition);
now the problem is that the parameter $edition is coming from a twig template like this:
<a href="{{ path('student', { 'edition': entity}) }}"</a>
being entity who holds the Edition object.
But when I do it like this entity returns the __toString() method, meaning a string with the name of the edition, not the edition itself which is what the function you gave me uses.
Now, do you happen to know a way to get the object itself from the template, not the __toString() method, thanks...
You should use custom repository method. Pass $edition as a parameter, not just an id. Something like this:
public function findAllByEdition($edition)
{
$em = $this->getEntityManager();
$queryText = "SELECT s FROM PersonBundle:Student s ";
$queryText .= "WHERE :edition MEMBER OF s.editions";
$query = $em->createQuery($queryText);
$query->setParameter('edition', $edition)
return $query->getResult();
}

Symfony 2 "findBy" a mapped entity parameter into controller

I'm new with Symfony2 and i would like to know whether there is a way to use the "findBy" with a param which is present only in a mapped entity.
This is my snippet controller:
$prods = $em->getRepository('EcommerceProductBundle:ProductData')
->findBy(array(
'product_id'=>46
));
It works good but if i try to add another element to the array, which is present in a mapped entity, it get (rightly) this error
Unrecognized field: ProductImage.is_visible
What i would like to do, is just to know wehether i can use the "filterBy" with a mapped element of the entity ProductData.
I'm in wrong but this is my idea:
->findBy(array(
'product_id'=>46,
'ProductImage.is_visible'=>1
));
Not possible as far as i know. Just add this custom method to your repository:
public function findByIdAndVisibleImage($id)
{
return $this->createQueryBuilder('product')
->lefJoin("product.image","i")
->where("product.product_id = :id")
->andWhere("i.is_visible = 1")
->setParameter("id", $id)
->getQuery()
->getSingleResult();
}
You can't do that, you need to write a custom method in the repository with a join clause.
The findBy method just add a where clause on the criteria.

Categories