Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 3.2.13

Bug #202 ArraySmarty Renderer Gives Unexpected Result
Submitted: 2003-11-05 15:45 UTC Modified: 2004-01-04 12:09 UTC
From: jkaufman at wamnetgov dot com Assigned: ths
Status: Closed Package: HTML_QuickForm
PHP Version: 4.3.3 OS: Mandrake Linux 9.1
Roadmaps: (Not assigned)    

 [2003-11-05 15:45 UTC] jkaufman at wamnetgov dot com
Description: ------------ I would like to create a text element that gets rendered as an array. eg, I want the generated form to look like: <input type='text' name="reqdate[0]" value='{$form.reqdate.value[$i]}'> (I have several arrays ($reqdate, $enddate, etc.) that are dynamically created by another form. I don't know up front how many there will be. I need to use Javascript to validate each one, and my original approach (w/o QuickForm) was this: for ($i=0; $i<$workcount; $i++) { $sid='sd' . $i; // unique id for start date echo <<<INPUT_FORM2 <TR> <TH class=l>Req. Start</TH> </TR> <TR> <TD><input type='text' size='10' name='reqdate[]' id='$sid' value='{$reqdate[$i]}'> etc. INPUT_FORM2; } The Javascript code knew that reqdate was an array (because of the square brackets, and could identify which element I wanted based on the unique ID. Using QuickForm/Smarty, I first tried: $form->addElement ('text', "reqdate[]", 'Req. Start'); so I could get this: <input type='text' name="reqdate" value='{$form.reqdate.value[$i]}'> but it never seemed to work correctly. I then tried the code snippet shown below. The resulting $form looks correct: [11] => html_quickform_text Object ( [_attributes] => Array ( [size] => 10 [name] => reqdate[0] [type] => text [value] => 07/17/2003 ) [_tabOffset] => 0 [_tab] => [_lineEnd] => [_comment] => [_label] => Req. Start [_type] => text [_flagFrozen] => [_persistantFreeze] => 1 ) The $smarty dump does not look correct: [0] => Array **** This is the problem line ( [name] => reqdate[0] [value] => 07/17/2003 [type] => text [frozen] => [label] => Req. Start [required] => [error] => [html] => ) Notice that the array key changed from 'reqdate[0]' to '[0]'. Reproduce code: --------------- require_once 'HTML/QuickForm.php'; require_once 'HTML/QuickForm/Renderer/ArraySmarty.php'; $form = new HTML_QuickForm(); $form->addElement ('text', "reqdate[0]", 'Req. Start'); $smarty = new Smarty_TSG; $renderer =& new HTML_QuickForm_Renderer_ArraySmarty($smarty); $form->accept($renderer); $smarty->assign('form', $renderer->toArray()); Expected result: ---------------- $smarty dump: [reqdate[0]] => Array ( [name] => reqdate[0] [value] => 07/17/2003 [type] => text [frozen] => [label] => Req. Start [required] => [error] => [html] => )


 [2003-11-05 16:35 UTC] ths at php dot net
I think its not a good idea to use somthing like "reqdate[]" as Quickform element name. Please try to use grouped element, which will result in reqdate[]. Have a look at the SmartyStatic_example.php
 [2003-11-05 17:45 UTC] mansion at php dot net
Thomas, This is supported in other renderers. How difficult do you think it will be to implement that for Smarty as well ? It is a useful feature under some circunstances (for example when you have to deal with multi dimentional arrays in grid like forms).
 [2003-11-06 05:56 UTC] ths at php dot net
The bug-submitter expect the full html field name as array key. This is not supported, because the keys in the array produced by the _static_ ArraySmarty renderer are only intended for convenient accesses the form elements inside the template. The html field name can accessed by: {$} ---> reqdate[0] {$} ---> reqdate[1] ... and his value with {$form.reqdate.0.value} {$form.reqdate.1.value} ... If you define the element as group. For output a complete group - maybe if you don't know how many elements are in it {$form.reqdate.html} can be used. Yes, it would be possible to preserve elements with names like reqdate[0] from changing (maybe only outside a group), but this make no sense because Smarty not support brakes [] in array keys. You can't access $form['reqdate[0]'] with {$form.reqdate[0]} in an smarty template.
 [2003-11-06 16:38 UTC] avb
In fact IT[X]/Sigma does not support the brackets in placeholder names either, but ITStatic renderer works around this replacing brackets by underscores. Current behaviour looks *extremely* bad, so I suggest fixing it using ITStatic as the example. Side note: ObjectFlexy suffers from the same problem as ArraySmarty. And also from a problem that was fixed in ArraySmarty right before release 3.2. Sigh.
 [2003-11-06 16:40 UTC] avb
Oops, forgot to change the status.
 [2003-11-07 09:30 UTC] ths at php dot net
Ok, i will try to fix it. The current behavior in IT-static is: 'reqdate' --> {form_reqdate_html} 'reqdate[]' --> {form_reqdate__html} 'reqdate[0]' --> {form_reqdate_0_html} 'reqdate[start]' --> {form_reqdate_start_html} For ArraySmarty i would also handle these handmade groups like real Quickform groups by: 'reqdate' --> {$form.reqdate.html} 'reqdate[]' --> {$form.reqdate.html} 'reqdate[0]' --> {$form.reqdate.0.html} 'reqdate[start]' --> {$form.reqdate.start.html} and maybe for the flexy renderer: 'reqdate' --> {form.reqdate.html} 'reqdate[]' --> {form.reqdate.html} 'reqdate[0]' --> {form.reqdate.0.html} 'reqdate[start]' --> {form.reqdate.start.html} Any suggestions?
 [2003-11-07 19:06 UTC] ths at php dot net
Here is an Patch for ArraySmarty. Please feel free to apply it or wait with me for my CVS-account ;-) BTW: I use $mergedArray = Array1 + Array2 to prevent numeric array keys from rearranging... cvs -q diff -u Index: ArraySmarty.php =================================================================== RCS file: /repository/pear/HTML_QuickForm/QuickForm/Renderer/ArraySmarty.php,v retrieving revision 1.3 diff -u -r1.3 ArraySmarty.php --- ArraySmarty.php 4 Nov 2003 10:53:03 -0000 1.3 +++ ArraySmarty.php 7 Nov 2003 23:58:37 -0000 @@ -166,10 +166,22 @@ // create a simple element key $ret['key'] = $ret['name']; if (strstr($ret['key'], '[')) { - preg_match('/\\[([^]]*)\\]/', $ret['key'], $matches); - $ret['key'] = $matches[1]; - if (empty($ret['key'])) { - $ret['key'] = $this->_groupElementIdx++; + preg_match('/([^]]*)\\[([^]]*)\\]/', $ret['key'], $matches); + // pseudo group element + if (empty($this->_currentGroup)) { + if ($matches[2] != '') { + $newret['key'] = $matches[1]; + $newret[$matches[2]] = $ret; + $ret = $newret; + } else { + $ret['key'] = $matches[1]; + } + // real group element + } else { + $ret['key'] = $matches[2]; + if (empty($ret['key'])) { + $ret['key'] = $this->_groupElementIdx++; + } } } elseif (empty($ret['key'])) { $ret['key'] = 'element_' . $this->_elementIdx; @@ -194,7 +206,11 @@ if (is_array($this->_currentGroup) && ('group' != $elAry['type'])) { $this->_currentGroup[$key] = $elAry; } else { - $this->_ary[$key] = $elAry; + if (isset($this->_ary[$key])) { + $this->_ary[$key] = $this->_ary[$key] + $elAry; + } else { + $this->_ary[$key] = $elAry; + } } }
 [2003-11-13 09:28 UTC] avb
Tried applying the patch. The solution does not "scale", which means that if I add the element like 'foobar[0][0]', then the array is not generated properly. I think you'll need some eval() Black Magik or recursive function call to process such names properly.
 [2004-01-04 12:09 UTC] ths at php dot net
This bug has been fixed in CVS. In case this was a documentation problem, the fix will show up at the end of next Sunday (CET) on In case this was a website problem, the change will show up on the website in short time. Thank you for the report, and for helping us make PEAR better. Final fix. The solution now "scale" and should handle any mix of element and group names like element[1][aaa].