使用CakePHP表单创建拥有并且属于许多现有课程的用户

时间:2015-06-29 15:33:21

标签: php cakephp

我有一个带有两个关联模型的应用程序:用户和课程,它们与HABTM协会相关。

有一个注册表单,新用户可以输入用户名并选择他们所属的课程(从数据库中的现有课程列表中),只有表单只保存新用户 - 它不会将任何内容保存到连接表中。

联接表(courses_users)包含course_id列和user_id列,两个模型如下所示:

// User.php
class User extends AppModel {
    public $name = 'User';

    public $hasAndBelongsToMany = array(
        'Courses' => array(
            'className' => 'Course',
            'joinTable' => 'courses_users',
            'foreignKey' => 'user_id',
            'associatedForeignKey' => 'course_id'
        )
    );
}

// Course.php
class Course extends AppModel {
    public $name = 'Course';

    public $hasAndBelongsToMany = array(
        'Users' => array(
            'className' => 'User',
            'joinTable' => 'courses_users',
            'foreignKey' => 'course_id',
            'associatedForeignKey' => 'user_id'
        )
    );
}

此外,这是控制器操作:

// IdentificationController.php
public function register() {
    if ($this->request->is('POST')) {
        $data = $this->request->data;
        $username = $data['User']['username'];

        $saved = $this->User->save($data, array('deep' => true));
        //debug($data);

        if ($saved) {
            $this->_set_new_user_session($username);

            //$log = $this->User->getDataSource()->getLog(false, false);
            //debug($log);

            $this->redirect(array('controller' => 'users', 'action' => 'index'));
        }
    }

    // Not redirecting
    $courses = $this->Course->find('list', array('Course.name'));
    //debug($courses);
    $this->set(compact('courses'));
}

这是形式,没有容器div:

<?php
echo $this->Form->create('User', array(
    'inputDefaults' => array(
        'label' => false,
        'div' => false
    ),
    'url' => '/identification/register'
));

echo $this->Form->input('username', array(
    'error' => false,
    'autofocus' => true,
    'required' => true,
    'pattern' => '[a-zA-Z0-9]{3,16}'
));

if ($this->Form->isFieldError('username')) {
    echo $this->Form->error('username', null, array('wrap' => 'small', 'class' => 'error'));
}

echo $this->Form->input('Course.Course', array(
    'error' => false,
    'required' => true
));

if ($this->Form->isFieldError('courses')) {
    echo $this->Form->error('course', null, array('wrap' => 'small', 'class' => 'error'));
}

echo $this->Form->button('Register', array(
    'div' => false,
    'type' => 'submit'
));

echo $this->Form->end();
?>

当我调用debug($ data)时,正确的数据似乎从表单传递给控制器​​:

array(
    'User' => array(
        'username' => 'test63apd'
    ),
    'Course' => array(
        'Course' => array(
            (int) 0 => '1'
        )
    )
)

但是连接表没有任何反应,并且DataSource日志中没有提到连接表:

array(
    'log' => array(
        (int) 0 => array(
            'query' => 'BEGIN',
            'params' => array(),
            'affected' => null,
            'numRows' => null,
            'took' => null
        ),
        (int) 1 => array(
            'query' => 'INSERT INTO `xray2`.`users` (`username`) VALUES ('test06apd')',
            'params' => array(),
            'affected' => (int) 1,
            'numRows' => (int) 1,
            'took' => (float) 1
        ),
        (int) 2 => array(
            'query' => 'COMMIT',
            'params' => array(),
            'affected' => (int) 1,
            'numRows' => (int) 1,
            'took' => (float) 1
        )
    ),
    'count' => (int) 3,
    'time' => (float) 2
)

我是否遗漏了一些非常明显的东西,或者是否有一些我尚未发现的蛋糕怪癖?

1 个答案:

答案 0 :(得分:1)

您只是告诉Cake保存主要模型数据。您需要更改此行: -

$saved = $this->User->save($data, array('deep' => true));

要: -

$saved = $this->User->saveAssociated($data, array('deep' => true));

saveAssociated()告诉Cake保存当前模型及其相关数据。您也不需要传递array('deep' => true),因为您只将数据保存到直接关联的模型。所以使用它会更好(也更安全): -

$saved = $this->User->saveAssociated($data);

<强>更新

由于您没有使用关联中为数据定义的别名,因此保存数据存在问题。因此,当Cake尝试保存关联数据时,它无法看到任何数据。根据您的代码,您的User模型拥有并属于许多Courses(复数),但您的保存数据使用Course(单数)。因此,您的表格应为: -

echo $this->Form->input('Courses.Courses', array(
    'error' => false,
    'required' => true
));

应该注意Cake naming conventions使用单数形式的模型名称,因此最好在关联中使用Course而不是Courses。如果您更改此设置,则您的关联可以简化为以下内容: -

public $hasAndBelongsToMany = array(
    'Course'
);

Cake将了解如何处理连接表和外键,因为它们符合命名约定。然后你不需要改变你的表格。