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

Php 如何基于另一个hasMany表创建虚拟字段,php,postgresql,cakephp,virtual,Php,Postgresql,Cakephp,Virtual,这是一个与非常类似的问题,但表之间的关系不同 我有3个表:用户,通知,和用户通知user\u notifications是用户和通知之间的联接表,表示已发送给用户的通知的实例 关系如下: User => hasMany => UserNotification UserNotification => belong to => User, Notification Notification => hasMany => UserNotification 各

这是一个与非常类似的问题,但表之间的关系不同

我有3个表:
用户
通知
,和
用户通知
user\u notifications
是用户和通知之间的联接表,表示已发送给用户的通知的实例

关系如下:

User => hasMany   => UserNotification
UserNotification => belong to => User, Notification  
Notification => hasMany => UserNotification
各栏如下: 用户=>id,名称
UserNotification=>id,user\u id,notification\u 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“HelloWorld!”已经发送给用户1和2、Bob和Bill。因此,虚拟字段
Notification.users
包含以逗号分隔的两个名称列表,我看到:

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

最终对我有效的代码是:

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)"
);
使用提供的可选分隔符将选定列聚合为字符串。一开始我遇到的一个问题是其他表的CakePHP别名(“user”、“UserNotification”)的用户;这会导致“表未提供”错误,因此我使用了实际的数据库表名。默认情况下,值不会按特定顺序馈送到
string\u 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)"
);