【发布时间】:2013-12-03 01:27:17
【问题描述】:
问题简述
我想通过模型 B 的控制器中的 find() 操作从 模型 A 中检索数据,该 HABTM 模型 B 不依赖于广泛的递归。
$this->ModelB->bindModel('hasMany' => array('ModelAsModelBs'));
$this->ModelB->find('all', array('fields' => array('ModelA.*'))); //cond'ts below
我知道执行此操作需要 bindModel(),但我似乎无法访问关联的模型字段(即,不仅是 HABTM 表的字段,还有实际关联的模型 /em>) 没有多重递归。
我突然想到,在模型关系应该如何交互、设计或检索等方面,我可能从根本上误解了一些东西——简而言之,我认识到我可能无法成功的原因是可能不是我应该做的事情,哼。如果是这样,我同样很乐意学习如何做得更好,因为我经常处理非常复杂的模型关系(我主要为学术界和在线课程材料/远程研究进行网络开发)。
具体例子/实际情况
数据库有这些表,id 和你期望的一样:
- 用户
- 课程
- 模块
- 用户课程
- 用户模块
- 课程模块
我尝试执行的模型查询发生在 Users 控制器中,如下所示:
class Users extends AppController {
public function doSomething() {
$hasOne = array( 'hasOne' => array('CoursesModules','UsersModules'));
$this->User->Course->Module->bindModel($hasOne);
$conditions = array('`CoursesModules`.`course_id`' => $courseIds, //this is a known constraint within the app
'NOT' => array('`UsersModules`.`module_id` = `CoursesModules`.`module_id`' ));
$options = array( 'fields' => array('Module', 'Course.*'), // Note the attempt to get Course model information
'conditions' => $conditions,
'recursive' => 0);
$modules = $this->User->Course->Module->find('all', $options);
$this->set(compact('modules'));
}
}
此查询结果:
错误: SQLSTATE[42S02]:找不到基表或视图:1051 Unknown table 'Course'
但我也不能使用bindModel() 将Courses 连接到Modules。这让我觉得很奇怪,因为关联路径是Users->Courses->Modules。我可以将递归提高一个档次,但它会导致需要大量 unbind() 的各种地狱,并且还会提取完全荒谬的数据量。
第二个奇怪的地方是,如果我从字段列表中删除Course.*,上面的查询会执行,但不会像我预期的那样工作;我认为这是正确地要求 CoursesModules 中列出的所有 Modules 也不在 UsersModules 中。此类数据确实存在于我的记录中,但并未由此检索到。
我意识到我可以从 CoursesModules 获取 course_ids,然后再进行一次查找以获取课程模型数据,但那是 a) 不是很像蛋糕,b) 很痛苦,因为我真的很感激拥有访问渲染视图文件中的$modules['Module']['Course']。
任何人都可以在这里指出正确的方向吗?或者,哈哈,上帝保佑,帮我构建这个 MySQL 查询(我都是 MySQL 连接的大拇指)?非常感谢,谢谢!
更新
@Kai:为了建立关系,我设置了我的表并烘焙它们。也许值得注意的是,我对 MySQL 有相当基本的了解,并且通常通过 PhpMyAdmin 完成所有工作。至于生成初始的 Cake 文件,我使用cake bake all,然后在进行过程中进行了修改。表的 SQL 和来自各个模型的 $hasAndBelongsToMany 数组在最后发布。
至于我为什么选择hasOne...我还假设hasMany;使用这种关系总是会从我绑定的表中生成“未找到列”错误(与哪一列无关)。同时,hasOne 的明显错误选择在某种程度上起作用了。
最后,我有一个潜伏的怀疑,这个containable behavior 业务可能是我所追求的,但我并不真正理解它。尽我所能,这是这些模型的上下文以及我尝试执行的各种查询:
我正在为大学教员构建一个程序,该程序基本上可以让教授进行一些在线课程。但是课程作业(即模块)可能在不同的班级(即课程)之间共享,学生可能在任何或所有班级。另一个限制是,学生可以选择她将在给定课程中学习的模块——教授可能会提供五个,他们必须完成其中的任何三个。因此,当学生登录时,我需要能够检索他们尚未完成的模块,并结合他们所参加的课程。
我必须提出大量类似的查询,这些查询或多或少都属于这种性质。就目前而言,我可以通过loadModel() 的各种用途、执行更简单的$this->Model->find()、通过一些foreach 逻辑对结果进行排序、冲洗重复来实现所有这一切(因为这是在最后期限内,所以已经这样做了)。除了烦人之外,我还担心由于我的处理不当,它无法扩展,最后......我讨厌做错事,哈哈。我知道 CakePHP 可以处理我想对我的数据提出的问题,我只是不知道如何提出这些问题(和/或设置数据以便可以提出这样的问题)。
CREATE TABLE IF NOT EXISTS `modules` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`domain_id` int(11) NOT NULL,
`subject_id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`description` text NOT NULL,
`passing_score` int(11) NOT NULL,
`max_attempts` int(11) NOT NULL,
`allow_retry` int(11) NOT NULL,
`running_score` tinyint(1) NOT NULL,
`score_privacy` int(11) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `domain_id` (`domain_id`),
KEY `subject_id` (`subject_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`group_id` int(11) NOT NULL,
`institution_id` int(11) NOT NULL,
`password` varchar(255) NOT NULL,
`firstname` varchar(63) NOT NULL,
`lastname` varchar(63) NOT NULL,
`email` varchar(255) NOT NULL,
`studentno` varchar(31) NOT NULL,
`claimed` tinyint(1) NOT NULL,
`verified` tinyint(1) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `group_id` (`group_id`),
KEY `institution_id` (`institution_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `courses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`institution_id` int(11) NOT NULL,
`coursecode` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`semester` varchar(7) NOT NULL,
`educator_id` int(11) NOT NULL,
`year` year(4) NOT NULL,
`description` text NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`educator_id`), /* educator is an alias of user in some cases */
KEY `institution_id` (`institution_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `users_courses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`course_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`,`course_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `users_modules` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`module_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`,`module_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE IF NOT EXISTS `courses_modules` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`course_id` int(11) NOT NULL,
`module_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `course_id` (`course_id`,`module_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
模型关联
注意:这并不全面——hasOne、hasMany、belongsTo 等。已省略以节省空间;如果需要,我可以发布整个模型。
// from User Model
public $hasAndBelongsToMany = array(
'Course' => array(
'className' => 'Course',
'joinTable' => 'users_courses',
'foreignKey' => 'user_id',
'associationForeignKey' => 'course_id',
'unique' => 'keepExisting',
),
'Module' => array(
'className' => 'Module',
'joinTable' => 'users_modules',
'foreignKey' => 'user_id',
'associationForeignKey' => 'module_id',
'unique' => 'keepExisting',
)
);
// from Course Model
public $hasAndBelongsToMany = array(
'Module' => array(
'className' => 'Module',
'joinTable' => 'courses_modules',
'foreignKey' => 'course_id',
'associationForeignKey' => 'module_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
),
'User' => array(
'className' => 'User',
'joinTable' => 'users_courses',
'foreignKey' => 'course_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
)
);
// from Module Model
public $hasAndBelongsToMany = array(
'Excerpt' => array(
'className' => 'Excerpt',
'joinTable' => 'excerpts_modules',
'foreignKey' => 'module_id',
'associationForeignKey' => 'excerpt_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
),
'Course' => array(
'className' => 'Course',
'joinTable' => 'courses_modules',
'foreignKey' => 'module_id',
'associationForeignKey' => 'course_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
)
);
【问题讨论】:
-
“CoursesModules 中列出的所有 Modules 不在 UsersModules 中” - 你能解释一下你的意思吗请问简单的英文好吗?我是否将其理解为“查找属于课程但没有用户的所有模块”?
-
我的意思是,“查找 Module.id 在 CoursesModules.module_id 中存在但在 UsersModules.module_id 中不存在的所有模块”。
-
“我需要能够检索[学生尚未]完成的模块,在他们所在课程的背景下。” - 这就是我要的!
-
哦,喜欢,普通英文,哈哈。道歉。 :)
-
您是否可以为生成的查询和执行的查询提供日志。
标签: mysql cakephp model has-and-belongs-to-many cakephp-2.4