Jump to content

Sorting Nested Array Results


TCombs

Recommended Posts

Hello all! I've posted here in the past and had great success, hoping for the same today.

 

I have a wordpress site and I'm trying to pull the members into a page and sort them by results.

It's a Musicians site and I need to be able to sort the members by the instruments they play.

 

This code will pull the members into the page and you can see the results at: http://afm1.org/wp/?page_id=677

<?php
$args = array(
'fields' => 'all',
'role' => 'Subscriber',
'meta_query' => array(
 array(
 'key'=>'instrument'
 ))
);
$members = get_users($args);
//custom function for comparing the data we want to sort by
function cmp($a, $B){
if ($a->instrument == $b->instrument) {
return 0;
}
return ($a->instrument > $b->instrument) ? 1 : -1;
}
usort($members, 'cmp');
foreach ($members as $member ) {
 // get all the user's data
 $member_info = get_userdata($member->ID);
echo '<div id="membox">';
echo $member_info->first_name. ' ' .$member_info->last_name.'<br />';
echo $member_info->address_1.'<br />';
echo $member_info->city.', '.$member_info->state.', '.$member_info->zip.'<br />';
echo $member_info->phone.'<br />';
echo '<a href="mailto:'.$member_info->email.'">'.$member_info->email.'</a><br />';
foreach ($member_info->instrument as $inst) {
echo '<b>'.$inst.'</b>, '; }
echo '</div>';
}
?>

 

What I want to do is have the Instrument as a title and have all of the members that play that instrument listed like this:

 

<h1>Accordian</h1>

Arpi Anderson

1234 Whitfield Avenue

Cincinnati, OH, 45220

513-111-1111

arpianderson@hotmail.com

Accordion,

 

David Abbott

123 N. Ft. Thomas Ave.

Ft. Thomas, KY, 41075

859-111-1111

davejanet@acninc.net

Accordion, Acoustic,

 

<h1>Violin</h1>

Ann Baer

123 Cabinridge

Batavia, OH, 45103

513-111-1111

violin@cinci.rr.com

Violin,

 

 

Any help would be GREATLY appreciated! Thanks

Link to comment
Share on other sites

It seems you have a couple problems here. The first one is that it looks like your schema supports multiple instruments per musician. So your sortation is inherently flawed because you are checkng the equivalence of arrays rather than the strings that contain the instruments themselves. If you're alright with checking the first instrument then you should probably change your cmp function to compare $a->instrument[0] vs $b->instrument[0] for both comparisons. I also noticed a subtle bug you have:

 

