• Willkommen im Zend Framework Forum

    ZF1 Zend Framework 1 + ZF2 Zend Framework 2

    Das Zend Framework Forum ist seit 2006 die erste Anlaufstelle für Zend Framework Entwickler in Deutschland. Mit über 70.000 Beiträgen und einer steigenden Nutzerzahl bietet das Forum hilfreiche Themen und ZF-Tutorials für professionelle Entwickler, fortgeschrittene Programmierer sowie Zend Framework Einsteiger.
    Wenn dies Dein erster Besuch in der Zend Framework Community ist, lies bitte zuerst die Hilfe - FAQ durch. Du musst Dich registrieren, bevor Du Beiträge verfassen kannst. Klicke oben auf 'Registrieren', um die Registrierung zu starten. Du kannst auch jetzt schon Beiträge lesen. Hier im Forum findest Du die Zend Framework Hilfe, die Du suchst!

    Grüße an alle Zend Framework Entwickler. Das Team vom Zend Framework Forum!

    Drupal Agentur

Veränderung jeder Item von Collection

Serg

New member
Hallo,

Entschuldigen Sie für mein schlecht Deutschsprache aber ich habe eine Frage.

Es gibt ein Fieldset, der ein element Collection enthält

Code:
class IngredientFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct(ObjectManager $objectManager)
    {
        parent::__construct('ingredient');

        $this->setHydrator(new DoctrineHydrator($objectManager))
             ->setObject(new Ingredient());
        
        /*iregendwelche felden*/

        $this->add(array(
            'type'    => 'Zend\Form\Element\Collection',
            'name'    => 'measurementIngredient',
            'options' => array(
                'target_element' => new MeasureIngredFieldset($objectManager),
           )
        ));

        /*iregendwelche felden*/
    }
}
Target element MeasureIngredFieldset sieht aus:

Code:
class MeasureIngredFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct(ObjectManager $objectManager)
    {
        parent::__construct('measurementIngredient');
        
        $this->setHydrator(new DoctrineHydrator($objectManager))
             ->setObject(new MeasureIngred());
        
        $this->add(array(
            'type' => 'Zend\Form\Element\Hidden',
            'name' => 'id'
        ));
        
        $this->add(array(
            'name' => 'measurement',
            'type' => '\Zend\Form\Element\Checkbox',
            'options' => array(
                'label' => 'test',  
                'use_hidden_element' => true,
                'checked_value' => '2',
                'unchecked_value' => '0',
            ),
        ));
        
        $this->add(array(
            'name' => 'gramm',
            'type' => '\Zend\Form\Element\Text',
            'options' => array(
                'label' => 'Количество, г'
            ),
            'attributes' => array(
                'class' => 'form-control'
            )
        ));
    }
}
Und ich schreibe folgende code in meinem Controller:
Code:
$measurements = $this->getEntityManager()->getRepository('Recipe\Entity\Measurement')->findBy(array('activate' => 1));
$measurementIngredient = $form->get('ingredient')->get('measurementIngredient');
$measurementIngredient->setCount(count($measurements));
Es arbeitet gut, und ich stelle Count im Collection erfolgreich hin. Aber ich brauche verschidene Label und verschidene checked_value im Feld 'measurement' in jeder Item dieser Collection zu haben. Hilfen Sie mir bitter.

Folgende code in meiner Controller arbeitet nicht
Code:
$measurementIngredient = $form->get('ingredient')->get('measurementIngredient')->getFieldsets()
Ich kann nich jeder Item von Collection im foreach durchsehen.

Viele Grüße,
Sergey.
 

Serg

New member
Leute,

ich verstehe, dass es vielleicht sehr seltsame Frage ist, aber ich kann nicht die Antwort nirgendwo suchen. Wie kann ich im Controller jeder Item von Collection im foreach durchsehen und label mit checked_value veränderen?

Hilfen Sie Mir bitte:)

Viele Grüße,
Sergey.
 

michl

New member
Nachdem prepare() auf das Formular aufgerufen wurde kannst du ganz regulär über collections iterieren!

