我的CakePHP应用程序中有2个基本模型:用户和登录。用户与登录具有hasMany关系(即,每次用户登录时都会创建新的登录记录)。
现在,我想从User模型到Login模型建立2个关系: 用户有很多登录 和 用户hasOne lastLogin
此最后一个关系应仅包括所选用户的登录模型的最后一条记录。
我尝试了如下:
var $belongsTo = array
(
'LastLogin' => array
(
'className' => 'Login',
'order' => 'LastLogin.created DESC',
'limit' => 1
)
);
然而,这不起作用。关于如何使这个工作的任何想法?
答案 0 :(得分:1)
对评论作出回应的最新答案
如果关系为belongsTo
,则外键应位于当前模型中。
这意味着如果您想要将User属于LastLogin的关系,users
表应该有一个last_login_id
字段。
在您的情况下,您可能希望使用hasOne关系,而您将不得不在MAX()
键中使用fields
SQL函数。请注意,获取last_login完全独立于用户hasMany登录关系。因此,如果你想要的只是最后一次登录,你可以删除hasMany关系并离开hasOne。
使用下面的示例代码,您将获得:
输出/ users / index:
Array
(
[User] => Array
(
[id] => 1
[name] => user1
[last_login] => 2011-05-01 14:00:00
)
[Login] => Array
(
[0] => Array
(
[id] => 1
[user_id] => 1
[created] => 2011-05-01 12:00:00
)
[1] => Array
(
[id] => 2
[user_id] => 1
[created] => 2011-05-01 13:00:00
)
[2] => Array
(
[id] => 3
[user_id] => 1
[created] => 2011-05-01 14:00:00
)
)
)
如果你不使用Model :: afterFind()回调,你的结果看起来会更像这样(破解登录数组以节省空间):
Array
(
[User] => Array
(
[id] => 1
[name] => user1
)
[0] => Array
(
[last_login] => 2011-05-01 14:00:00
)
)
<小时/> 示例代码:
用户表:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
)
登录表:
CREATE TABLE `logins` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
)
用户模型:
class User extends AppModel {
var $name = 'User';
var $hasMany = array('Login');
var $hasOne = array(
'LastLogin' => array(
'className' => 'Login',
'fields' => array('MAX(LastLogin.created) as last_login')
)
);
// This takes the last_login field from the [0] keyed array and puts it into
// [User]. You could also put this into your AppModel and it would work for
// all find operations where you use an SQL function in the 'fields' key.
function afterFind($results, $primary=false) {
if (!empty($results)) {
foreach ($results as $i => $result) {
if (!empty($result[0])) { // If the [0] key exists in a result...
foreach ($result[0] as $key => $value) { // ...cycle through all its fields...
$results[$i][$this->alias][$key] = $value; // ...move them to the main result...
}
unset($results[$i][0]); // ...and finally remove the [0] array
}
}
}
return parent::afterFind($results, $primary=false); // Don't forget to call the parent::afterFind()
}
}
用户控制器:
class UsersController extends AppController {
var $name = 'Users';
function index() {
$this->autoRender = false;
pr($this->User->find('all'));
}
}
答案 1 :(得分:0)
我有类似的情况但我的是
Product hasMany Price
如果按照Product hasOne CurrentPrice
按顺序排序,我希望将CurrentPrice
created
定义为找到的最高记录。
class User extends AppModel {
var $name = 'User';
var $hasMany = array('Login');
var $hasOne = array(
'LastLogin' => array(
'className' => 'Login',
'order' => 'LastLogin.created DESC'
)
);
如果你考虑一下,创建和id具有相同的含义。所以你也可以按降序使用id。
我假设您的表架构与one建议的mtnorthrop类似。
即
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
)
logins table:
CREATE TABLE `logins` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
)