12

I have the class categroies and class Products.

In my repository i have function

getProducts($categoryid,$location)

I need to loop in twig template like this

 {% for category in categories %}
    --{{ category.name }}--
      {% for product in getProducts(category.id,location) %}
     --{{ product.name }}--
    {% endfor %}
 {% endfor %}

or is there any better way for that

2
  • Have you tried {% for item in product.items %} ? Commented Aug 1, 2012 at 7:00
  • I think you should create a Twig extension. Take a look at this topic Commented Aug 1, 2012 at 7:05

4 Answers 4

20

You shouldn't. Thats business logic, that should not appear in templates. One solution is to create a new action within a controller and in your template call

{% render '@MyBundle:Product:list' with {category: category.id} %}
Sign up to request clarification or add additional context in comments.

6 Comments

or can i make 2 dimensional array like product[category][products] in controller and then send that array in template
@john110016 Or you create a OneToMany-Relationship between the category- and the product-entity ;) for product in category.products. Yes, there are multiple solutions, but calling the entity repository is not one of them.
I already have the onetomany relationship but problem is how to apply the location filter , it shows all products if i do that
@john110016 Good point. You could try a Filter :) Should look like for product in products|products_by_location(location) or something like that. You can find information on how to implement them quite easy when usin s2 in this article and in official manual "How to write a custom Twig Extension".
IIRC, rendering a controller can have a bad impact on performance. Can you please confirm that it won't be slower than passing the repository to the Twig template?
|
7

It's a pretty old question, but I'm missing a really simple solution like this one.

It is possible to pass the repo object to twig and call the repo public methods from twig like so:

In your controller

$oCatRepo = $this->getDoctrine()->getManager()->getRepository('AppBundle:Categories');
....
return $this->render('product_list.html.twig', array('oCatRepo' => $oCatRepo));

And then in your twig template :

{{ oCatRepo.getProducts(category.id, location) }}

Im saying it's possible, many would argue that templates should only display data and let controllers gather the data. I personally don't mind letting my templates getting their data themselves.

Comments

1

I suspect that all you really need is a left join using a WITH expression. Something like:

class CategoryManager
{
    public function loadCategoriesProductsForLocation($location)
    {
        $qb = $this->em->->createQueryBuilder();

        $qb->addSelect('category');
        $qb->addSelect('product');

        $qb->from('MyBundleBundle:Category','category');

        $qb->leftJoin('category.products','product', 
            Expr\Join::WITH, $qb->expr()->eq('product.location', $location));

That will give you all the categories with their respective products for a given location.

Comments

1

The solution is the other way around as how this is done right now. The Category entity should have a one-to-many relation. Take a look at http://symfony.com/doc/2.0/book/doctrine.html#entity-relationships-associations

The category Entity should then have an EntityCollection attribute called 'products'. In your template you then can solve this in the following way:

{% for category in categories %}
    --{{ category.name }}--
      {% for product in category.products %}
     --{{ product.name }}--
    {% endfor %}
 {% endfor %}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.