Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Sorting with PHP 1

Status
Not open for further replies.

TStriker

Programmer
Nov 12, 2003
277
US
Hi all,

I'm a real rookie at PHP. I've done an LDAP query on Active Directory but cannot figure out how to sort the results. Here's what I have so far:

// ====== P R O C E S S ======
$connect = ldap_connect( $ldap_host, $ldap_port)
or exit("<p>ERROR: Could not connect to LDAP server</p>");

ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
$bind = ldap_bind($connect, $ldap_user, $ldap_pass )
or exit("<p>ERROR: Could not bind to $ldap_host</p>");

$read = ldap_search($connect, $base_dn, $filter, array("sn","givenname","telephonenumber","mobile"))
or exit("<p>ERROR: Unable to read the LDAP server</p>");

$info = ldap_get_entries($connect, $read);

echo '<table>';
echo '<tr><td>Last</td><td>First</td><td>Phone</td><td>Mobile</td></tr>';

for ($i=0; $i<$info["count"]; $i++) {
echo "<tr>";
echo "<td>" . $info[$i]["sn"][0] . "</td>";
echo "<td>" . $info[$i]["givenname"][0] . "</td>";
echo "<td>" . $info[$i]["telephonenumber"][0] . "</td>";
echo "<td>" . $info[$i]["mobile"][0] . "</td>";
echo "</tr>";
}

echo '</table>';

How do I sort the results first on sn then on givenname?

Thanks!

-Striker
 
Hi

PHP:
[COLOR=darkgoldenrod]usort[/color][teal]([/teal][navy]$info[/navy][teal],[/teal][b]function[/b][teal]([/teal][navy]$a[/navy][teal],[/teal][navy]$b[/navy][teal])[/teal][teal]{[/teal][b]return[/b][navy]$a[/navy][teal][[/teal][green][i]'givenname'[/i][/green][teal]]!=[/teal][navy]$b[/navy][teal][[/teal][green][i]'givenname'[/i][/green][teal]]?[/teal][COLOR=darkgoldenrod]cmp[/color][teal]([/teal][navy]$a[/navy][teal][[/teal][green][i]'givenname'[/i][/green][teal]],[/teal][navy]$b[/navy][teal][[/teal][green][i]'givenname'[/i][/green][teal]]):[/teal][COLOR=darkgoldenrod]cmp[/color][teal]([/teal][navy]$a[/navy][teal][[/teal][green][i]'sn'[/i][/green][teal]],[/teal][navy]$b[/navy][teal][[/teal][green][i]'sn'[/i][/green][teal]]);[/teal][teal]}[/teal][teal]);[/teal]
Note that cmp() is not a standard PHP function. You can find its declaration in the PHP manual, at the [tt]usort()[/tt] examples.

Note that anonymous functions are supported since PHP 5.3.0. If you have older PHP, use [tt]create_function()[/tt] instead.


Feherke.
 
feherke,

Didn't work for me. I'm getting a parse error. I strongly suspect that the problem is that you're thinking I know more than I really do.

Is there any way to simplify the answer?

-Striker
 
here's an alternative method leveraging the sqlite memory ability (and this kind of thing is exactly the application for sqlite::memory:). if you have not got sqlite installed and cannot install it then the code can be easily adapted for mysql temp tables

the advantage of this method is that database sorting functions are both compiled and optimised rather than simply interpreted.

Code:
<?php
$connect = ldap_connect( $ldap_host, $ldap_port)
    or exit("<p>ERROR: Could not connect to LDAP server</p>");

ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
$bind = ldap_bind($connect, $ldap_user, $ldap_pass ) 
    or exit("<p>ERROR: Could not bind to $ldap_host</p>");

$read = ldap_search($connect, $base_dn, $filter, array("sn","givenname","telephonenumber","mobile"))
    or exit("<p>ERROR: Unable to read the LDAP server</p>");

$info = ldap_get_entries($connect, $read);
try{
	$pdo = new pdo ('sqlite::memory:');
} catch (PDOException $e) {
	echo 'Connection failed: ' . $e->getMessage();
	exit;
}
$pdo->exec('create table tmpT (lastname text, firstname text, telnum text, mobnum text');
$s = $pdo->prepare('insert into tmpT (lastname, firstname, telnum, mobnum) values (?,?,?,?)');
foreach ($info as $data){
	$s->execute(array($data['sn'],	$data['givenname'],	$data['telephonenumber'],	$data['mobile']));
}
$query = "Select * from tmpT order by lastname asc, firstname asc";

echo '<table>';
echo '<tr><td>Last</td><td>First</td><td>Phone</td><td>Mobile</td></tr>';
foreach ($pdo->query($query) as $info){
	echo "<tr>";
	echo "<td>" . $info["lastname"] . "</td>";
	echo "<td>" . $info["firstname"] . "</td>";
	echo "<td>" . $info["telnum"] . "</td>";
	echo "<td>" . $info["mobnum"]. "</td>";
	echo "</tr>";
}
echo '</table>';
?>
 
