【问题标题】:How to properly pass multiple lists from controller to view?如何正确地将多个列表从控制器传递到视图?
【发布时间】:2014-04-18 12:37:27
【问题描述】:

这是我的简化问题描述。我有几个包含不同数据的相似列的表:

table_one.id, table_one.name, ..., table_one.foo
table_two.id, table_two.name, ..., table_two.foo

table_one.foo 允许的值为 'a', 'b', 'c',

table_two.foo 允许的值为 'x'、'y'、'z'。

在视图中,我有一个表单,允许在 table_one 和 table_two 中输入多条记录:

$this->Form->input('TableOne.0.foo', array('type' => 'select'));
$this->Form->input('TableOne.1.foo', array('type' => 'select'));
$this->Form->input('TableOne.2.foo', array('type' => 'select'));
...
$this->Form->input('TableTwo.0.foo', array('type' => 'select'));
$this->Form->input('TableTwo.1.foo', array('type' => 'select'));
$this->Form->input('TableTwo.2.foo', array('type' => 'select'));

在控制器中,我构造列表并将它们传递给视图:

$tableOneFooList = array('a', 'b', 'c');
$tableTwoFooList = array('x', 'y', 'z');
$this->set('foo', $tableOneFooList);

问题在于我无法设置第二个 foo 变量并且$tableOneFooList 被填充到所有 6 个选择框中。我可以在控制器中以不同的方式命名列表,但这需要在视图中进行更多工作才能在验证失败后选择正确的值。是否有一种将列表传递给视图的好方法,以便如果表单在提交后未验证,则将保留所选值?也许我不知道一些命名约定?

【问题讨论】:

    标签: cakephp cakephp-2.4


    【解决方案1】:

    据我所知,表单助手魔法无法区分这两个字段,您要么必须单独传递列表,要么使用自定义表单助手。

    使用options 选项

    单独传递列表时,您只需使用options option,如有必要,CakePHP 将根据请求中传递的值自动选择适当的列表条目。

    控制器

    $tableOneFoos = array('a', 'b', 'c');
    $tableTwoFoos = array('x', 'y', 'z');
    $this->set(compact('tableOneFoos', 'tableTwoFoos'));
    

    查看

    $this->Form->input('TableOne.0.foo', array('type' => 'select', 'options' => $tableOneFoos));
    $this->Form->input('TableOne.1.foo', array('type' => 'select', 'options' => $tableOneFoos));
    $this->Form->input('TableOne.2.foo', array('type' => 'select', 'options' => $tableOneFoos));
    
    $this->Form->input('TableTwo.0.foo', array('type' => 'select', 'options' => $tableTwoFoos));
    $this->Form->input('TableTwo.1.foo', array('type' => 'select', 'options' => $tableTwoFoos));
    $this->Form->input('TableTwo.2.foo', array('type' => 'select', 'options' => $tableTwoFoos));
    

    就是这样,在使用提交的数据呈现表单时应该按预期选择值。

    自定义表单助手

    表单助手检查字段名的camelCased plurals 变量名(请参阅FormHelper::_optionsOptions()),不考虑模型名称,因此在您的情况下它将查找foos,那就是为什么你以这个列表结束所有输入。

    您可以覆盖该方法并实施使用模型名称的附加检查,以便帮助程序查找 tableOneFoostableTwoFoos 等变量。

    这是一个未经测试的!示例:

    App::uses('FormHelper', 'View/Helper');
    
    class MyFormHelper extends FormHelper {
        protected function _optionsOptions($options) {
            $options = parent::_optionsOptions($options);
            
            if (!isset($options['options'])) {
                // this is where the magic happens, an entity name like
                // `Model_field` is turned into a variable name like
                // `modelFields` which is then used to lookup the view vars.
                $entityName = $this->model() . '_' . $this->field();
                $varName = Inflector::variable(
                    Inflector::pluralize(preg_replace('/_id$/', '', $entityName))
                );
                $varOptions = $this->_View->get($varName);
    
                if (is_array($varOptions)) {
                    if ($options['type'] !== 'radio') {
                        $options['type'] = 'select';
                    }
                    $options['options'] = $varOptions;
                }
            }
    
            return $options;
        }
    }
    

    然后您可以将tableOneFoostableTwoFoos 传递给视图,而不使用optionstype 选项作为输入:

    控制器

    $tableOneFoos = array('a', 'b', 'c');
    $tableTwoFoos = array('x', 'y', 'z');
    $this->set(compact('tableOneFoos', 'tableTwoFoos'));
    

    查看

    $this->MyForm->input('TableOne.0.foo');
    $this->MyForm->input('TableOne.1.foo');
    $this->MyForm->input('TableOne.2.foo');
    
    $this->MyForm->input('TableTwo.0.foo');
    $this->MyForm->input('TableTwo.1.foo');
    $this->MyForm->input('TableTwo.2.foo');
    

    只要没有以 HABTM 方式使用的 TableOneFooTableTwoFoo 模型,这应该可以工作,因为它们的字段最终会使用相同的变量名称,即 tableOneFoostableTwoFoos

    【讨论】:

    • 顺便说一下,它也适用于像$this->MyForm->input('TableOne.foo');这样的单个输入
    【解决方案2】:

    我们不要让这个复杂——简单的解决方案是——

    <?php
    $tableOneFooList = array('a', 'b', 'c');
    $tableTwoFooList = array('x', 'y', 'z');
    
    echo $this->Form->create();
    echo $this->Form->input('TableOne.0.foo', array('type' => 'select', 'options' => $tableOneFooList));
    echo $this->Form->input('TableOne.1.foo', array('type' => 'select', 'options' => $tableOneFooList));
    echo $this->Form->input('TableOne.2.foo', array('type' => 'select', 'options' => $tableOneFooList));
    echo $this->Form->input('TableTwo.0.foo', array('type' => 'select', 'options' => $tableTwoFooList));
    echo $this->Form->input('TableTwo.1.foo', array('type' => 'select', 'options' => $tableTwoFooList));
    echo $this->Form->input('TableTwo.2.foo', array('type' => 'select', 'options' => $tableTwoFooList));
    echo $this->Form->end('Submit');
    ?>
    

    【讨论】:

    • 不幸的是,它虽然简单但很麻烦。我需要设置选项的地方太多了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    • 2014-02-21
    相关资源
    最近更新 更多