PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

ldap_start_tls> <ldap_set_rebind_proc
Last updated: Sun, 25 Nov 2007

view this page in

ldap_sort

(PHP 4 >= 4.2.0, PHP 5)

ldap_sort — Sort LDAP result entries

Description

bool ldap_sort ( resource $link , resource $result , string $sortfilter )
Warning

Αυτή η συνάρτηση επί του παρόντος δεν είναι τεκμηριωμένη, μόνο ο κατάλογος των argument της είναι διαθέσιμος.



ldap_start_tls> <ldap_set_rebind_proc
Last updated: Sun, 25 Nov 2007
 
add a note add a note User Contributed Notes
ldap_sort
renandelima at gmail dot com
25-Aug-2008 09:40
I was very unhappy because doesn't exists a way to order ldap search results. Above a solution to order a search in ascending and descending order. This function also do pagination.

// descending order
$list = ldap_sort_paginate( $conn, $search, "cn", "desc" );

// ascending order with pagination
$list = ldap_sort_paginate( $conn, $search, "cn", "asc", 3, 15 );

Use http://php.net/ldap_count_entries to calculate the min and max pages values before call this function. The first page value is 0 (zero).

<?php

/**
 * Order a search in ascending and descending order.
 *
 * @param resource from ldap_connect()
 * @param resource from ldap_search()
 * @param string of attribute to order
 * @param string "asc" or "desc"
 * @param integer page number, first is 0 zero
 * @param integer entries per page
 * @return string[]
 */
function ldap_sort_paginate( $rConnection, $rSearch, $sField, $sOrder = "asc", $iPage = null, $iPerPage = null )
{
   
$iTotalEntries = ldap_count_entries( $rConnection, $rSearch );
    if (
$iPage === null || $iPerPage === null )
    {
       
# fetch all in one page
       
$iStart = 0;
       
$iEnd = $iTotalEntries - 1;
    }
    else
    {
       
# calculate range of page
       
$iStart = ( ceil( $iTotalEntries / $iPerPage ) - 1 ) * $iPage;
       
$iEnd = $iStart + $iPerPage - 1;
        if (
$sOrder === "desc" )
        {
           
# revert range
           
$iStart = $iTotalEntries - 1 - $iEnd;
           
$iEnd = $iStart + $iPerPage - 1;
        }
    }
   
var_dump( $iStart . " " . $iEnd );
   
# fetch entries
   
ldap_sort( $rConnection, $rSearch, $sField );
   
$aList = array();
    for (
       
$iCurrent = 0, $rEntry = ldap_first_entry( $rConnection, $rSearch );
       
$iCurrent <= $iEnd && is_resource( $rEntry );
       
$iCurrent++, $rEntry = ldap_next_entry( $rConnection, $rEntry )
    )
    {
        if (
$iCurrent >= $iStart )
        {
           
array_push( $aList, ldap_get_attributes( $rConnection, $rEntry ) );
        }
    }
   
# if order is desc revert page's entries
   
return $sOrder === "desc" ? array_reverse( $aList ) : $aList;
}
anonymous at hotmail dot com
18-Jul-2008 07:24
LDAP does not support sorting by more than one field.  Simply calling ldap_sort() multiple times will not work because the previous order is ignored.

If you want to sort the result by multiple fields, you'll have to do it manually client side.
james at mediatrust dot org
03-Apr-2008 08:53
The syntax for this simple case sensitive sort should be -

$search_return = ldap_search($ldap_connection,$ldap_base,$search_filter);
ldap_sort($ldap_connection,$search_return,"givenname");
$entries = ldap_get_entries($ldap_connection,$search_return);
headley at my-mail dot ch
28-Feb-2008 07:47
I've got extend the functionality of the last code.
Now you can sort the ldap-array with multiple sort-directions.

<?php

/*Scoped global*/
$LDAPSortOrder;

/*$array is the return from ldap_get_entries
   $sortBy is an array of values to sort by in the order in                  
   which to sort them
   Example:
   $sortBy=array('name' => 'ASC','givenname' => 'DESC') ;
*/
function LDAPSort(&$array,$sortBy){
        global
$LDAPSortOrder;
       
       
$LDAPSortOrder = $sortBy;
       
       
usort($array,'ldapcompare');
       
}

/* The compare functions always check case insensitive*/
function ldapcompare($x,$y){
        global
$LDAPSortOrder;
/*
Loops through the items in order until a difference is found
*/
       
foreach($LDAPSortOrder as $ele => $direction){
               
                if(
strtolower($x[$ele][0]) == strtolower($y[$ele][0]))
                        continue;
                else{
                    if(
strtolower($x[$ele][0]) < strtolower($y[$ele][0])){
                        switch(
strtoupper($direction)){
                               case
'ASC': return -1; break;
                            case
'DESC': return 1; break;
                        }
                    }
                       
                    else{
                            switch(
strtoupper($direction)){
                                case
'ASC': return 1; break;
                                case
'DESC': return -1; break;
                            }
                    }
                }
        }
        return
0;
}

?>
tarnishedniteNOSPA(T)MgMAIL
28-Aug-2007 01:30
While bob's sort is nice I found that this one was a little more to my liking. This little library ignores case and sorts on multiple criteria with some fairly short and simple code. I'm sure it could be simplified further - switch statement perhaps.

<?php

/*Scoped global*/
$LDAPSortOrder;

/*$array is the return from ldap_get_entries
   $sortBy is an array of values to sort by in the order in                   
   which to sort them
   $reverse will sort in reverse order if true
*/
function LDAPSort(&$array,$sortBy,$reverse=FALSE){
        global
$LDAPSortOrder;
       
$LDAPSortOrder = $sortBy;
        if(
$reverse){
               
usort($array,'ldapcomparereverse');
        } else {
               
usort($array,'ldapcompare');
        }
}

/* The compare functions always check case insensitive*/
function ldapcompare($x,$y){
        global
$LDAPSortOrder;
/*
Loops through the items in order until a difference is found
*/
       
foreach($LDAPSortOrder as $ele){
                if(
strtolower($x[$ele][0]) == strtolower($y[$ele][0]))
                        continue;
                elseif(
strtolower($x[$ele][0]) < strtolower($y[$ele][0]))
                        return -
1;
                else
                        return
1;
        }
        return
0;
}

/*Just like above but in reverse order*/
function ldapcomparereverse($x,$y){
        global
$LDAPSortOrder;
        foreach(
$LDAPSortOrder as $ele){
                if(
strtolower($x[$ele][0]) == strtolower($y[$ele][0]))
                        continue;
                elseif(
strtolower($x[$ele][0]) < strtolower($y[$ele][0]))
                        return
1;
                else
                        return -
1;
        }
        return
0;
}

?>

JML
nick at lazy(hyphen)river dot net
21-Mar-2007 09:38
I'm not sure if there's a way to make ldap_sort case insensitive, so I'm sticking with Ben's solution with the following amendment.

<?php
...
$a .= strtolower($entries[$j-1][$attrib][0]);
$b .= strtolower($index[$attrib][0]);
...
?>

Hope it's useful.
huntz at huntz dot org
17-May-2005 09:12
About the note of ccblanket at yahoo dot com...

Nice tip, but on line 2 of your example we need to use $ldapSortAttributes and not $ldapSortAttribues :-)

So, the whole correct function is:

<?php
   $ldapFilterAttributes
= array ('givenname', 'sn', 'mail');
  
$ldapSortAttributes = array('sn', 'givenname');
 
  
$ldapFilter = "(&(sn='')(givenname=''))";
 
  
$ldapBaseDN = 'ou=users, dc=example, dc=com';
 
  
$search = @ldap_search($ldapConnect, $ldapBaseDN, $ldapFilter, $ldapFilterAttributes) ;
   if (!(
$search)) {
       die(
"Unable to search LDAP server");
   }

   foreach (
$ldapSortAttributes as $eachSortAttribute) {
       if (
in_array($eachSortAttribute, $ldapFilterAttributes)) {
          
ldap_sort($this->connect, $search, $eachSortAttribute);
       }
   }

  
$results = ldap_get_entries($this->connect, $search);

print_r($results);
?>
ccblanket at yahoo dot com
05-Mar-2005 09:30
It is interesting people are using all these methods to sort multi-attribute results from LDAP searches. Well, here is a simpler one. Just use ldap_sort once for each sort attribute in the reverse order of importance.

--hikmet

<?php
    $ldapFilterAttributes
= array ('givenname', 'sn', 'mail');
   
$ldapSortAttribues = array('sn', 'givenname'); // ie. sort by givenname, then by sn
   
   
$ldapFilter = "(&(sn='')(givenname=''))";
   
   
$ldapBaseDN = 'ou=users, dc=example, dc=com';
   
   
$search = @ldap_search($ldapConnect, $ldapBaseDN, $ldapFilter, $ldapFilterAttributes) ;
    if (!(
$search)) {
        die(
"Unable to search LDAP server");
    }

   
// lets sort the results by firstname if firstname is in the results
   
foreach ($ldapSortAttributes as $eachSortAttribute) {
        if (
in_array($eachSortAttribute, $ldapFilterAttributes)) { // making sure we don't accidentally try to sort against an inexisting field
           
ldap_sort($this->connect, $search, $eachSortAttribute);
        }
    }

   
// and here is the result
   
$results = ldap_get_entries($this->connect, $search);
?>
ben at xsusio dot com
03-Sep-2004 02:33
If you are wanting to sort by multiple attributes, for instance ordering by last name and then first name,  try this function. This is similar to "ORDER BY lastname, firstname"  in SQL.

This function uses an insertion sort algorithm, which is somewhat faster then the old-fashoned bubble sort.  The second argument is an array containing the attributes you want to sort by. (this functon won't do descending or ascending..  feel free to add it!)

<?php
/**
 * @param array $entries
 * @param array $attribs
 * @desc Sort LDAP result entries by multiple attributes.
*/
function ldap_multi_sort(&$entries, $attribs){
    for (
$i=1; $i<$entries['count']; $i++){
       
$index = $entries[$i];
       
$j=$i;
        do {
           
//create comparison variables from attributes:
           
$a = $b = null;
            foreach(
$attribs as $attrib){
               
$a .= $entries[$j-1][$attrib][0];
               
$b .= $index[$attrib][0];
            }
           
// do the comparison
           
if ($a > $b){
               
$is_greater = true;
               
$entries[$j] = $entries[$j-1];
               
$j = $j-1;
            }else{
               
$is_greater = false;
            }
        } while (
$j>0 && $is_greater);
       
       
$entries[$j] = $index;
    }
    return
$entries;
}
?>
zbaizman at yahoo dot com
06-Aug-2004 06:15
This note may be self-evident, but the functionality of ldap_sort threw off this sometime user of relational databases.

The following code will NOT do what you expect:

<?php

// omitted calls to connect and and bind to LDAP server...

// attributes we want to retrieve from LDAP server
$ldap_attributes = array ( 'cn', 'o', 'mail' ) ;

// retrieve attributes from matching entries
$search_results = ldap_search ( $ldap_conn, 'dc=example,dc=org', '(objectclass=*)', 0, 500, 30 ) ;

// sort entries by last name ('sn')
ldap_sort ( $ldap_conn, $search_results, 'sn' ) ;

?>

The entries will NOT be sorted by last name. Why not? Because LDAP doesn't function like a RDBMS; you cannot sort a result set on an arbitrary field, regardless of whether you "selected" it. You must always include the attribute by which you want to sort your entries among the requested attributes (add 'sn' to $ldap_attributes, in this case).

Hope this is helpful to some other folks who scratched their heads when they tried to sort entries and it didn't work out...
helmut dot patay at scandio dot de
21-Apr-2004 03:02
If you want to sort the search results based on any attribute reverse,
please do not use the examples above containing two loops!
You will end up in changing php.ini with increasing the value
of 'max_execution_time' dramatically. No one will use your website
again!
I have used the following construct and it works very well:

// write this function
function myReverseCnCmp( $a, $b ) {
    // Note: $b comes before $a because of reverse ordering
    return strcasecmp( $b[cn][0], $a[cn][0] );
}

// search
$sr = ldap_search( $ds, $baseDn, $filter );

// before reading the entries, you must sort normally
// in my example I use the attribute 'cn' for sorting
// instead of cn you can use any other attribute
ldap_sort( $ds, $sr, "cn" )

// read the entries
$entries = ldap_get_entries( $ds, $sr );

// now sort the array reverse with usort
usort( $entries, "myReverseCnCmp" );

// now $entries is sorted reverse based on "cn"

// This runs at least 5 times faster than the double loop
// solutions

// Note: If you want to sort reverse based on dynamic
// attribute names, you must do some if's or switch'es,
// but it's really fast!
john at benden dot co dot uk
11-Apr-2004 04:30
An alternative for multivalue sorting for ldap queries:

function cmp($a,$b) {
   global $fld1,$fld2,$fld3; // getting the fld defs from the main routine
   global $info; // get search results from the main routine
   $d=strcasecmp($info[$a][$fld1][0],
                        $info[$b][$fld1][0]);
   if ($d==0) {
     $d = strcasecmp($info[$a][$fld2][0],
                             $info[$b][$fld2][0]);
     if ($d==0) {
       $d= strcasecmp($info[$a][$fld3][0],
                             $info[$b][$fld3][0]);
     }
   }
   if ($d==0) {
      return 0;
   } else {
      return ($d>0)? 1 : -1;
   }
}
//
// connect to the directory server
//
$ds=ldap_connect("localhost",389);
ldap_bind($ds,"","");
//
// setup the search
//
$basedn="o=org";
$search="(sn=foo)"
$searchattr=array('sn','givenname','desc','telephonenumber',
'cn','mail');
//
// do the search
//
$sr=ldap_search($ds, $basedn, $search,$searchattr);
//
// verify that the search was ok
//
if (ldap_count_entries($ds,$sr)==0) {
   echo "<BR><H1>No results</H1>";
} else {
   // some results found
   // get the search results
   $info = ldap_get_entries($ds, $sr);
   // setup the sorting fields
   $fld1="sn";
   $fld2="givenname";
   $fld3="desc"; // there maybe a better attribute
   uksort($info,"cmp"); // use a key sort
   //
   // Setup results
   //
   echo "<table><tr><th>Name</th>";
   echo "<th>Phone</th> <th>Mail</th>";
   echo "<th>desc</th> </tr>";
   while (list($i, $value) = each($info)) {
      echo "<tr><td>" . $info[$i]["cn"][0] . "</td><td>";
      echo $info[$i]["telephonenumber"][0] . "</td><td>";
      echo $info[$i]["mail"][0] . "</td><td>";
      echo $info[$i]["desc"][0] . "</td></tr>";
   }
   echo "</table>";
   ldap_free_result($sr);
}

ldap_close($ds);

i hope this helps!
askgopal at sify dot com
04-Sep-2003 08:07
Here's a simple LDAP sort function I wrote:

function sort_ldap_entries($e, $fld, $order)
{
    for ($i = 0; $i < $e['count']; $i++) {
        for ($j = $i; $j < $e['count']; $j++) {
            $d = strcasecmp($e[$i][$fld][0], $e[$j][$fld][0]);
            switch ($order) {
            case 'A':
                if ($d > 0)
                    swap($e, $i, $j);
                break;
            case 'D':
                if ($d < 0)
                    swap($e, $i, $j);
                break;
            }
        }
    }
    return ($e);
}

function swap(&$ary, $i, $j)
{
    $temp = $ary[$i];
    $ary[$i] = $ary[$j];
    $ary[$j] = $temp;
}

so that it can be invoked like:

    $entries = sort_ldap_entries($entries, 'mail', 'A'); // sort entries by ascending order of mail

where,
    `$entries' is the array returned by ldap_get_entries() function.

This might be useful to those who still run older versions of PHP (<= 4.2.0) on their web servers :-)
rieflin at tdontspam dot salem dot k12 dot va dot us
19-Dec-2002 03:58
The note from Sean on 14-Nov-2002 was of great help to me but I had to change one line for it to work.

In the example below, change the line ...
ldap_sort = ($ldap_connection,$search_return,"givenname");
to ldap_sort ($ldap_connection,$search_return,"givenname");
and everything should work fine. 

Sean's code.................
The following is a working example of how to use the ldap_sort function ...

$search_return = ldap_search($ldap_connection,$ldap_base,$search_filter);
ldap_sort = ($ldap_connection,$search_return,"givenname");
$entries = ldap_get_entries($ldap_connection,$search_return);

This will take the returned search sort it by the "givenname" attribute. It has to be done BEFORE you call ldap_get_entries.
sean dot ogrady at sheridanc dot on dot ca
14-Nov-2002 03:04
The following is a working example of how to use the ldap_sort function ...

$search_return = ldap_search($ldap_connection,$ldap_base,$search_filter);
ldap_sort = ($ldap_connection,$search_return,"givenname");
$entries = ldap_get_entries($ldap_connection,$search_return);

This will take the returned search sort it by the "givenname" attribute. It has to be done BEFORE you call ldap_get_entries.
jason dot sokolowski at rotork dot com
06-Sep-2002 01:51
Something real simple i wrote to sort directory searches by a persons last name.

for($i=0;$i<$result["count"];$i++)
{

$lastname = $result[$i]["sn"][0];

$lnames["$i"]=$lastname;

}//for i

@asort($lnames);
matthew dot j dot gray at uwrf dot edu
25-Jun-2002 02:47
This function applies strcmp() to each attribute (given by sortfilter) in order to sort the entries returned by the server.  To order search results ascending by last name, try passing "sn" as the sortfilter argument.  This function does not play nice with multi-valued attributes.

ldap_start_tls> <ldap_set_rebind_proc
Last updated: Sun, 25 Nov 2007
 
 
show source | credits | stats | sitemap | contact | advertising | mirror sites