Symfony view loop parameter

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Roel -

Roel -

14/08/2015 13:49:05
Quote Anchor link
Hoi,

Ik heb in Symfony een view met daarin een loop die een andere (partial) view laadt. Deze partial view maakt gebruik van cycle om odd en even te onderscheiden. Zolang ik de cycle binnen de hoofd Twig-template gebruik, is er niets aan de hand, maar op het moment dat ik deze partial view vanuit m'n controller wil renderen met $this->renderView() krijg ik de volgende foutmelding:
Variable "loop" does not exist in desktop/ride/ride.html.twig at line 1

Weet iemand hoe ik aan renderView() de loop-variabele kan meegeven vanuit een foreach() in mijn controller?

Roel
 
PHP hulp

PHP hulp

24/12/2024 19:23:40
 
Jan de Laet

Jan de Laet

14/08/2015 14:13:55
Quote Anchor link
Is het voor opmaak van je view?
Dan kun je ook naar CSS oplossing kijken, bijv om een tr op te maken: tr:nth-child(2n+0) {background: #ff0000;}
 
Richard Snijders

Richard Snijders

14/08/2015 14:26:22
Quote Anchor link
Hoi Roel,

Als het goed is, render je de view vanuit je Controller? In dat geval kun je namelijk gewoon return $this->render('AcmeBundle:default:index.html.twig', array('entities' => $entities)); doen bijvoorbeeld.

In je view kun je dan het volgende schrijven:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
{% for entity in entities %}
    {% include 'AcmeBundle:default/blocks:item.html.twig' %}
{% endfor %}


Volgens mij wordt het loop object dan meegegeven aan item.html.twig, maar kan zijn dat je hem apart moet opgeven met with{}

Zie ook:
http://twig.sensiolabs.org/doc/tags/include.html
 
Roel -

Roel -

14/08/2015 14:32:08
Quote Anchor link
De view render ik op deze manier in een Twig-template:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
{% for ride in rides %}
            {{ include('desktop/ride/ride.html.twig', { 'ride': ride }) }}
        {% else %}
            <tr>
                <td colspan="6">Het lijkt erop dat er (nog) geen ritten zijn geregistreerd.</td>
            </tr>
        {% endfor %}

In m'n controller doe ik het zo:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
foreach ($rides as $ride) {
                    $output .= $this->renderView(
                        Toolkit::getDeviceType() . '/ride/ride.html.twig',
                        array(
                            'ride' => $ride
                        )
                    );
                }

Inmiddels heb ik het werkend met de hierboven getoonde CSS-oplossing. Bedankt!
 
Richard Snijders

Richard Snijders

14/08/2015 14:43:34
Quote Anchor link
Hoi Roel,

Fijn dat je een oplossing gevonden hebt :)
Ik wil nog wel even inhaken op de code die je geplaatst hebt.

Ik zie namelijk dat je in je controller een view rendert en vervolgens in een $output variabele stopt. Dat is eigenlijk per definitie geen correct gebruik van views. Die gebruik je uitsluitend om webpagina's of e-mails te renderen; Twig is immers krachtig genoeg om dat zelf allemaal te kunnen doen :)

Dat is ook meteen de reden dat je de loop-variabele niet kunt gebruiken in je view; de renderView functie van Controller geeft die variabele niet standaard mee, maar Twig doet dat wel bij een include (als je de only flag niet gebruikt).
 
Roel -

Roel -

14/08/2015 16:16:38
Quote Anchor link
Bedankt voor je commentaar op de manier hoe ik de view render in m'n controller. Het kan best dat mijn manier van denken nog niet helemaal MVC is. :-)

Het is namelijk zo dat ik een tabel heb waarin ik dan de rijen in m'n Twig-template als partial view toon. Omdat ik wil filteren op deze tabel, bouw ik nadat je op 'zoek' klikt in m'n controller een nieuw overzicht op en dan render ik weer die rijen, om ze vervolgens als HTML terug te sturen.

Is dit geen correct gebruik?
 
Richard Snijders

Richard Snijders

14/08/2015 16:39:57
Quote Anchor link
Het is eigenlijk de bedoeling dat je de data die je aan de view meegeeft hapklaar is. Filteren moet je dus voor het renderen doen.
Dat kan heel makkelijk via een Form Type. Je kunt bijvoorbeeld een PersistentCollection, gewone Collection of een QueryBuilder (of whatever) aan je Form meegeven waar je op basis van de filterbare velden op filtert.

Hier heb ik zelf weleens iets voor gebouwd. Is wel een beetje een rommelcode, maar dan heb je een idee hoe je zoiets kunt doen.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
<?php
namespace Fizz\Klaver\AdminBundle\Form\Entity;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class Filter extends AbstractType
{

    /**
     * @var string
     * The name of the entity to be selected from
     */

    private $entityName;
    /**
     * @var EntityManager
     * The entity manager
     */

    private $entityManager;
    /**
     * @var array Fields to use as a filter
     */

    private $filterFields = array();

    private $customFilters = array();

    /**
     *
     * @param $entityName The entity to use for filtering
     * @param $filterFields Explaination up above
     * @param EntityManager $em Give the entity manager
     */

    public function __construct($entityName, $filterFields, EntityManager $em)
    {

        $this->entityName = $entityName;
        $this->entityManager = $em;
        $this->filterFields = $filterFields;
    }


    /**
     * Factory for extended filters
     * @param $filterName
     * @param FormBuilderInterface $builder
     * @return mixed
     */

