Reputation: 1680
Hi this has been going around a little but hopefully I can get some light shone on the problem. Basically I would like to do a search in my active directory using ldap and paginate the results.
I've seen code like this around but it doesn't make any sense to me
// $ds is a valid link identifier (see ldap_connect)
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
$dn = 'ou=example,dc=org';
$filter = '(|(sn=Doe*)(givenname=John*))';
$justthese = array('ou', 'sn', 'givenname', 'mail');
// enable pagination with a page size of 100.
$pageSize = 100;
$cookie = '';
do {
ldap_control_paged_result($ds, $pageSize, true, $cookie);
$result = ldap_search($ds, $dn, $filter, $justthese);
$entries = ldap_get_entries($ds, $result);
foreach ($entries as $e) {
echo $e['dn'] . PHP_EOL;
}
ldap_control_paged_result_response($ds, $result, $cookie);
} while($cookie !== null && $cookie != '');
What does this actually do? What is the cookie all about?
I could replace
$result = ldap_search($ds, $dn, $filter, $justthese);
with
$result = ldap_search($ds, $dn, $filter, $justthese,0,100);
Which would do with filter and get me the first 100 rows.
The question in hand is how do I control ldap pagination successfully. i.e giving the number of results to return and the page that I want them from.
Update
Right the code above, I've given it a run and what it does is run the search, several times - returning in each iteration a new page until the end. So it seems that the cookie has some control over that.
Upvotes: 3
Views: 3910
Reputation: 3861
The cookie holds an internal pointer (a ressource) to the currently returned part of the result set. So for the server to know where to continue you have to provide the pointer back as parameter. ThaT is at least currently the case but there are thoughts of changing that. I'll have to do some digging to find the current status of that.
Your second idea of setting the number of returned items to 100 will return the same results over and over again as it sets the maximum number of values that the server will return for each request.
You will have to be carefull with sorting though! currently there is only ldap_sort (which is deprecated as of PHP 7) which sorts the resultset on clientside. But as the pagination is done on the serverside and there currently is no way of doing serversided sorting (we are working on that) the result will not be what you might expect.
Upvotes: 2
Reputation: 1680
Right, I think the answers are this.
a) The $cookie
parameter, is an internal thing to do with searching and pagination, you can't edit/control this (or at least I can't find how).
b) The reason to use the code above is if your server has some restrictions on the amount of users ldap can return.
c) If you do use the code above you might want to search, you can't use ldap_sort
because this just sorts each page.
d) So that leads you into creating an array and then using a php function e.g asort
to sort the array, then to get your page use array_splice
So the solution into ldap pagination is to use some code like this
$filter = "(&(displayName=*".ldap_escape('r')."*)(samaccountname=*)(givenname=*)(sn=*)(lastlogontimestamp=*))";
$justthese = array('ou', 'sn', 'givenname', 'mail');
$sr = ldap_search($conn['connect'], $conn['base_dn'], $filter, $justthese);
ldap_sort ( $conn['connect'], $sr, 'givenname' ) ;
$info = ldap_get_entries($conn['connect'], $sr);
$offset = $page_number*$number;
$length = $number;
unset($info['count']);
$info = array_slice ($info, $offset ,$length);
echo '<pre>';
print_r($info);
echo '</pre>';
Just one more thing the ldap_sort, looks a little rubbish because it's case sensitive. I guess you can write your own after you have the results, if it's not your cup of tea. Update - if there is a lot of results this isn't workable, also with the order you are prob best using something like array_reverse
So they you go, not great but workable. Other solutions to try and improve on this is when a search happens query ldap, store the results in a sql table. Let the user manipulate the results (sort/pagination) using the sql table. Each search gets a new set of results for the table. Then you get the speed of the sql table and the benefit of it's sorting/pagination, but the inserting will cost you.
So no great solutions, just a few ideas that kinda work. Hope it helps someone.
Upvotes: 1