While jpadie's suggestion is the best alternative, you could also change the for loop to foreach, concatenate the sn and givenname fields and use that as the key, then just do an asort of the array when you're done. You can loop through the sorted array and output the data afterward.

If your data set isn't too large, it should complete in a matter of seconds.

Code:
$newarray = array();
foreach ($info as $i) {
        $key = $i['sn'] . $i['givenname'];

        $newarray[$key]['sn'] = $i["sn"][0];
        $newarray[$key]['givenname'] = $i["givenname"][0];
        $newarray[$key]['telephonenumber'] = $i["telephonenumber"][0];
        $newarray[$key]['mobile'] = $i["mobile"][0];
    }
asort($newarray);

I didn't test this code, so sorry if there are bugs. :)
 
good idea Mark. a slight tweak perhaps as shown to keep the original data untouched

Code:
<?php
$connect = ldap_connect( $ldap_host, $ldap_port)
    or exit("<p>ERROR: Could not connect to LDAP server</p>");

ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
$bind = ldap_bind($connect, $ldap_user, $ldap_pass ) 
    or exit("<p>ERROR: Could not bind to $ldap_host</p>");

$read = ldap_search($connect, $base_dn, $filter, array("sn","givenname","telephonenumber","mobile"))
    or exit("<p>ERROR: Unable to read the LDAP server</p>");

$info = ldap_get_entries($connect, $read);
$results = array();
foreach ($info as $data){
	$consol[] = $data['sn'] . '||' . $data['givenname'];
	$results[] = $data;
}
asort($consol);
echo '<table>';
echo '<tr><td>Last</td><td>First</td><td>Phone</td><td>Mobile</td></tr>';
foreach ($consol as $key=>$val){
	echo "<tr>";
	echo "<td>" . $results[$key]["lastname"] . "</td>";
	echo "<td>" . $results[$key]["firstname"] . "</td>";
	echo "<td>" . $results[$key]["telnum"] . "</td>";
	echo "<td>" . $results[$key]["mobnum"]. "</td>";
	echo "</tr>";
}
echo '</table>';
?>
 
I tried jpadie's last suggestion and no errors but all it produces is a big set of empty opening and closing TD tags -- no content. I'm not enough of a PHP guy to figure out what the problem is.

-Striker
 
the array keys were wrong given your ldap call

Code:
echo "<td>" . $results[$key]["sn"] . "</td>";
    echo "<td>" . $results[$key]["givenname"] . "</td>";
    echo "<td>" . $results[$key]["telephonenumber"] . "</td>";
    echo "<td>" . $results[$key]["mobile"]. "</td>";
 
Now the word "Array" appears in each cell.

-Striker
 
How 'bout this...

Code:
echo "<td>" . $results[$key]["sn"][0] . "</td>";
    echo "<td>" . $results[$key]["givenname"][0] . "</td>";
    echo "<td>" . $results[$key]["telephonenumber"][0] . "</td>";
    echo "<td>" . $results[$key]["mobile"][0]. "</td>";
 
i was implying the same array structure as you used in your original post. if it is not working for you then the array structure is not as you posted.

If mark's suggestion does not work then print_r the array and post the results.
 
Okay, obviously I'm in over my head on the PHP stuff because now it is returning results but it's not sorted. Here's what I have:

$connect = ldap_connect( $ldap_host, $ldap_port)
or exit("<p>ERROR: Could not connect to LDAP server</p>");

ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
$bind = ldap_bind($connect, $ldap_user, $ldap_pass )
or exit("<p>ERROR: Could not bind to $ldap_host</p>");

$read = ldap_search($connect, $base_dn, $filter, array("sn","givenname","telephonenumber","mobile"))
or exit("<p>ERROR: Unable to read the LDAP server</p>");

$info = ldap_get_entries($connect, $read);

$results = array();
foreach ($info as $data){
$consol[] = $data['sn'] . '||' . $data['givenname'];
$results[] = $data;
}
asort($consol);
echo '<table>';
echo '<tr><td>Last</td><td>First</td><td>Phone</td><td>Mobile</td></tr>';
foreach ($consol as $key => $val){
echo "<tr>";
echo "<td>" . $results[$key]["sn"][0] . "</td>";
echo "<td>" . $results[$key]["givenname"][0] . "</td>";
echo "<td>" . $results[$key]["telephonenumber"][0] . "</td>";
echo "<td>" . $results[$key]["mobile"][0]. "</td>";
echo "</tr>";
}
echo '</table>';

$closeResult = ldap_close($connect)
or exit ("ERROR: The connection could not be closed");

-Striker
 
given that the goal posts on the array structure have changed the solution must also change.

Code:
foreach ($info as $data){
    $consol[] = $data['sn'][0] . '||' . $data['givenname'][0];
    $results[] = $data;
}
 
SUCCESS!

Thanks for the help guys. It's embarrassing just how little I know about PHP and especially arrays. I'm going to have to study your work and see if I can figure out how and why it happens.

Thanks again.



-Striker
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top