    public function factory($filterName, FormBuilderInterface $builder)
    {

        $filterName = __NAMESPACE__ . '\Filter\\' . ucfirst($filterName) . 'Filter';
        return new $filterName($builder);
    }


    /**
     * The form builder automatically builds the form based on the given fields and choices
     * @param FormBuilderInterface $builder
     * @param array $options
     * @throws \Doctrine\ORM\Mapping\MappingException
     */

    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $md = $this->entityManager->getClassMetadata($this->entityName);
        foreach($this->filterFields as $key => $field)
        {

            $choices = array();
            if(!is_numeric($key) && !$md->hasAssociation($key) && is_array($field) && isset($field['choices']) && is_array($field['choices']))
            {

                $choices[''] = '';
                foreach($field['choices'] as $choice => $alias)
                    $choices[$choice] = $alias;
            }

            elseif($md->hasAssociation($key) && $field['method'] == 'choice')
            {

                $mapping = $md->getAssociationMapping($key);
                $entities = $this->entityManager->getRepository($mapping['targetEntity'])->findAll();
                $choices[''] = '';
                $value = 'get' . ucfirst($field['field']);
                foreach($entities as $choice)
                {

                    $getId = 'get' . ucfirst($field['idField']);
                    $choices[$choice->$getId()] = $choice->$value();
                }
            }

            elseif(isset($field['method']) && $field['method'] != 'choice')
                $field = $key;
            elseif(!is_string($field))
            {

                $this->customFilters[$key] = $this->factory($field['filter'], $builder);
                $builder->add($this->customFilters[$key]->create());
            }

            if(count($choices)) {
                $builder
                    ->add($builder->create($key, 'choice', array(
                        'choices' => $choices,
                        'label' => false,
                        'expanded' => false,
                        'multiple' => false,
                        'required' => false
                    )));
            }

            elseif(is_string($field))
                $builder->add($builder->create($field, 'text', array('label' => false, 'required' => false)));
        }

        $builder->add('filter', 'submit', array('label' => 'Filter'));
    }


    /**
     * Adds a where condition to the query considering the possibility of there already being
     * added conditions
     * @param QueryBuilder $query
     * @param $where
     * @return QueryBuilder
     */

    private function addWhere(QueryBuilder $query, $where)
    {

        if(strpos($query->getDQL(), ' WHERE ') === false)
            return $query->where($where);
        else
            return $query->andWhere($where);
    }


    /**
     * Filter on all entered criteria.
     * If the field name has an association with an internal relationship, it will try to find a match in this relationship using a join
     * If the field name exists in the entity, it will try to find a match in the entity using the determined method
     * If a custom filter is given using the 'filter' option, it will execute the filter method of this custom filter
     * If the conditions exist in a 'choice', it will try to match the given text exactly using the value provided.
     * @param QueryBuilder $query
     * @param array $data
     * @return QueryBuilder
     */

    public function filterQuery(QueryBuilder &$query, $data)
    {

        $fn['like'] = function($query, $fieldName, $field, $value) {
            $this->addWhere($query, $fieldName . ' LIKE :' .  strtolower($field))
                ->
setParameter(strtolower($field), '%' . addcslashes($value, '%_') . '%');
        };

        $fn['eq'] = function($query, $fieldName, $field, $value) {
            $this->addWhere($query, $fieldName . ' = :' .  strtolower($field))
                ->
setParameter(strtolower($field), $value);
        };

        if(!$data)
            return $query;
        $md = $this->entityManager->getClassMetadata($this->entityName);
        $i = 97;
        foreach($data as $field => $value)
        {

            $func = 'like';
            if(!strlen($value))
                continue;
            $aliases = $query->getRootAliases();
            $fieldName = $aliases[0] . '.' . $field;
            if($md->hasAssociation($field))
            {

                while(in_array(chr($i), $aliases))
                    $i++;
                $func = $this->filterFields[$field]['method'] == 'choice' ? 'eq' : 'like';
                $this->filterFields[$field] = $this->filterFields[$field]['method'] == 'choice' ? (isset($this->filterFields[$field]['idField']) ? $this->filterFields[$field]['idField'] : 'id') : $this->filterFields[$field]['field'];
                $fieldName = chr($i) . '.' . $this->filterFields[$field];
                $query->join($aliases[0] . '.' . $field, chr($i));
                $i++;
            }

            elseif(isset($this->filterFields[$field]) && is_array($this->filterFields[$field]))
                $func = 'eq';
            if(isset($this->customFilters[$field]))
                $this->customFilters[$field]->filter($query, $value);
            else
                $fn[$func]($query, $fieldName, $field, $value);

        }


        $query = $query->getQuery();

        $query->setHint(
            \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
            'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
        );

        return $query;
    }


    /**
     * The name of the form
     * @return string
     */

    public function getName()
    {

        return 'filters';
    }

}


//[/code] < Lol phphulp sluit de code tag niet af de 1e keer :P


Op deze manier maak je hem dan aan:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
$this->createForm(
    $filterType = new Filter(
        $entity,
        array(
            'title' => 'title',
            'category' => array('field' => 'value', 'method' => 'choice', 'idField' => 'id'),
        ),
        $this->getDoctrine()->getManager()
    ));
/** @var QueryBuilder $qb **/
$filterType->filterQuery($qb, $filterForm->getData());
Gewijzigd op 14/08/2015 16:41:36 door Richard Snijders
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.