Wieso benötigst du unterschiedliche checked_value Werte? Vielleicht liegt der Fehler schon im Ansatz :)
 

Serg

New member
Hallo michl. Danke für deine Antwort:)

Es arbeitet wirklich! Nachdem prepare() kann ich collections iterieren! Ich verändere Label erfolgreich.

Aber wenn ich dort anhand setCheckedValue() checked_value Werte verändert, erhalte ich "The input was not found in the haystack" bei submit des Formular. Mein code:

Code:
$form = $this->form;
$form->prepare();
$filedsets = $form->get('ingredient')->get('measurementIngredient')->getFieldsets();
$i=0;
foreach($measurements as $measure){
  $filedsets[$i]->get('measurement')->setLabel($measure->getFullName());
  $filedsets[$i]->get('measurement')->setCheckedValue($measure->getId());
  $i++;
}
Ja, vielleich liegt der Fehler schon im Ansatz. Ich werde meine Ziel beschreiben, vielleicht gibt es andere Lösung.

Es ist eine Seite für Küche und Rezepten. Hier wird man Rechner des Kalorie sein. Ich habe die Tabelen Ingredient und Measurement. Und für jeder Ingredient müss ich einige measurements auswählen und für jeder measurement die Menge in Gramm zeigen.

Also im Formel "Add ingredient" habe ich Liste alles Measurements und für jeder Measurements ein input feld, folgende code:
Code:
class IngredientFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct(ObjectManager $objectManager)
    {
        parent::__construct('ingredient');

        $this->setHydrator(new DoctrineHydrator($objectManager))
             ->setObject(new Ingredient());
        
        /*iregendwelche felden*/

        $this->add(array(
            'type'    => 'Zend\Form\Element\Collection',
            'name'    => 'measurementIngredient',
            'options' => array(
                'target_element' => new MeasureIngredFieldset($objectManager),
           )
        ));

        /*iregendwelche felden*/
    }
}
hier "measurementIngredient" ist Liste der Measurements, und

Code:
class MeasureIngredFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct(ObjectManager $objectManager)
    {
        parent::__construct('measurementIngredient');
        
        $this->setHydrator(new DoctrineHydrator($objectManager))
             ->setObject(new MeasureIngred());
        
        $this->add(array(
            'type' => 'Zend\Form\Element\Hidden',
            'name' => 'id'
        ));
        
        $this->add(array(
            'name' => 'measurement',
            'type' => '\Zend\Form\Element\Checkbox',
            'options' => array(
                'label' => 'test',  
                'use_hidden_element' => true,
                'checked_value' => '2',
                'unchecked_value' => '0',
            ),
        ));
        
        $this->add(array(
            'name' => 'gramm',
            'type' => '\Zend\Form\Element\Text',
            'options' => array(
                'label' => 'Количество, г'
            ),
            'attributes' => array(
                'class' => 'form-control'
            )
        ));
    }
}
jeder Item in Liste des Measurements.

Eigentlich, jeder "measurement" in collection muss verschidene "checked_value" (measurement_id) haben. Vielleicht gibt es noch ein Lösung?

Wenn andere Lösung es gibt nicht, wie kann man "The input was not found in the haystack" berichtigen?

Ich kann nich DoctrineModule\Form\Element\ObjectMultiCheckbox benutzen, weil man noch input feld "gramm" braucht.

P.S. Ich verstehe, dass es nicht sehr einfach Frage ist, aber ich werde für deine Hilfe danbar sein.

Viele Grüße,
Sergey.
 

michl

New member
Der prepare() Aufruf sollte nicht im Controller stattfinden
Form Collections — Zend Framework 2 2.4.0 documentation - Zend Framework
the prepare() method. You must call it prior to rendering anything in the view (this function is only meant to be called in views, not in controllers).

Ich hab leider noch nicht ganz verstanden wie Die Formulare später aussehen sollen.
Kannst du das vielleicht nochmal auf englisch beschreiben?


Einen Hinweis hab ich allerdings vorab noch:

