title: Using usort() to sort a 2-dimensional array with hierarchical ordering criteria
body: <p>Trying to sort an 2-dimensional array of pizza toppings by the category of topping it belongs to. But the way the client supplies the data isn't ideal for this. Here's a sample of the data:</p>
  
  <pre><code>        [0] =&gt; Array
              (
                  [id] =&gt; 30
                  [title] =&gt; Pepperoni
                  [meat] =&gt; 1
                  [veggie] =&gt; 
                  [sauce] =&gt; 
                  [cheese] =&gt; 
                  [condiment] =&gt; 
              )
  
          [1] =&gt; Array
              (
                  [id] =&gt; 29
                  [title] =&gt; Onions
                  [meat] =&gt; 
                  [veggie] =&gt; 1
                  [sauce] =&gt; 
                  [cheese] =&gt; 
                  [condiment] =&gt; 
              )
  </code></pre>
  
  <p>The idea is that the toppings should always be grouped by a type (ie. <code>meat</code>) in a specific order (ie. <code>meats</code> followed by <code>veggies</code> followed by <code>sauces</code> and so on)—independent of the order in which they're retrieved. Importantly, no topping ever belongs to two types.</p>
  
  <p>Here's my stab at this: </p>
  
  <pre><code>$topping_options = array()  // ie. the sample data above
  usort($topping_options,
                  function($opt_a, $opt_b) {
                      $scores = array("a" =&gt;  0, "b" =&gt; 0);
                      foreach( array("a" =&gt; $opt_a, "b" =&gt; $opt_b) as $index =&gt; $opt) {
                          if ($opt['meat']) $scores[$index] = 5;
                          if ($opt['veggie']) $scores[$index] = 4;
                          if ($opt['sauce']) $scores[$index] = 3;
                          if ($opt['cheese']) $scores[$index] = 2;
                          if ($opt['condiment']) $scores[$index] = 1;
                      }
  
                      return $scores['a'] - $scores['b'];
                  }
              );
  </code></pre>
  
  <p>This doesn't at all achieve my aims and I don't understand why; it seems to me that whenever <code>$opt_a</code> has a higher score than <code>$opt_b</code> it should keep it's position while <code>$opt_b</code> gets sent down a rung for further comparisons. Would like to understand what I'm doing wrong. Thanks. </p>