op het moment ben ik bezig met een aatal tests om te kunnen werken met SubForms.

Doel is :
$_POST['form']['veldnaam'] = value,
$_POST['subform1']['veldnaam'] = value,
$_POST['subform2']['veldnaam'] = value;

subform1 & 2 zijn dezelfde klassen.

Wat ik nu heb is :

<?php
$subForm = new Test_Form_Sub();
$subForms = array('a'=>$subForm,'b'=>$subForm,'c'=>$subForm);
$arr = array();
foreach($subForms as $formId => $form){
$subForms[$formId]->setName('form'.$formId);
}
$sub = new Zend_Form_SubForm();
$sub->addSubForms($subForms,'lines');
$this->addSubForm($sub,'sub');


Wat als resultaat geeft:
a = sub[veldnaam]
b = sub[ignore][sub][/ignore][veldnaam]
c = sub[ignore][sub][sub][/ignore][price_klm]

Ik weet dat het ergens nodig is om naamgeving van de "parent subform" te negeren of te overschrijven.

Iemand nog ideeën of een andere aanpak om gebruik te maken van Zend_SubForm();

(Getest met ZF Versie:1.10)
<?php
$subForms = array('a'=>$subForm,'b'=>$subForm,'c'=>$subForm); 

foreach($subForms as $formId => $form){ 
    $subForms[$formId]->setName('form'.$formId); 
} 
?>

Je weet dat je hier ervoor zorgt dat a, b en c alledrie verwijzen naar hetzelfde subform, en dat je in de foreach lus daaronder effectief 3x $subForm->setName() aanroept op dus dezelfde instantie?
Dat weet ik inderdaad.
Ik zou denken dat je dan niks wijzigt aan de naam van het SubFormulier, maar als ik voor elk subform een nieuw instantie maak is het resultaat:
a = sub['veldnaam']
b = sub['veldnaam']
c = sub['veldnaam']

Ik kan nog niet echt zeggen wat er mogelijk mis gaat, maar het heeft iets met de referentie te maken. Misschien dan niet van
[code]<?php $subForm;
// Maar dan van :
$sub;
// zie:
$sub = new Zend_Form_SubForm();
$sub->addSubForms($subForms,'lines');
$this->addSubForm($sub,'sub');
?>
Als je door de broncode van ZF spit, zie je dat addSubForm($sub, $x) zelf $sub->setName($x) aanroept (en dat addSubForms maar één argument neemt, en de namen afleidt uit de keys van dat eerste argument) Zou dat er iets mee te maken kunnen hebben?

Wijzigt Zend_Form_SubForm sowieso iets aan de veldnamen, of zou je daar weer een aparte decorator voor nodig hebben? (je merkt al, ik heb de documentatie niet helemaal gelezen)

PS: Kan je misschien een voorbeeld geven met echte namen ipv het abstracte 'sub' en 'veldnaam'? Ik kan me hier niet bij voorstellen wat er nu eigenlijk uit moet komen.
Ben ondertussen stuk verder gekomen. Hier onder het resultaat.
De magie zit in de setDefaults, isValid en getValues.
Er is een kleine workaround met een prefix voor mijn elementen in de subforms. Deze workaround zorgt er voor dat er geen velden met dezelfde naam voorkomen.

De volgende stap is een Jqueryscript wat een "template subform" kan kopiëren en de attributen wijzigt, zodat je dynamisch subforms kunt toevoegen en kunt verwijderen.




<?php