Die konkreten values für deine Checkboxen sollten bereits beim hydrieren stehen!
Es ist wenig sinnvoll im Nachgang über die Collections zu iterieren und dann Werte zu verändern. Siehe InArray Validator. Der lässt sich zwar deaktivieren, aber das willst du nicht ;)
 

Serg

New member
Michl Entschuldig, dass ich so lange Zeit nicht antworte. Vielleicht ist es sehr seltsam, aber ich kann Englich nicht schreiben und sprechen((

Meine Frage ist akute bisher.

Ich habe ein Doctrine Entity mit dem Titel "Ingredient", der ein variable $measurementIngredient hat.

Code:
[COLOR=#000080][B]class [/B][/COLOR]Ingredient [COLOR=#000080][B]extends [/B][/COLOR]BaseEntity
{
   ...

   [COLOR=#808080][I]/**
[/I][/COLOR][COLOR=#808080][I]    * [/I][/COLOR][COLOR=#808080][B][I]@ORM\OneToMany[/I][/B][/COLOR][COLOR=#808080][I](targetEntity="\Recipe\Entity\MeasureIngred", mappedBy="ingredient", cascade={"persist", "remove"}, orphanRemoval=TRUE)
[/I][/COLOR][COLOR=#808080][I]    */
   [/I][/COLOR][COLOR=#000080][B]protected [/B][/COLOR][COLOR=#660e7a][B]$measurementIngredient[/B][/COLOR];

   [COLOR=#000080][B]public function [/B][/COLOR]__construct()
   {
       [COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient [/B][/COLOR]= [COLOR=#000080][B]new [/B][/COLOR]ArrayCollection();
   }
   
   [COLOR=#000080][B]public function [/B][/COLOR]addMeasurementIngredient(Collection [COLOR=#660000]$measurementIngredients[/COLOR])
   {
       [COLOR=#000080][B]foreach[/B][/COLOR]([COLOR=#660000]$measurementIngredients [/COLOR][COLOR=#000080][B]as [/B][/COLOR][COLOR=#660000]$measurementIngredient[/COLOR]){
          [COLOR=#000080][B]if [/B][/COLOR](![COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR]->contains([COLOR=#660000]$measurementIngredient[/COLOR])) {
               [COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR]->add([COLOR=#660000]$measurementIngredient[/COLOR]);
               [COLOR=#660000]$measurementIngredient[/COLOR]->setIngredient([COLOR=#660000]$this[/COLOR]);
           }
       }
   }
   [COLOR=#000080][B]public function [/B][/COLOR]removeMeasurementIngredient(Collection [COLOR=#660000]$measurementIngredients[/COLOR])
   {
   [COLOR=#000080][B]foreach[/B][/COLOR]([COLOR=#660000]$measurementIngredients [/COLOR][COLOR=#000080][B]as [/B][/COLOR][COLOR=#660000]$measurementIngredient[/COLOR]){
           [COLOR=#000080][B]if [/B][/COLOR]([COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR]->contains([COLOR=#660000]$measurementIngredient[/COLOR])) {
               [COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR]->removeElement([COLOR=#660000]$measurementIngredient[/COLOR]);
            [COLOR=#660000]    $measurementIngredient[/COLOR]->setIngredient([COLOR=#000080][B]null[/B][/COLOR]);
           }
       }
   }

   [COLOR=#000080][B]public function [/B][/COLOR]getMeasurementIngredient()
   {
       [COLOR=#000080][B]return [/B][/COLOR][COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR]->toArray();
   }
...
Es gibt noch Entity mit dem Titel "Measurement", der auch ein variable $measurementIngredient hat.

Code:
[COLOR=#000080][B]class [/B][/COLOR]Measurement [COLOR=#000080][B]extends [/B][/COLOR]BaseEntity
{
    
   [COLOR=#808080][I]/**
    [/I][/COLOR][COLOR=#808080][I]    * [/I][/COLOR][COLOR=#808080][B][I]@ORM\OneToMany[/I][/B][/COLOR][COLOR=#808080][I](targetEntity="\Recipe\Entity\MeasureIngred", mappedBy="measurement", cascade={"persist", "remove"}, orphanRemoval=TRUE)
    [/I][/COLOR][COLOR=#808080][I]    */
    [/I][/COLOR][COLOR=#000080][B]protected [/B][/COLOR][COLOR=#660e7a][B]$measurementIngredient[/B][/COLOR];
   
       [COLOR=#000080][B]public function [/B][/COLOR]addMeasurementIngredient(MeasureIngred [COLOR=#660000]$measurementIngredient[/COLOR])
        {
               [COLOR=#000080][B]if [/B][/COLOR](![COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR]->contains([COLOR=#660000]$measurementIngredient[/COLOR])) {
                        [COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR]->add([COLOR=#660000]$measurementIngredient[/COLOR]);
                        [COLOR=#660000]$measurementIngredient[/COLOR]->setMeasurement([COLOR=#660000]$this[/COLOR]); 
        }
    }
   
       [COLOR=#000080][B]public function [/B][/COLOR]removeMeasurementIngredient(MeasureIngred [COLOR=#660000]$measurementIngredient[/COLOR])
        {
                [COLOR=#000080][B]if [/B][/COLOR]([COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR]->contains([COLOR=#660000]$measurementIngredient[/COLOR])) {
                        [COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR]->removeElement([COLOR=#660000]$measurementIngredient[/COLOR]);
            [COLOR=#660000]$measurementIngredient[/COLOR]->setMeasurement([COLOR=#000080][B]null[/B][/COLOR]);
                }
         }

         [COLOR=#000080][B]public function [/B][/COLOR]getMeasurementIngredient()
         {
                 [COLOR=#000080][B]return [/B][/COLOR][COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurementIngredient[/B][/COLOR];
         }
}
...
Diese Entities verbinden miteinander anhand Entity MeasureIngred:

Code:
[COLOR=#000080][B]class [/B][/COLOR]MeasureIngred
{
   [COLOR=#808080][I]/**
[/I][/COLOR][COLOR=#808080][I]     * [/I][/COLOR][COLOR=#808080][B][I]@var [/I][/B][/COLOR][COLOR=#808080][I]integer
[/I][/COLOR][COLOR=#808080][I]     * [/I][/COLOR][COLOR=#808080][B][I]@ORM\Id
    [/I][/B][/COLOR][COLOR=#808080][I]* [/I][/COLOR][COLOR=#808080][B][I]@ORM\Column[/I][/B][/COLOR][COLOR=#808080][I](type="integer", options={"unsigned"=true})
[/I][/COLOR][COLOR=#808080][I]     * [/I][/COLOR][COLOR=#808080][B][I]@ORM\GeneratedValue[/I][/B][/COLOR][COLOR=#808080][I](strategy="AUTO")
[/I][/COLOR][COLOR=#808080][I]     */
    [/I][/COLOR][COLOR=#000080][B]protected [/B][/COLOR][COLOR=#660e7a][B]$id[/B][/COLOR];
   
   [COLOR=#808080][I]/**
[/I][/COLOR][COLOR=#808080][I]     * [/I][/COLOR][COLOR=#808080][B][I]@ORM\ManyToOne[/I][/B][/COLOR][COLOR=#808080][I](targetEntity="\Recipe\Entity\Measurement", inversedBy="measurementIngredient")
[/I][/COLOR][COLOR=#808080][I]     * [/I][/COLOR][COLOR=#808080][B][I]@ORM\JoinColumn[/I][/B][/COLOR][COLOR=#808080][I](name="measurement_id", referencedColumnName="id", nullable=FALSE)
[/I][/COLOR][COLOR=#808080][I]     */
    [/I][/COLOR][COLOR=#000080][B]protected [/B][/COLOR][COLOR=#660e7a][B]$measurement[/B][/COLOR];

    [COLOR=#808080][I]/**
[/I][/COLOR][COLOR=#808080][I]      * [/I][/COLOR][COLOR=#808080][B][I]@ORM\ManyToOne[/I][/B][/COLOR][COLOR=#808080][I](targetEntity="\Recipe\Entity\Ingredient", inversedBy="measurementIngredient")
[/I][/COLOR][COLOR=#808080][I]      * [/I][/COLOR][COLOR=#808080][B][I]@ORM\JoinColumn[/I][/B][/COLOR][COLOR=#808080][I](name="ingredient_id", referencedColumnName="id", nullable=FALSE)
[/I][/COLOR][COLOR=#808080][I]      */
    [/I][/COLOR][COLOR=#000080][B]protected [/B][/COLOR][COLOR=#660e7a][B]$ingredient[/B][/COLOR];
   
   [COLOR=#808080][I]/**
[/I][/COLOR][COLOR=#808080][I]     * [/I][/COLOR][COLOR=#808080][B][I]@ORM\Column[/I][/B][/COLOR][COLOR=#808080][I](type="float", scale=2)
[/I][/COLOR][COLOR=#808080][I]     */
    [/I][/COLOR][COLOR=#000080][B]protected [/B][/COLOR][COLOR=#660e7a][B]$gramm[/B][/COLOR];

    [COLOR=#000080][B]public function [/B][/COLOR]getId()
    {
        [COLOR=#000080][B]return [/B][/COLOR][COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]id[/B][/COLOR];
    }

    [COLOR=#000080][B]public function [/B][/COLOR]setId([COLOR=#660000]$id[/COLOR])
    {
        [COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]id [/B][/COLOR]= [COLOR=#660000]$id[/COLOR];
    }

    [COLOR=#000080][B]public function [/B][/COLOR]getMeasurement()
    {
        [COLOR=#000080][B]return [/B][/COLOR][COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurement[/B][/COLOR];
    }

    [COLOR=#000080][B]public function [/B][/COLOR]setMeasurement(Measurement [COLOR=#660000]$measurement [/COLOR]= [COLOR=#000080][B]null[/B][/COLOR])
    {
        [COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]measurement [/B][/COLOR]= [COLOR=#660000]$measurement[/COLOR];
    }

    [COLOR=#000080][B]public function [/B][/COLOR]getIngredient()
    {
        [COLOR=#000080][B]return [/B][/COLOR][COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]ingredient[/B][/COLOR];
    }

    [COLOR=#000080][B]public function [/B][/COLOR]setIngredient(Ingredient [COLOR=#660000]$ingredient [/COLOR]= [COLOR=#000080][B]null[/B][/COLOR])
    {
        [COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]ingredient [/B][/COLOR]= [COLOR=#660000]$ingredient[/COLOR];
    }
   
   [COLOR=#000080][B]public function [/B][/COLOR]getGramm()
    {
        [COLOR=#000080][B]return [/B][/COLOR][COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]gramm[/B][/COLOR];
    }

    [COLOR=#000080][B]public function [/B][/COLOR]setGramm([COLOR=#660000]$gramm[/COLOR])
    {
        [COLOR=#660000]$this[/COLOR]->[COLOR=#660e7a][B]gramm [/B][/COLOR]= [COLOR=#660000]$gramm[/COLOR];
    }

    [COLOR=#000080][B]public function [/B][/COLOR]__toString(){
        [COLOR=#000080][B]return [/B][/COLOR](string)[COLOR=#660000]$this[/COLOR]->getId();
    }
}
Ich habe große Probleme. Wie habe ich oben geschrieben, ich habe IngredientFieldset und MeasureIngredFieldset.

Ich schaffe in IngredientFieldset die Collection mit dem name "measurementIngredient". Und ich brauche, dass auf Formel alles Werte der Measurement von databank sein werden. Aber gitb es ein Schwerichkeit, dass es in MeasureIngred ein Field "Gramm" gibt.

Wie kann ich die Werte von databanke binden:

Code:
  $this->add(array(
    'type'    => 'Zend\Form\Element\Collection',
    'name'    => 'measurementIngredient',
    'options' => array(
       'target_element' => new MeasureIngredFieldset($objectManager),
    )
));
Ich habe gedacht, dass ich DoctrineModule\Form\Element\ObjectMultiCheckbox benutzen kann, aber ich habe ein Field "Gramm" und ich weiß nicht was kann ich machen.
 
Oben