Cakephp 3-如何在表中集成外部源? [英] Cakephp 3 - How to integrate external sources in table?
问题描述
我正在开发一个具有自己的数据库并从另一个服务获取用户信息的应用程序(在这种情况下,LDAP通过API包).
I working on an application that has its own database and gets user information from another serivce (an LDAP is this case, through an API package).
说我有一个名为 Articles
的表,其中有一列 user_id
.没有 Users
表,而是通过外部API检索一个或一组用户:
Say I have a tables called Articles
, with a column user_id
. There is no Users
table, instead a user or set of users is retrieved through the external API:
$user = LDAPConnector::getUser($user_id);
$users = LDAPConnector::getUsers([1, 2, 5, 6]);
当然,我希望从控制器内部检索数据尽可能地简单,理想情况下仍可以使用以下内容:
Of course I want retrieving data from inside a controller to be as simple as possible, ideally still with something like:
$articles = $this->Articles->find()->contain('Users');
foreach ($articles as $article) {
echo $article->user->getFullname();
}
我不确定该如何处理.
我应该在哪里将代码放在表对象中以允许与外部API集成?
还有一个额外的问题:在填充实体时如何减少LDAP查询的数量?
也就是说,通过反复使用单个-> getUsers()
检索相关用户并稍后放置它们,似乎速度要快得多,即使遍历文章并使用多个->getUser()
可能更简单.
And as a bonus question: How to minimise the number of LDAP queries when filling the Entities?
i.e. it seems to be a lot faster by first retrieving the relevant users with a single ->getUsers()
and placing them later, even though iterating over the articles and using multiple ->getUser()
might be simpler.
推荐答案
最简单的解决方案是使用结果格式化程序来获取和注入外部数据.
The most simple solution would be to use a result formatter to fetch and inject the external data.
更复杂的解决方案是自定义关联和自定义关联加载器,但是考虑到以数据库为中心的关联如何,您可能还必须提供一个表以及一个可能用于处理LDAP数据源的查询实现.将其移动到自定义关联中相当简单,但包含该关联将查找匹配表,导致检查架构等.
The more sophisticated solution would a custom association, and a custom association loader, but given how database-centric associations are, you'd probably also have to come up with a table and possibly a query implementation that handles your LDAP datasource. While it would be rather simple to move this into a custom association, containing the association will look up a matching table, cause the schema to be inspected, etc.
因此,我将坚持为第一个选项提供示例.结果格式化程序将非常简单,如下所示:
So I'll stick with providing an example for the first option. A result formatter would be pretty simple, something like this:
$this->Articles
->find()
->formatResults(function (\Cake\Collection\CollectionInterface $results) {
$userIds = array_unique($results->extract('user_id')->toArray());
$users = LDAPConnector::getUsers($userIds);
$usersMap = collection($users)->indexBy('id')->toArray();
return $results
->map(function ($article) use ($usersMap) {
if (isset($usersMap[$article['user_id']])) {
$article['user'] = $usersMap[$article['user_id']];
}
return $article;
});
});
该示例假设从 LDAPConnector :: getUsers()
返回的数据是关联数组的集合,其键的 id
与用户ID匹配.您必须相应地对此进行调整,具体取决于 LDAPConnector :: getUsers()
返回的内容.
The example makes the assumption that the data returned from LDAPConnector::getUsers()
is a collection of associative arrays, with an id
key that matches the user id. You'd have to adapt this accordingly, depending on what exactly LDAPConnector::getUsers()
returns.
此外,该示例应该是不言自明的,首先获得在查询的文章中找到的唯一的用户ID列表,使用这些ID获得LDAP用户,然后将用户注入到文章中.
That aside, the example should be rather self-explanatory, first obtain a unique list of users IDs found in the queried articles, obtain the LDAP users using those IDs, then inject the users into the articles.
如果您想在结果中包含实体,请根据用户数据创建实体,例如:
If you wanted to have entities in your results, then create entities from the user data, for example like this:
$userData = $usersMap[$article['user_id']];
$article['user'] = new \App\Model\Entity\User($userData);
为获得更好的可重用性,请将格式化程序放入自定义查找器中.在您的 ArticlesTable
类中:
For better reusability, put the formatter in a custom finder. In your ArticlesTable
class:
public function findWithUsers(\Cake\ORM\Query $query, array $options)
{
return $query->formatResults(/* ... */);
}
然后,您只需执行 $ this-> Articles-> find('withUsers')
,即可.
Then you can just do $this->Articles->find('withUsers')
, just as simple as containing.
另请参见
这篇关于Cakephp 3-如何在表中集成外部源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!