PHP group array

Hi Guys!

I have been trying to group an array of locations for a while without success - I just can’t get my head round how it can be done.

Here’s the array:


Array (
[0] => Array ( [id] => 1001 [parent] => 1001 [show_type] => parent [location_name] => East Anglia )
[1] => Array ( [id] => 1081 [parent] => 1001 [show_type] => child [location_name] => Bedfordshire )
[2] => Array ( [id] => 1002 [parent] => 1001 [show_type] => child [location_name] => Cambridgeshire )
[3] => Array ( [id] => 1003 [parent] => 1001 [show_type] => child [location_name] => Norfolk )
[4] => Array ( [id] => 1004 [parent] => 1001 [show_type] => child [location_name] => Suffolk )
[5] => Array ( [id] => 1005 [parent] => 1005 [show_type] => parent [location_name] => East Midlands )
[6] => Array ( [id] => 1006 [parent] => 1005 [show_type] => child [location_name] => Derbyshire )
[7] => Array ( [id] => 1007 [parent] => 1005 [show_type] => child [location_name] => Leicestershire )
[8] => Array ( [id] => 1008 [parent] => 1005 [show_type] => child [location_name] => Lincolnshire )
[9] => Array ( [id] => 1009 [parent] => 1005 [show_type] => child [location_name] => Northamptonshire )
[10] => Array ( [id] => 1010 [parent] => 1005 [show_type] => child [location_name] => Nottinghamshire )
[11] => Array ( [id] => 1011 [parent] => 1005 [show_type] => child [location_name] => Rutland )
)

Now, what i’m trying to output is a SELECT menu with optgroup elements. Here’s the result i’m trying to achieve:


<select name="test">
<optgroup label="East Anglia">
  <option value="Bedfordshire">Bedfordshire</option>
  <option value="Cambridgeshire">Cambridgeshire</option>
  <option value="Norfolk">Norfolk</option>
  <option value="Suffolk">Suffolk</option>
</optgroup>
<optgroup label="East Midlands">
  <option value="Derbyshire">Derbyshire</option>
  <option value="Leicestershire">Leicestershire</option>
  <option value="Lincolnshire">Lincolnshire</option>
  <option value="Northamptonshire">Northamptonshire</option>
  <option value="Nottinghamshire">Nottinghamshire</option>
  <option value="Rutland">Rutland</option>
</optgroup>
</select>

As you can see, the parent (optgroup) have a show_type of “parent” in the array. So basically what I need to do is place all the “childs” under the “parent” in the select box.

Any ideas ?

Since you record the parent with each node it would be best to first create a new array from the array you have now, and then process that array for display.


$newArray = array();
foreach($myArray as $item)
{
   switch ($item['show_type'])
   {
      case 'parent':
         isset($newArray[$item['key']]) || $newArray[$item['key']] = array();
         $newArray[$item['key']]['location_name'] = $item['location_name'];
      break;
      case 'child': 
         isset($newArray[$item['parent']]) || $newArray[$item['parent']] = array();
         isset($newArray[$item['parent']]['children']) || $newArray[$item['parent']]['children'] = array();
         array_push($newArray[$item['parent']]['children'], $item['location_name']);
      break;
}

and then with the new array


<select name="test">
<?php
foreach($newArray as $items)
{
   echo '<optgroup label="', $items['location_name'], '">';
   foreach($items['children'] as $child)
   {
      echo '<option value="', $child, '">', $child, '</option>';
   }
   echo '</optgroup>';
}

(not tested)


$c = array (  
array ( 'id' => 1001, 'parent' => 1001, 'show_type' => 'parent', 'location_name' => 'East Anglia' ) , 
array ( 'id' => 1081, 'parent' => 1001, 'show_type' => 'child', 'location_name' => 'Bedfordshire' )  ,
array ( 'id' => 1002, 'parent' => 1001, 'show_type' => 'child', 'location_name' => 'Cambridgeshire' ),
); 

print_r($c);

foreach( $c as $county){
  if($county['show_type'] === 'parent'){
  echo '<optgroup label="' . $county['location_name']  . '">' . PHP_EOL;
  }else{
  echo  ' <option value="' . $county['location_name']  .  '">' .$county['location_name'] . '</option>' . PHP_EOL ;
  }
}

// gives
//<optgroup label="East Anglia">
// <option value="Bedfordshire">Bedfordshire</option>
// <option value="Cambridgeshire">Cambridgeshire</option>


That was more time-consuming than necessary for me because you showed the output of


var_dump($array) ;

rather than


$array = var_export( $array, 1);

echo $array;

So I had to type out the small test case above.

You’re a star! I tried the code you posted, here’s the output array:

Array ( [1035] => Array ( [children] => Array ( [0] => Aberdeenshire [1] => Angus [2] => Argyll & Bute [3] => Ayrshire [4] => Clackmannanshire [5] => Dumfries and Galloway [6] => Dumfriesshire [7] => Dunbartonshire [8] => Dundee [9] => East Lothian [10] => Edinburgh [11] => Fife [12] => Glasgow [13] => Highland [14] => Inverclyde [15] => Lanarkshire [16] => Midlothian [17] => Moray [18] => Perth and Kinross [19] => Renfrewshire [20] => Scottish Borders [21] => Scottish Islands [22] => Stirling [23] => West Lothian ) ) [1101] => Array ( [children] => Array ( [0] => Anglesey [1] => Bridgend [2] => Caerphilly [3] => Cardiff [4] => Carmarthenshire [5] => Ceredigion [6] => Conwy [7] => Denbighshire [8] => Flintshire [9] => Gwent [10] => Gwynedd [11] => Merthyr Tydfil [12] => Monmouthshire [13] => Neath & Port Talbot [14] => Pembrokeshire [15] => Powys [16] => Rhondda Cynon Taf [17] => Swansea [18] => Torfaen [19] => Vale of Glamorgan ) ) [1001] => Array ( [children] => Array ( [0] => Bedfordshire [1] => Cambridgeshire [2] => Norfolk [3] => Suffolk ) ) [1133] => Array ( [children] => Array ( [0] => Berkshire [1] => Buckinghamshire [2] => East Sussex [3] => Essex [4] => Hampshire [5] => Hertfordshire [6] => Isle of Wight [7] => Kent [8] => Middlesex [9] => Oxfordshire [10] => Surrey [11] => West Sussex ) ) [1118] => Array ( [children] => Array ( [0] => Birmingham [1] => Coventry [2] => Herefordshire [3] => Shropshire [4] => Staffordshire [5] => Warwickshire [6] => West Midlands [7] => Worcestershire ) ) [1080] => Array ( [children] => Array ( [0] => Bristol [1] => Cornwall [2] => Devon [3] => Dorset [4] => Gloucestershire [5] => Isles of Scilly [6] => Somerset [7] => Wiltshire ) ) [] => Array ( [location_name] => Yorkshire ) [1022] => Array ( [children] => Array ( [0] => Cheshire [1] => Cumbria [2] => Greater Manchester [3] => Isle of Man [4] => Lancashire [5] => Merseyside [6] => Merseyside [7] => Tyne and Wear [8] => West Yorkshire ) ) [1028] => Array ( [children] => Array ( [0] => County Antrim [1] => County Armagh [2] => County Down [3] => County Fermanagh [4] => County Londonderry [5] => County Tyrone ) ) [1013] => Array ( [children] => Array ( [0] => County Durham [1] => Northumberland [2] => Redcar & Cleveland [3] => Tyne and Wear ) ) [1005] => Array ( [children] => Array ( [0] => Derbyshire [1] => Leicestershire [2] => Lincolnshire [3] => Northamptonshire [4] => Nottinghamshire [5] => Rutland ) ) [1020] => Array ( [children] => Array ( [0] => East Yorkshire [1] => North Yorkshire [2] => South Yorkshire [3] => West Yorkshire ) ) ) 

I am then trying to output using smarty with the following code:

{foreach from=$select_locations item="cat"}
            	<optgroup label="{$cat.location_name}">
                {foreach from=$cat.children item="child"}
      				<option value="{$child}">{$child}</option>
   				{/foreach}
                </optgroup>
            {/foreach}

However, it results in the following select box:


<select class="inp" name="location" id="location">

            <option value="">All Locations</option>
                        	<optgroup label="">
                      				<option value="Aberdeenshire">Aberdeenshire</option>
   				      				<option value="Angus">Angus</option>
   				      				<option value="Argyll & Bute">Argyll & Bute</option>
   				      				<option value="Ayrshire">Ayrshire</option>

   				      				<option value="Clackmannanshire">Clackmannanshire</option>
   				      				<option value="Dumfries and Galloway">Dumfries and Galloway</option>
   				      				<option value="Dumfriesshire">Dumfriesshire</option>
   				      				<option value="Dunbartonshire">Dunbartonshire</option>
   				      				<option value="Dundee">Dundee</option>
   				      				<option value="East Lothian">East Lothian</option>

   				      				<option value="Edinburgh">Edinburgh</option>
   				      				<option value="Fife">Fife</option>
   				      				<option value="Glasgow">Glasgow</option>
   				      				<option value="Highland">Highland</option>
   				      				<option value="Inverclyde">Inverclyde</option>
   				      				<option value="Lanarkshire">Lanarkshire</option>

   				      				<option value="Midlothian">Midlothian</option>
   				      				<option value="Moray">Moray</option>
   				      				<option value="Perth and Kinross">Perth and Kinross</option>
   				      				<option value="Renfrewshire">Renfrewshire</option>
   				      				<option value="Scottish Borders">Scottish Borders</option>
   				      				<option value="Scottish Islands">Scottish Islands</option>

   				      				<option value="Stirling">Stirling</option>
   				      				<option value="West Lothian">West Lothian</option>
   				                </optgroup>
                        	<optgroup label="">
                      				<option value="Anglesey">Anglesey</option>
   				      				<option value="Bridgend">Bridgend</option>
   				      				<option value="Caerphilly">Caerphilly</option>

   				      				<option value="Cardiff">Cardiff</option>
   				      				<option value="Carmarthenshire">Carmarthenshire</option>
   				      				<option value="Ceredigion">Ceredigion</option>
   				      				<option value="Conwy">Conwy</option>
   				      				<option value="Denbighshire">Denbighshire</option>
   				      				<option value="Flintshire">Flintshire</option>

   				      				<option value="Gwent">Gwent</option>
   				      				<option value="Gwynedd">Gwynedd</option>
   				      				<option value="Merthyr Tydfil">Merthyr Tydfil</option>
   				      				<option value="Monmouthshire">Monmouthshire</option>
   				      				<option value="Neath & Port Talbot">Neath & Port Talbot</option>
   				      				<option value="Pembrokeshire">Pembrokeshire</option>

   				      				<option value="Powys">Powys</option>
   				      				<option value="Rhondda Cynon Taf">Rhondda Cynon Taf</option>
   				      				<option value="Swansea">Swansea</option>
   				      				<option value="Torfaen">Torfaen</option>
   				      				<option value="Vale of Glamorgan">Vale of Glamorgan</option>
   				                </optgroup>

                        	<optgroup label="">
                      				<option value="Bedfordshire">Bedfordshire</option>
   				      				<option value="Cambridgeshire">Cambridgeshire</option>
   				      				<option value="Norfolk">Norfolk</option>
   				      				<option value="Suffolk">Suffolk</option>
   				                </optgroup>
                        	<optgroup label="">

                      				<option value="Berkshire">Berkshire</option>
   				      				<option value="Buckinghamshire">Buckinghamshire</option>
   				      				<option value="East Sussex">East Sussex</option>
   				      				<option value="Essex">Essex</option>
   				      				<option value="Hampshire">Hampshire</option>
   				      				<option value="Hertfordshire">Hertfordshire</option>

   				      				<option value="Isle of Wight">Isle of Wight</option>
   				      				<option value="Kent">Kent</option>
   				      				<option value="Middlesex">Middlesex</option>
   				      				<option value="Oxfordshire">Oxfordshire</option>
   				      				<option value="Surrey">Surrey</option>
   				      				<option value="West Sussex">West Sussex</option>

   				                </optgroup>
                        	<optgroup label="">
                      				<option value="Birmingham">Birmingham</option>
   				      				<option value="Coventry">Coventry</option>
   				      				<option value="Herefordshire">Herefordshire</option>
   				      				<option value="Shropshire">Shropshire</option>
   				      				<option value="Staffordshire">Staffordshire</option>

   				      				<option value="Warwickshire">Warwickshire</option>
   				      				<option value="West Midlands">West Midlands</option>
   				      				<option value="Worcestershire">Worcestershire</option>
   				                </optgroup>
                        	<optgroup label="">
                      				<option value="Bristol">Bristol</option>
   				      				<option value="Cornwall">Cornwall</option>

   				      				<option value="Devon">Devon</option>
   				      				<option value="Dorset">Dorset</option>
   				      				<option value="Gloucestershire">Gloucestershire</option>
   				      				<option value="Isles of Scilly">Isles of Scilly</option>
   				      				<option value="Somerset">Somerset</option>
   				      				<option value="Wiltshire">Wiltshire</option>

   				                </optgroup>
                        	<optgroup label="Yorkshire">
                                </optgroup>
                        	<optgroup label="">
                      				<option value="Cheshire">Cheshire</option>
   				      				<option value="Cumbria">Cumbria</option>
   				      				<option value="Greater Manchester">Greater Manchester</option>

   				      				<option value="Isle of Man">Isle of Man</option>
   				      				<option value="Lancashire">Lancashire</option>
   				      				<option value="Merseyside">Merseyside</option>
   				      				<option value="Merseyside">Merseyside</option>
   				      				<option value="Tyne and Wear">Tyne and Wear</option>
   				      				<option value="West Yorkshire">West Yorkshire</option>

   				                </optgroup>
                        	<optgroup label="">
                      				<option value="County Antrim">County Antrim</option>
   				      				<option value="County Armagh">County Armagh</option>
   				      				<option value="County Down">County Down</option>
   				      				<option value="County Fermanagh">County Fermanagh</option>
   				      				<option value="County Londonderry">County Londonderry</option>

   				      				<option value="County Tyrone">County Tyrone</option>
   				                </optgroup>
                        	<optgroup label="">
                      				<option value="County Durham">County Durham</option>
   				      				<option value="Northumberland">Northumberland</option>
   				      				<option value="Redcar & Cleveland">Redcar & Cleveland</option>

   				      				<option value="Tyne and Wear">Tyne and Wear</option>
   				                </optgroup>
                        	<optgroup label="">
                      				<option value="Derbyshire">Derbyshire</option>
   				      				<option value="Leicestershire">Leicestershire</option>
   				      				<option value="Lincolnshire">Lincolnshire</option>
   				      				<option value="Northamptonshire">Northamptonshire</option>

   				      				<option value="Nottinghamshire">Nottinghamshire</option>
   				      				<option value="Rutland">Rutland</option>
   				                </optgroup>
                        	<optgroup label="">
                      				<option value="East Yorkshire">East Yorkshire</option>
   				      				<option value="North Yorkshire">North Yorkshire</option>
   				      				<option value="South Yorkshire">South Yorkshire</option>

   				      				<option value="West Yorkshire">West Yorkshire</option>
   				                </optgroup>
                      </select>

Any idea where we are going wrong?

Thanks!

Oops, I used ‘key’ instead of ‘id’ :slight_smile:


$c = array (  
array ( 'id' => 1001, 'parent' => 1001, 'show_type' => 'parent', 'location_name' => 'East Anglia' ) , 
array ( 'id' => 1081, 'parent' => 1001, 'show_type' => 'child', 'location_name' => 'Bedfordshire' )  ,
array ( 'id' => 1002, 'parent' => 1001, 'show_type' => 'child', 'location_name' => 'Cambridgeshire' ),
); 

$newArray = array(); 
foreach($c as $item) 
{ 
   switch ($item['show_type']) 
   { 
      case 'parent': 
         isset($newArray[$item['id']]) || $newArray[$item['id']] = array(); 
         $newArray[$item['id']]['location_name'] = $item['location_name']; 
      break; 
      case 'child':  
         isset($newArray[$item['parent']]) || $newArray[$item['parent']] = array(); 
         isset($newArray[$item['parent']]['children']) || $newArray[$item['parent']]['children'] = array(); 
         array_push($newArray[$item['parent']]['children'], $item['location_name']); 
      break; 
   }
}

var_dump($newArray);

And I’ve used location_name, not location. You might want to change either my code there or yours.

Ahhh yes, thank you! :slight_smile: