请注意user
并且role
是数据库保留字。
只需通过一个查询询问数据库您想要什么:
SELECT
my_user.id
my_user.name,
array_agg(my_role) AS "roles",
array_agg(permission) AS "permissions"
FROM
"user" my_user
LEFT JOIN user_permission up ON my_user.id = up.user_id
LEFT JOIN permission ON up.permission_id = permission.id
LEFT JOIN user_role ur ON user.id = ur.user_id
LEFT JOIN "role" my_role ON my_role.id = ur.role_id
你会得到一个丑陋的字符串,其中包含 dobule 转义的对象到数组中。使用Pomm层将允许您使用转换器直接从此查询中获取 PHP 对象数组。
<?php
public function getUserPermissionsAndRoles($user_id)
{
$sql = <<<SQL
SELECT
:user_fields_as_my_user,
array_agg(my_role) AS "roles",
array_agg(permission) AS "permissions"
FROM
":user_table" my_user
LEFT JOIN :user_permission_table up ON my_user.id = up.user_id
LEFT JOIN :permission_table ON up.permission_id = permission.id
LEFT JOIN :user_role_table ur ON user.id = ur.user_id
LEFT JOIN ":role_table" my_role ON my_role.id = ur.role_id
WHERE
my_user.id = ?
SQL;
$sql = strtr($sql, array(
":user_fields_as_my_user" => $this->formatFieldsWithAlias('getSelectFields', 'my_user'),
":user_table" => $this->getTableName(),
":user_permission_table" => $this->getConnection()->getMapFor("\Db\App\UserPermission")->getTableName(),
":permission_table" => $this->getConnection()->getMapFor("\Db\App\Permission")->getTableName(),
":user_role_table" => $this->getConnection()->getMapFor("\Db\App\UserRole")->getTableName(),
":role_table" => $this->getConnection()->getMapFor("\Db\App\Role")->getTableName(),
));
return $this->query($sql, array($user_id));
}
为了告诉 Pomm 它可以是 user_role、user_permission、permission 和 role 数据库对象的转换器,在实例化您的数据库时,添加以下内容:
$database = new \Pomm\Database(array("dsn" => "pgsql://user:pass@host:port/db_name", "name" => "app"));
$cnct = $database->getConnection();
$database
->registerConverter('UserPermission', new \Pomm\Converter\PgEntity($cnct->getMapFor('\Db\App\UserPermission')), array('user_permission'))
->registerConverter('Permission', new \Pomm\Converter\PgEntity($cnct->getMapFor('\Db\App\Permission')), array('permission'))
->registerConverter('UserRole', new \Pomm\Converter\PgEntity($cnct->getMapFor('\Db\App\UserRole')), array('user_role'))
->registerConverter('Role', new \Pomm\Converter\PgEntity($cnct->getMapFor('\Db\App\Role')), array('role'))
;
现在数据库知道可以使用这些转换器,但必须知道何时解析名为“roles”和“permissions”的结果字段,它必须将它们作为实体UserMap
数组处理。这就是类的功能所代表的含义:Role
Permission
initialize()
UserMap
<?php
class UserMap extends \Db\App\Base\UserMap
{
public function initialize()
{
parent::initialize();
$this->addVirtualField('roles', 'Role[]');
$this->addVirtualField('permissions', 'Permission[]');
}
现在,在您的控制器中,您只需调用模型的方法并将其转换为 JSON 响应:
<?php
$database = new \Pomm\Database(array("dsn" => "pgsql://user:pass@host:port/db_name", "name" => "app"));
$cnct = $database->getConnection();
$database
->registerConverter('UserPermission', new \Pomm\Converter\PgEntity($cnct->getMapFor('\Db\App\UserPermission')), array('user_permission'))
->registerConverter('Permission', new \Pomm\Converter\PgEntity($cnct->getMapFor('\Db\App\Permission')), array('permission'))
->registerConverter('UserRole', new \Pomm\Converter\PgEntity($cnct->getMapFor('\Db\App\UserRole')), array('user_role'))
->registerConverter('Role', new \Pomm\Converter\PgEntity($cnct->getMapFor('\Db\App\Role')), array('role'))
;
$collection = $cnct->getMapFor('\Db\App\User')
->getUserPermissionsAndRoles($_GET['user_id']) // <- get an iterator over fetched users with extra info.
;
echo json_encode($collection->extract()); // <- dump an array from the iterator and cast it to json.
当然,纯 PHP 部分使用像Silex这样的微框架会更容易,您的控制器将是:
<?php //...
$app->get('/user/{user_id}', function($user_id) use ($app) {
$collection = $app['pomm.connection']
->getMapFor('\Db\App\User')
->getUserPermissionsAndRoles($user_id);
if ($collection->count() === 0)
{
$this->abort(404, sprintf("No such user '%s'.", $user_id));
}
return $app->json($collection->extract());
});
干杯!