Cakephp 3 - Как интегрировать внешние источники в таблицу? - PullRequest
0 голосов
/ 04 октября 2019

Я работаю над приложением, которое имеет свою собственную базу данных и получает информацию о пользователях из другой службы (в данном случае LDAP, через пакет API).

Скажем, у меня есть таблицы с именем Articles, сстолбец user_id. Нет таблицы Users, вместо этого пользователь или группа пользователей извлекаются через внешний API:

$user = LDAPConnector::getUser($user_id);
$users = LDAPConnector::getUsers([1, 2, 5, 6]);

Конечно, я хочу, чтобы получение данных из контроллера было как можно более простым, в идеале все ещес чем-то вроде:

$articles = $this->Articles->find()->contain('Users');

foreach ($articles as $article) {
    echo $article->user->getFullname();
}

Я не уверен, как подойти к этому.

Где я должен разместить код в табличном объекте, чтобы позволить интеграцию с внешним API?

И в качестве дополнительного вопроса: Как свести к минимуму количество запросов LDAP при заполнении сущностей?
то есть, кажется, что это намного быстрее, сначала получив соответствующийпользователи с одним ->getUsers() и размещением их позже, даже если перебирать статьи и использовать несколько ->getUser(), может быть проще.

1 Ответ

1 голос
/ 04 октября 2019

Самое простое решение - использовать средство форматирования результатов для извлечения и ввода внешних данных.

Более сложное решение - это пользовательская ассоциация и пользовательский загрузчик ассоциаций, но с учетом того, как ассоциации базируются на базе данных. Возможно, вам также придется придумать таблицу и, возможно, реализацию запроса, которая обрабатывает ваш источник данных LDAP. Хотя было бы довольно просто переместить это в пользовательскую ассоциацию, содержащую ассоциацию, которая будет искать соответствующую таблицу, вызвать проверку схемы и т. Д.

Поэтому я остановлюсь на предоставлении примера дляПервый вариантФорматирование результата будет довольно простым, примерно так:

$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, который соответствуетЛогин пользователя. Вы должны были бы адаптировать это соответственно, в зависимости от того, что именно возвращает LDAPConnector::getUsers().

Кроме того, пример должен быть довольно понятным, сначала получите уникальный список идентификаторов пользователей, найденных в запрашиваемых статьях,получить пользователей LDAP, используя эти идентификаторы, а затем внедрить пользователей в статьи.

Если вы хотите, чтобы в ваших результатах были сущности, то создайте сущности из пользовательских данных, например, так:

$userData = $usersMap[$article['user_id']];
$article['user'] = new \App\Model\Entity\User($userData);

Для лучшего повторного использования поместите форматтер в пользовательский искатель. В вашем ArticlesTable классе:

public function findWithUsers(\Cake\ORM\Query $query, array $options)
{
    return $query->formatResults(/* ... */);
}

Тогда вы можете просто сделать $this->Articles->find('withUsers'), так же просто, как содержать.

См. Также

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...