###What happened:
When using nested documents with MongoDB, you can create fields using the form helper to save data in a nested document. However, when editing, the form helper doesn't pull the data out of the nested document correctly.
Example:
{{{
<?=$this->form->field('loc[lat]', array('label'=>'Latitude'));?>
}}}
###What was expected:
The field should display the value inside the nested document... in this case $obj->loc->lat;
###Example Fix:
This code is a bit ugly, but it works even for multiple objects nested multiple times.
Modify lithium\template\helper\Form.php
Change:
{{{
$hasValue = (
(!isset($options['value']) || $options['value'] === null) &&
$name && $this->_binding && $value = $this->_binding->data($name)
);
}}}
To:
{{{
if(stristr($name,']') != FALSE && (!isset($options['value']) || $options['value'] === null) && $this->_binding)
{
$nameParts = explode(".",str_replace(array('[',']'),array('.',''), $name));
$value = null;
foreach($nameParts as $namePart)
{
if(is_null($value)){
$hasValue = $value = $this->_binding->data($namePart);
}
else
{
$hasValue = $value = $value[$namePart];
}
}
}
else
{
$hasValue = (
(!isset($options['value']) || $options['value'] === null) &&
$name && $this->_binding && $value = $this->_binding->data($name)
);
}
}}}
Hi! The case SeyelentEco describes is actually not covered by the test case. The test case tests form::text() but not form::field(), which fails with dot syntax. Here is a failing test: {{{ $doc = new Document(array('data' => array('foo' => array('bar' => 'value')))); $this->form->create($doc); $result = $this->form->field('foo.bar'); $this->assertTags($result, array( 'div' => array(), 'label' => array('for' => 'FooBar'), 'Foo[bar]', '/label', 'input' => array('type' => 'text', 'name' => 'foo[bar]', 'id' => 'FooBar', 'value' => 'value'), )); }}}Hi. Since this update we got errors with nested documents: ###What happened: We have Customers and Attachments (fs.file) as Models. We store/mirroring some of the attachments model data inside users data. eg: customer.attachment.bill_amount and customer.attachment.data_file ###Description {{{ Catchable fatal error: Object of class lithium\data\entity\Document could not be converted to string in /mnt/nfs/cored-li3/libraries/lithium/template/Helper.php on line 196 }}} i am currently not able to build a test case but this code excerpts might give a hint: template excerpt: {{{ <?=$this->form->field('attachment.'.$fieldId, array( 'type' => 'file', 'label' => $fieldLabel) ); ?> }}} var_dump inside the form helper like so: {{{ /** * Convert a set of options to HTML attributes * * @param array $params * @param string $method * @param array $options * @return string */ protected function _attributes($params, $method = null, array $options = array()) { if (!is_array($params)) { return !$params ? '' : ' ' . $params; } $defaults = array('escape' => true, 'prepend' => ' ', 'append' => ''); $options += $defaults; $result = array(); var_dump($params); foreach ($params as $key => $value) { $result[] = $this->_attribute($key, $value, $options); } return $result ? $options['prepend'] . implode(' ', $result) . $options['append'] : ''; } }}} var_dump: {{{ array(1) { ["class"]=> string(0) "" } array(2) { ["id"]=> string(29) "CustomerAttachmentBillAmounts" ["value"]=> object(lithium\data\entity\Document)#78 (17) { ["_pathKey":protected]=> string(23) "attachment.bill_amounts" ["_relations":protected]=> array(0) { } ["_removed":protected]=> array(0) { } ["_stats":protected]=> array(0) { } ["_valid":protected]=> bool(false) ["_model":protected]=> string(19) "app\models\Customer" ["_data":protected]=> array(5) { ["name"]=> string(0) "" ["type"]=> string(0) "" ["tmp_name"]=> string(0) "" ["error"]=> int(4) ["size"]=> int(0) } ["_relationships":protected]=> array(0) { } ["_parent":protected]=> NULL ["_handle":protected]=> NULL ["_errors":protected]=> array(0) { } ["_updated":protected]=> array(0) { } ["_increment":protected]=> array(0) { } ["_exists":protected]=> bool(true) ["_schema":protected]=> array(0) { } ["_config":protected]=> array(7) { ["model"]=> string(19) "app\models\Customer" ["data"]=> array(5) { ["name"]=> string(0) "" ["type"]=> string(0) "" ["tmp_name"]=> string(0) "" ["error"]=> int(4) ["size"]=> int(0) } ["pathKey"]=> string(23) "attachment.bill_amounts" ["first"]=> bool(true) ["handlers"]=> array(8) { ["id"]=> object(Closure)#17 (1) { ["parameter"]=> array(1) { ["$v"]=> string(10) "<required>" } } ["date"]=> object(Closure)#18 (1) { ["parameter"]=> array(1) { ["$v"]=> string(10) "<required>" } } ["regex"]=> object(Closure)#19 (1) { ["parameter"]=> array(1) { ["$v"]=> string(10) "<required>" } } ["integer"]=> object(Closure)#20 (1) { ["parameter"]=> array(1) { ["$v"]=> string(10) "<required>" } } ["float"]=> object(Closure)#21 (1) { ["parameter"]=> array(1) { ["$v"]=> string(10) "<required>" } } ["boolean"]=> object(Closure)#22 (1) { ["parameter"]=> array(1) { ["$v"]=> string(10) "<required>" } } ["code"]=> object(Closure)#23 (1) { ["parameter"]=> array(1) { ["$v"]=> string(10) "<required>" } } ["binary"]=> object(Closure)#24 (1) { ["parameter"]=> array(1) { ["$v"]=> string(10) "<required>" } } } ["arrays"]=> bool(true) ["init"]=> bool(true) } ["_methodFilters":protected]=> array(0) { } } } }}}Also getting a similar error. Not sure if this is directly related. {{{ Catchable fatal error: Object of class lithium\data\entity\Document could not be converted to string in /Users/norm/Projects/taggs.co/site/libraries/lithium/template/Helper.php on line 198 }}} The combination of using a ```$form->field('upload', array('type' => 'file'))``` with mongo causes this error when form validation fails for another field. ### The solution for me: {{{ $upload = Tagg::create($this->request->data); // Make sure our form validates if(!$upload->validates()){ Session::write('error', 'Correct the errors below.'); unset($upload->upload); // Remove the uploaded file field - stops error return compact('upload'); } }}}