class Money_Form_Invoice extends Form_Base
{
	public function init() 
	{
		$this->setMethod('post')
		     ->setName('invoice')
			 ->setDecorators($this->formDecorators);
		
	 	$this->addElement('hidden', 'invoice_id', array(
			'required' 		=> false,
			'decorators' 	=> $this->hiddenDecorator
		));
		
		$this->addElement('hidden', 'year', array(
			'required' 		=> false,
			'decorators' 	=> $this->hiddenDecorator
		));

		$this->addElement('hidden','serial_code',array(
			'required' => true  ,
			'decorators'=> $this->hiddenDecorator,
		));


       $this->addElement('text', 'ordernumber', array(
			'label' => 'Werkorder',
			'maxlength' => 45,
			'size' => 15,
			'decorators' => $this->elementDecorator,
			'required' => true,
			'validators' => array(
				array('NotEmpty', false, array('messages' => array( 'isEmpty' => 'Dit veld is verplicht')))
			),
			'filters' => array('stringTrim', 'stripTags'),
		));

		$this->addElement('text', 'number', array(
			'label' => 'Factuur nummer',
			'maxlength' => 15,
			'size' => 15,
			'decorators' => $this->elementDecorator,
			'required' => true,
			'validators' => array(
				array('NotEmpty', false, array('messages' => array( 'isEmpty' => 'Dit veld is verplicht')))
			),		
			'value' => date('W'),
			'filters' => array('stringTrim', 'stripTags'),
		));
		
		$this->addElement('select', 'status', array(
			'label' => 'Status',
			'decorators' => $this->elementDecorator,
			'required' => true,
			'multiOptions' => array(
				'0' => 'Onbetaald',
				'1' => 'Betaald',
			), 
			'filters' => array('stringTrim', 'stripTags'),
		));
		
		$this->addElement('text', 'week', array(
			'label' => 'Weeknummer',
			'maxlength' => 5,
			'size' => 5,
			'decorators' => $this->elementDecorator,
			'required' => true,
			'validators' => array(
				array('NotEmpty', false, array('messages' => array( 'isEmpty' => 'Dit veld is verplicht')))
			),		
			'value' => date('W'),
			'filters' => array('stringTrim', 'stripTags'),
		));	

		$this->addElement('select', 'company_id', array(
			'label' => 'Bedrijf',
			'multiOptions' => array(0=>'',1=>'Bedrijf A',2=>'Bedrijf B'),
			'decorators' => $this->elementDecorator,
			'description' => '',
			'filters' => array('stringTrim', 'stripTags'),
		));		
        
		$this->addElement('select', 'rate', array(
			'label' => 'Tarief',
			'multiOptions' => Model_Rate::getRatesSelect()	,
			'decorators' => $this->elementDecorator,
			'description' => '',
			'filters' => array('stringTrim', 'stripTags'),
		));		
		
		$this->addElement('select', 'road_pricing', array(
			'label' => 'Reistarief',
			'multiOptions' => array('0.19'=>'€0,19','0.30'=>'€0,30')	,
			'decorators' => $this->elementDecorator,
			'description' => '',
			'filters' => array('stringTrim', 'stripTags'),
		));		

        $this->addElement('textarea', 'description', array(
			'label' => 'omschrijving',
                        'class' => 'newLine',
			'rows' => 10,
			'cols' => 25,
			'decorators' => $this->elementDecoratorNewLine,
			'description' => 'korte omschrijving van factuur. Wordt gebruikt in overzichten',
			'required' => true,
			'validators' => array(
				array('NotEmpty', false, array('messages' => array( 'isEmpty' => 'Dit veld is verplicht')))
			),		
			'filters' => array('stringTrim', 'stripTags'),
		));

		$this->addElement('button', 'submit', array(
			'label' => 'Opslaan',
			'class'=> 'button',
			'ignore' => true,
			'type' => 'submit',
			'decorators' => $this->buttonDecorator,
		));

		$this->addSubForm(new Zend_Form_SubForm,'lines');
		$this->addSubForm(new Zend_Form_SubForm,'new');
		
		$this->addElement('button', 'submit', array(
			'label' => 'Opslaan',
			'class'=> 'button',
			'ignore' => true,
			'type' => 'submit',
			'order'=>1002,
			'decorators' => $this->buttonDecorator,
		));
   	}