function cmp($a, $B){

 

Notice that $B should be $b. PHP variable names are case sensitive, so the compare function currently is not working at all if that is your real code, although as I said, it's also not going to work the way you want unless you get down to the string comparison of a specific array element in each array.

 

Assuming all that is working, you can effectively add the catagory headers by using a variable that you initialize before the output loop, and that you check to see if it has changed just prior to doing the member block output.

 

$category = '';
foreach ($members as $member ) {
        // get all the user's data
        $member_info = get_userdata($member->ID);

        //did category change?        
        if ($category !== $member_info->instrument[0]) {
            $category = $member_info->instrument[0];
            echo "<h1>$category</h1>\n";
        }

 

 

Link to comment
Share on other sites

If it is true that members play multiple instruments then this approach will list players under all the instruments that have in their profile

 

<?php
$directory = array();

foreach ($members as $member ) {
   // get all the user's data
   $member_info = get_userdata($member->ID);
   foreach ($member_info->instrument as $inst) {
    $directory[$inst][] = array (
		    'lastname' => $member_info->last_name,
		    'firstname' => $member_info->first_name,
		    'address' => $member_info->address_1,
		    'city' => $member_info->city,
		    'state' => $member_info->state,
		    'zip' => $member_info->zip,
		    'phone' => $member_info->phone,
		    'email' => $member_info->email
		    );
   }
}
ksort($directory);  // sort by instrument

foreach ($directory as $instrument => $players) {
   echo "<h1>$instrument</h1>\n";
   sort($players);  // sort players by lastname
   foreach ($players as $player) {
    // output player details here
   }
}
?>

Link to comment
Share on other sites

@gizmoloa - Thanks for your response, not sure how the 'b' became 'B' when I pasted the code. I have noticed this editor is a little buggy.

 

@barand - Thank you as well.

 

The code you showed me got me a lot closer to what I need. however, it is listing each instrument with the same user. Here's what I have now:

<?php
$args  = array( 
 'fields' => 'all',
 'role' => 'Subscriber',
 'meta_query' => array(
   array(
  'key'=>'instrument'
  ))
 ); 
$members = get_users($args);
//custom function for comparing the data we want to sort by 
function cmp($a, $B){ 
 if ($a->instrument == $b->instrument) { 
   return 0; 
 } 
 return ($a->instrument > $b->instrument) ? 1 : -1; 
}
usort($members, 'cmp');
$directory = array();
foreach ($members as $member ) { // get all the user's data	   
$member_info = get_userdata($member->ID);	  
foreach ($member_info->instrument as $inst) {			   
$directory[$inst][] = array (							   
'lastname' => $member_info->last_name,							   
'firstname' => $member_info->first_name,							   
'address' => $member_info->address_1,							   
'city' => $member_info->city,							   
'state' => $member_info->state,							   
'zip' => $member_info->zip,							   
'phone' => $member_info->phone,							   
'email' => $member_info->email							  
);	   
}}
ksort($directory);  // sort by instrument
foreach ($directory as $instrument => $players) {	   
echo '<h1>' .$instrument. '</h1>';	   
sort($players);  // sort players by lastname	   
foreach ($players as $player) {			    // output player details here 
echo '<div id="membox">';
 echo $member_info->first_name. ' ' .$member_info->last_name.'<br />';
 echo $member_info->address_1.'<br />';
 echo $member_info->city.', '.$member_info->state.', '.$member_info->zip.'<br />';
 echo $member_info->phone.'<br />';
 echo '<a href="mailto:'.$member_info->email.'">'.$member_info->email.'</a><br />';
 foreach ($member_info->instrument as $inst) {
 echo '<b>'.$inst.'</b>, '; }
 echo '</div>';	
}}
?>

Link to comment
Share on other sites

Can't see why yet. I did a mock-up with

$members = array(
   array ('name' => 'Mary', 'instruments' => array('clarinet', 'saxophone')),
   array ('name' => 'Bob', 'instruments' => array('piano')),
   array ('name' => 'Peter', 'instruments' => array('piano', 'violin')),
   array ('name' => 'Jane', 'instruments' => array('cello', 'violin')),
   array ('name' => 'Paul', 'instruments' => array('guitar', 'violin')),
   array ('name' => 'Henry', 'instruments' => array('clarinet')),
   array ('name' => 'Margaret', 'instruments' => array('guitar')),
   array ('name' => 'Alan', 'instruments' => array('guitar', 'ukelele'))
   );

 

RESULTS

cello
--- Jane
clarinet
--- Henry
--- Mary
guitar
--- Alan
--- Margaret
--- Paul
piano
--- Bob
--- Peter
saxophone
--- Mary
ukelele
--- Alan
violin
--- Jane
--- Paul
--- Peter

Link to comment
Share on other sites

Thank you sir! Looks very good now!

 

1 last tweak, if a user has multiple instruments listed, can we get all instruments to show in the member output.

 

For example, if you look at this link: http://afm1.org/wp/?page_id=677

You see that david abbott is listed under Accordian & Acoustic...which is CORRECT.

however, under his email address only the 1 instrument is listed. Can we get both instruments listed here?

Link to comment
Share on other sites

Store instruments in directory array

   foreach ($member_info->instrument as $inst) {
    $directory[$inst][] = array (
		    'lastname' => $member_info->last_name,
		    'firstname' => $member_info->first_name,
		    'address' => $member_info->address_1,
		    'city' => $member_info->city,
		    'state' => $member_info->state,
		    'zip' => $member_info->zip,
		    'phone' => $member_info->phone,
		    'email' => $member_info->email,
		    'instruments' => $member_info->instrument	    // ADD THIS LINE
		    );
   }

 

When outputting the details

echo join(', ', $player['instruments']) . '<br>';   // ADD THIS

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.