如何基于另一个hasMany表创建虚拟字段

时间:2014-07-14 15:17:39

标签: php postgresql cakephp virtual

这是与this one非常相似的问题,但表之间的关系不同。

我有3个表:usersnotificationsuser_notificationsuser_notifications是用户和通知之间的连接表,表示已发送给用户的通知实例。

关系如下:

User => hasMany   => UserNotification
UserNotification => belong to => User, Notification  
Notification => hasMany => UserNotification

列如下:     用户=> id,名称
    UserNotification => id,user_id,notification_id     通知=> id,消息

我想创建一个名为Notification.users的虚拟字段,它只包含已发送该特定通知的所有用户的字符串列表,例如:

User => id = 1, name = Bob
User => id = 2, name = Bill

UserNotification => id = 1, user_id = 1, notification_id = 1
UserNotification => id = 2, user_id = 2, notification_id = 1

Notification => id = 1, message = "Hello World!"

通知1,“Hello World!”已经发送给用户1和2,鲍勃和比尔。因此,虚拟字段Notification.users包含这两个名称的逗号分隔列表,我看到了:

Notification => id = 1, message = "Hello World!", users = "Bob,Bill"

1 个答案:

答案 0 :(得分:0)

最终为我工作的代码是:

class Notification extends AppModel
{
    public $virtualFields = array(
        "users" => "SELECT string_agg(users.name, ',') FROM users where users.id IN (SELECT user_notifications.user_id FROM user_notifications where user_notifications.notification_id = Notification.id)"
);

string_agg()使用提供的可选分隔符将所选列聚合为字符串。我最初遇到的一个问题是其他表的CakePHP别名(“User”,“UserNotification”)的用户;这导致“table not provided”错误,所以我使用了实际的数据库表名。默认情况下,值不按特定顺序馈送到string_agg(),这可能会导致字符串混乱。 string_agg()支持order by子句来解决此问题,如下所示(请注意分隔符','和order by子句之间缺少逗号):

class Notification extends AppModel
{
    public $virtualFields = array(
        "users" => "SELECT string_agg(users.name, ',' ORDER BY users.name) FROM users where users.id IN (SELECT user_notifications.user_id FROM user_notifications where user_notifications.notification_id = Notification.id)"
);

这对我来说似乎是最简单的解决方案。有更优雅或更正确的吗?