	public function isValid($data){
		$subForm = $this->getSubForm('new');
		if(isset($data['new'])){
			$data['new']= array();
		}

		foreach($data as $idx => $line){
			$prefixIdx = $idx.'__';
			$newSubForm = new Money_Form_SubInvoiceLine(array('prefix'=>$prefixIdx));
			$subForm->addSubForm($newSubForm, $idx);
       	}

		return parent::setDefaults($data);
	}

	public function setDefaults($defaults)
	{
		$subForm = $this->getSubForm('lines');
		$subForm->clearSubForms();
       	foreach($defaults['lines'] as $idx => $line){
			if($idx == 0) $idx =1;
			$prefixIdx = $idx.'__';
			$subFormLine = new Money_Form_SubInvoiceLine(array('prefix'=>$prefixIdx));

			foreach($line as $name => $value){
				$subFormLine->setDefault($prefixIdx.$name, $value);
           	}
			
			$subForm->addSubForm($subFormLine,(string) $idx );
			unset($defaults[$idx]);
		}
		unset($defaults['lines']);
		return parent::setDefaults($defaults);
    }

	public function getValues(){
		$values = parent::getValues(true);
		$lines = array();
       	foreach($values['lines'] as $idx => $line ){
			if($idx == 0) $idx =1;
			foreach($line as $name => $value){
				$key = preg_replace('/[0-9]__/','',$name);
				$lines[$idx][$key] = $value;
			}
		}
		$values['lines'] = $lines;
		return $values;
	}

}


<?php
Class Money_Form_SubInvoiceLine extends Form_SubBase
{
	protected $_prefix = '';

	public function setPrefix($prefix = null){
		$this->_prefix = $prefix;
	}
	
	public function init(){

		$this->addElement('hidden', $this->_prefix.'invoice_id', array(
				'required' 		=> false,
				'decorators' 	=> $this->hiddenDecorator
			));

			$this->addElement('hidden', $this->_prefix.'invoice_line_id', array(
				'required' 		=> false,
				'decorators' 	=> $this->hiddenDecorator
			));

			$this->addElement('text', $this->_prefix.'description', array(
				'label' => 'omschrijving',
				'maxlength' => 250,
				'size' => 10,
				'decorators' => $this->elementDecorator,
				'description' => 'korte omschrijving',
				'required' => true,
				'validators' => array(
					array('NotEmpty', false, array('messages' => array( 'isEmpty' => 'Dit veld is verplicht')))
				),
				'filters' => array('stringTrim', 'stripTags'),
			));

			$this->addElement('text', $this->_prefix.'hours', array(
				'label' => 'Uren',
				'maxlength' => 100,
				'size' => 4,
				'decorators' => $this->elementDecorator,
				'required' => true,
				'validators' => array(
					array('NotEmpty', false, array('messages' => array( 'isEmpty' => 'Dit veld is verplicht')))
				),
				'filters' => array('stringTrim', 'stripTags'),
			));

			$this->addElement('text', $this->_prefix.'travel_klm', array(
				'label' => 'Kilometers',
				'maxlength' => 100,
				'size' => 4,
				'decorators' => $this->elementDecorator,
				'required' => false,
				'filters' => array('stringTrim', 'stripTags'),
			));

			$this->addElement('text', $this->_prefix.'price_klm', array(
				'label' => 'Klm prijs',
				'maxlength' => 100,
				'size' => 4,
				'decorators' => $this->elementDecorator,
				'required' => false,
				'filters' => array('stringTrim', 'stripTags'),
			));

			$this->addElement('select', $this->_prefix.'rate', array(
				'label' => 'Tarief',
				'multiOptions' => Model_Rate::getRatesSelect()	,
				'decorators' => $this->elementDecorator,
				'description' => '',
				'filters' => array('stringTrim', 'stripTags'),
			));

			$this->addElement('select', $this->_prefix.'cost_percentage', array(
				'label' => 'Toeslag',
				'multiOptions' => array('100'=>'Geen','110'=>'110%','150'=>'150%','200'=>'200%'),
				'decorators' => $this->elementDecorator,
				'description' => '',
				'filters' => array('stringTrim', 'stripTags'),
			));
	}
}

Reageren