【问题标题】:CakePHP: FormHelper not showing default values from associated modelCakePHP:FormHelper 不显示关联模型的默认值
【发布时间】:2013-11-07 17:46:56
【问题描述】:

我们有两个模型,它们通过具有和属于多 (HABTM) 关系相关:工作、测试。我们能够成功添加/编辑关系(我们知道是因为它们出现在连接表中),但我们无法让现有值出现在视图中。选择/复选框(我们都试过了)总是空的。

以下是模型关系:

//Job.php
public $hasAndBelongsToMany = array (
    'Test' => array (
        'classname' => 'Test', 
        'foreignKey'=>'job_id',
        'joinTable' => 'jobs_tests',
        'associatedForeignKey' => 'test_id'
    )
);

//Test.php
    public $hasAndBelongsToMany = array(
        'Job' => array(
            'className'=> 'Job',
            'joinTable'=>'jobs_tests',
            'foreignKey' => 'test_id',
            'associatedForeignKey'=> 'job_id'
            )

    );

这里是 /view/Jobs/edit.ctp

            echo $this->Form->select('Test', $test_options, array('class'=>'form-control', 'multiple'=>'checkbox'));
//This is always empty (nothing selected/checked). 

我们做错了什么?

更新:

这里是 JobsController 动作:

public function admin_edit( $id=NULL ) {
    $this->layout = 'admin';
    if (!$id)
        $this->redirect( array('controller'=>'jobs', 'action'=>'index'));

    $this->loadModel('Company');
    $companies = $this->Company->find('all');
    $company_options = array();
    foreach ($companies as $company) {
        $company_options[ $company['Company']['id'] ] = $company['Company']['name'];
    }
    $this->set('company_options', $company_options);

    $this->loadModel('Test');
    $tests = $this->Test->find('all');
    $tests_options = array();
    foreach ($tests as $test) {
        $test_options[ $test['Test']['id'] ] = $test['Test']['name'];
    }
    $this->set('test_options', $test_options);

    $category_options = $this->Job->validCategories;

    $this->set('category_options', $category_options);

    if ($this->request->isPut() ) {
        $data = $this->request->data;
        //debug($data);exit;
        $save = $this->Job->save( $data );
        if ($save) {
            $this->Session->setFlash('Job edited');
            //$job = $this->Job->findById( $id );
        } else {
            $this->Session->setFlash('Error editting job');
        }


    } 

    $job = $this->Job->findById($id);
    $this->request->data = $job;
    $this->set('job', $job);
}

这是 admin_edit.ctp 视图中的表单:

<?php echo $this->Form->create('Job'); ?>
    <fieldset>
        <?php
            echo $this->Form->input('id', array('type'=>'hidden'));
            echo $this->Form->input('name', array('class'=>'form-control')); 
            echo $this->Form->input('email', array('class'=>'form-control'));
            echo $this->Form->input('location', array('class'=>'form-control'));

            echo '<label>Type</label>';
            echo $this->Form->select('type', array('FT'=>'Full Time', 'PT'=>'Part Time', 'IN'=>'Internship'), array('empty'=>false, 'class'=>'form-control'));

            echo '<label>Company</label>';
            echo $this->Form->select('company_id', $company_options, array('class'=>'form-control')); 
            echo $this->Form->input('short_description', array('label' => 'Short Description', 'class'=>'form-control'));
            echo $this->Form->input('full_description', array('type'=>'textarea', 'label' => 'Full Description', 'class'=>'form-control'));
            echo $this->Form->input('is_private', array('label'=>'Is Private?', 'class'=>'form-control') );

            echo '<label>Category</label>';
            echo $this->Form->select('category', $category_options, array('class'=>'form-control'));
            echo '<label>Tests</label>';            
            //echo $this->Form->select('Test.id', $test_options, array('class'=>'form-control', 'multiple'=>true));

            $selected = array();
            foreach ($job['Test'] as $test) {
                $selected[]=$test['id'];
                //$selected[ $test['id'] ] = $test['name'];
            }
            debug($selected);
            echo $this->Form->input('Test', array('type'=>'select', 'options'=>$test_options, 'class'=>'form-control', 'multiple'=>'checkbox', 'selected'=>$selected));
        ?>
    </fieldset>
    <?php echo $this->Form->end(__('Submit')); ?>

