PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Tuesday, January 11, 2022

[FIXED] Cakephp 3 - How to integrate external sources in table?

 January 11, 2022     cakephp, cakephp-3.0, data-retrieval, ldap     No comments   

Issue

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).

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();
}

I'm not sure how to approach this.

Where should I place the code in the table object to allow integration with the external API?

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.


Solution

The most simple solution would be to use a result formatter to fetch and inject the external data.

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;
            });
        });

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.

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);

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(/* ... */);
}

Then you can just do $this->Articles->find('withUsers'), just as simple as containing.

See also

  • Cookbook > Database Access & ORM > Query Builder > Adding Calculated Fields
  • Cookbook > Database Access & ORM > Retrieving Data & Results Sets > Custom Finder Methods


Answered By - ndm
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home
View mobile version

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing