在我的用户模型中,我有以下关系:
public $hasAndBelongsToMany = array(
'User'=>array(
'className' => 'User',
'joinTable' => 'friends',
'with' => 'Friend',
'foreignKey' => 'user_id',
'associationForeignKey' => 'friend_id'
)
);
将用户作为朋友链接到用户。但是,当我对单个用户执行某些操作(如更改密码或编辑用户详细信息(与朋友无关))时,它将开始在friends表中执行操作,例如删除所有现有记录,然后添加空行数据。
我是否设置了错误的关系?如果命名不同,那么当我处理$this->User
时,它不会触及朋友吗?
编辑:自发布此问题以来,我已将user_id和friend_id更改为user1_id和user2_id,以防止Cake对字段执行任何自动化,假设它们是主键或nIcO下面解释的任何内容。但同样的问题仍然存在!
答案 0 :(得分:2)
我强烈建议您使用真正的Friends模型。设置如下:
User hasMany FriendList
User hasMany FriendOf (alias of FriendList)
FriendList belongsTo User
FriendList belongsTo Friend (alias of User)
示例代码:
Table definitions (skeleton):
users:
id
name
friend_lists:
id
user_id
friend_id
Model Definitions:
class User extends AppModel {
var $hasMany = array(
'FriendList',
'FriendOf' => array(
'className' => 'FriendList',
'foreignKey' => 'friend_id'
)
);
}
class FriendList extends AppModel {
var $belongsTo = array(
'User',
'Friend' => array(
'className' => 'User',
'foreignKey' => 'friend_id'
)
);
}
答案 1 :(得分:0)
您的联接表名为friends
,并使用名为Friend
的模型。通过查看HABTM关系声明,friends
表似乎包含一个名为user_id
的字段和一个名为friend_id
的字段。
在friend_id
表中使用friends
字段就像在user_id
表中有一个users
字段,您可能不会这样做。我猜那个Cake不喜欢它,因为Cake将friend_id
视为指向另一个名为Friend
的模型的外键。
无论如何,在HABTM关系中处理同一个表之间的HABTM并不容易(参见HABTM with self requires 2x the rows in join table?),你应该使用连接模型(参见http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasmany-through-the-join-model)
答案 2 :(得分:0)
不要创建与hasAndBelongsToMany关系中使用的别名/名称相同的模型。这对我来说只会让CakePHP感到头疼。
例如;
我有一个名为“公司”的模型,HABTM“用户”记录。所以在我的数据库中有一个名为“companyies_users”的表。
您可能很想在公司模型中做类似的事情。
var $hasAndBelongsToMany = array(
'User'=>array('with'=>'CompanyUser')
);
然后创建“CompanyUser”模型,因为您希望在关联中存储额外的数据。
不要这样做。我不知道为什么,但Cake无法预测它什么时候会自动创建一个名为“CompanyUser”的模型,什么时候会实际加载你创建的PHP文件。
最好在您的模型中定义HABTM以使用默认关联,然后从表中创建不同名称的模型,并使用它来处理记录。这可以确保CakePHP还将使用自动生成的模型并正常工作。
因此,在我的示例中,我创建了一个名为“Members”的模型,将“useTable”设置为“companies_users”。
现在我知道当我使用“公司”模型时,CakePHP将正确处理HABTM,如果我需要访问这些连接记录,那么我使用“Members”模型。
使用“with”选项的风险是你永远不知道CakePHP何时会失败,并自动生成模式。在这种情况下,您的回调或行为都不会发生。
编辑:
更直接地回答这个问题。
修改User.php模型文件,以便HABTM使用更多默认值。
public $hasAndBelongsToMany = array('Friend');
确保您没有为连接表定义UserFriend.php模型文件。如果需要修改连接表,请使用具有指向数据库中该表的别名的模型。
答案 3 :(得分:0)
我猜您的问题是由于错误地声明关联造成的。试试这个:
public $hasAndBelongsToMany = array(
'Friend'=>array(
'className' => 'Friend',
'joinTable' => 'friends',
'foreignKey' => 'user_id',
'associationForeignKey' => 'friend_id'
)
);
答案 4 :(得分:0)
实施友谊协会有几种方法,因为友谊中有两个方向。您可以说用户A是用户B的朋友,但用户B是用户A的朋友。
当一个人在数据库中创建友谊时。你必须在连接表中创建两个记录来表示这两个方向的友谊(假设你想要双向)。
这涵盖了方向的概念。
您可能遇到记录消失的问题,因为默认情况下CakePHP会在更新时删除记录的所有连接数据行。看一下HABTM上“独特”选项的描述。
唯一:如果为true(默认值),则在更新记录时,cake会先插入外键表中的现有关系记录,然后再插入新记录。因此,在更新时需要再次传递现有的关联。
这意味着您在更新记录时始终必须包含HABTM数据。否则,这些记录将被删除,并通过传递的内容进行更新。
现在,您可以创建的最基本的友谊设置将涉及两个表。
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `users_users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`friend_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `user` (`user_id`),
KEY `friend` (`friend_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
第一个表'users'将保存我们的用户数据,第二个'users_users'是HABTM连接表。注意名称,它是users_users,因为它正在加入。
您仍需要在CakePHP中创建两个模型。
第一个是User.php,它将描述系统中的用户。我们将主要使用CakePHP中的默认值来实现此功能。所以HABTM只是一行'朋友'。
class User extends AppModel
{
var $name = 'User';
var $hasAndBelongsToMany = array(
'Friend'
);
}
现在,CakePHP会抱怨表users_friends丢失了。我们需要创建一个Friend模型,而不是将它指向users表。
class Friend extends AppModel
{
var $name = 'Friend';
var $useTable = 'users';
}
现在CakePHP将使用users_users表作为连接。 Friend模型现在描述了一个朋友的用户。
了解您必须在两个方向创建朋友非常重要。当您为用户A保存数据时,他/她是用户B的朋友,那么您还必须保存用户B并说他/她是用户A的朋友。否则,只有一个用户将定义友谊。
这里有另一个答案,它定义了使用别名的友谊的双重方向,但我建议不要实现它,因为它为CakePHP添加了额外的SQL查询工作,这可能是您的应用程序可能不需要的。当您阅读用户A的记录时,您只需要知道他们的朋友是谁,但没有其他方法。
您可以创建一个行为,确保在更新用户记录时,友谊会双向进行。那会更有效率。
注意:我的代码示例适用于CakePHP 1.3 ,这是我目前正在使用的,但它应该在2.x中正常工作。
答案 5 :(得分:0)
根据Cakephp HABTM文档,
HABTM数据被视为一套完整的集合,每次都是新数据 关联是在数据库中添加完整的关联行集 被删除并再次创建,所以你总是需要通过整个 用于保存的数据集。
从2.1开始,
您可以设置唯一设置以使keepExisting避免在保存操作期间丢失额外数据。 即,
public $hasAndBelongsToMany = array(
'User' => array(
....
'unique' => 'keepExisting',
....
),
);
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasmany-through