【问题讨论】:

  • 附带说明,它是associationForeignKey,而不是associatedForeignKey,但在遵循约定时不必定义这些值,因为CakePHP 会自动选择正确的名称。
  • 除了你让你的生活变得比必要的更复杂的事实之外,如果你总是覆盖它而无法保存表单,那总是会丢失你的输入(这可能是你的问题?提交表单后丢失选择?),我不明白为什么它不应该工作,假设$test_data$selected 确实包含预期的数据。话虽如此,看看它们到底包含什么会很有帮助。
  • @ndm $test_data 的示例:array( (int) 0 =&gt; '5', (int) 1 =&gt; '7' ) 。提交后数据不会丢失。默认/当前选择看起来都很好。只有 HABTM 关联存在问题。
  • 抱歉,我提到了$test_options,而不是$test_data。此外,您似乎正在显示 $selected 的内容,因为根据您的控制器代码,$test_options 应该是 id =&gt; name 格式?
  • @ndm 我也很困惑。我刚刚发送的是 $test_options,但我们也尝试了 key=>value 版本:array( (int) 5 =&gt; 'WSAT Practice', (int) 7 =&gt; 'WSAT-PE' ) ,但也没有用。至于数据被重置的问题......我认为这实际上并没有发生,因为我在视图中调试它并且所有数据都在那里(包括关联)。我错过了什么吗?

标签: php cakephp cakephp-2.0 has-and-belongs-to-many


【解决方案1】:

呸!这是一个难题,但解决方案很简单...... $options['selected'] 中的值是字符串(数字),这让 CakePHP 感到困惑。我们使用intval() 将它们转换为整数,现在它可以完美运行,使用 all 原始设置...

这是视图中的修订版本(注意intval()):

        $selected = array();
        foreach ($job['Test'] as $test) {
            $selected[]= intval($test['id']);
        }
         echo $this->Form->input('Test', array('type'=>'select', 'options'=>$test_options, 'class'=>'form-control', 'multiple'=>'checkbox', 'selected'=>$selected));

另外,作为旁注,这证明几乎所有在上述 cmets 中受到挑战的东西都可以正常工作:

  1. $options['selected'] 不需要必须是键=>值对。
  2. 我们使用的模式不会覆盖 request->data 并将数据传递给表单助手。
  3. 传递给视图 ($some_variable_name) 的非camelCased 变量名称仍被表单助手正确拾取。

希望这对其他人有用。

【讨论】:

  • 1. 没有人说会这样,当然是选项数据需要采用key =&gt; value格式。 2.$this-&gt;request-&gt;data = $job;执行,如果无法保存数据,您将丢失输入,因为它会被从数据库中获取的数据覆盖。 3. 没有人试图证明相反... i>自动提取属于hasMany/HABTM关联模型的视图变量需要正确的驼峰式复数变量名。
  • 不是所有的,但其中的一些,是的。您将视图变量显式传递给 Form 助手,在您的情况下这是必要的,因为它不会自动拾取它,因为这需要遵循上述命名约定。
  • @ndm 我有兴趣尝试一下,而无需手动传递 $options['selected']。你能告诉我一个允许这样做的sn-p吗?
  • 检查我以前的 cmets,我已经链接到解释它如何工作的文档,还有一个示例(它只是两行代码,一个在控制器中,一个在视图中):@ 987654321@
【解决方案2】:

如果你通过使用 Model::find('list') 设置默认值会怎样。

//controller
$this->set('test_options', $this->YourModel->find('list'));


//view
 echo $this->Form->select('Test', $test_options, array('class'=>'form-control', 'multiple'=>'checkbox'));

【讨论】:

  • 是的。这会起作用,但感觉有点“模拟”。除了手动设置默认值的麻烦之外,我担心这意味着我们的模型关联有问题。 PS:我认为您错过了代码中的 'values'=>... 数组。
  • @Emerson 这并没有错,实际上您必须将值传递给视图,CakePHP 不会自动为您执行此操作。但是这样做时,您应该遵守约定,这意味着,将值设置为具有小写复数模型名称的变量,即tests,并使用FormHelper::input(),这样表单助手可以获取数据并自动检查必要的值。见book.cakephp.org/2.0/en/models/…
  • @GuillemoMansilla 您可能需要相应地更新您的答案。
  • 我编辑了代码,谢谢。 @Emerson 如果您不手动设置默认值,而是按照我告诉您的方式保持 find 调用,该怎么办?
  • @GuillemoMansilla 我还没有尝试过find('list'),但我确实尝试将 Test.id(s) 粘贴到 $test_options 数组中并设置 'default'=&gt;$test_options 但这没有用任何一个。另外,我对您所说的总是必须手动设置默认值感到困惑。这不是真的。我们不会在表单的其他任何地方手动设置默认值,它工作正常。 CakePHP 查看$this-&gt;request-&gt;default() 并填充
猜你喜欢
  • 2021-04-06
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 2021-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多