I have this HTML optgroup select box that is populated from values stored in a WordPress database.
$field_val = get_post_meta($post->ID, $field['id'], true);
echo '<select id="'.$field['id'].'" name="'.$field['id'].'">';
foreach ($field['options'] as $key => $value) {
$custom_fields = get_post_custom($value);
$bgtypes = $custom_fields['bgtype'];
foreach($bgtypes as $bgkey => $type){
echo '<optgroup label="'.$type.'">';
echo '<option value="'.$value.'" '.selected($value, $field_val, false).'>'.$key.'</option>';
echo '</optgroup>';
}
}
echo '</select>';
It retrieves all the correct data however when it prints out the values the values are not "grouped".
Here is an example of the returned results:
<select id="_wpbp_background" name="_wpbp_background">
<optgroup label="youtube">
<option value="2777" >YouTube Playlist video</option>
</optgroup>
<optgroup label="videos">
<option value="2775" >Another Self Hosted Video</option>
</optgroup>
<optgroup label="images">
<option value="2774" >Image Slideshow Main</option>
</optgroup>
<optgroup label="pattern">
<option value="2773" >Carbon Pattern BG</option>
</optgroup>
<optgroup label="solid">
<option value="2772" >Purple Solid BG Color</option>
</optgroup>
<optgroup label="audio">
<option value="2771" >Test Audio File 2</option>
</optgroup>
<optgroup label="images">
<option value="2759" >test image slideshow</option>
</optgroup>
<optgroup label="videos">
<option value="2747" selected='selected'>Test Hosted Video</option>
</optgroup>
<optgroup label="youtube">
<option value="2736" >YouTube Video 1</option>
</optgroup>
<optgroup label="pattern">
<option value="2718" >Pattern 1</option>
</optgroup>
<optgroup label="videos">
<option value="2711" >test video 1</option>
</optgroup>
<optgroup label="audio">
<option value="2693" >Test audio file 1</option>
</optgroup>
<optgroup label="images">
<option value="2670" >test image</option>
</optgroup>
<optgroup label="solid">
<option value="2669" >Blue Solid Background</option>
</optgroup>
<optgroup label="solid">
<option value="2667" >Red Background</option>
</optgroup>
</select>
If you look at the returned results you will notice that there are many groups with the same name. "Images" for example.
Is there a way I can modify the original PHP code to group those options like so:
<select id="_wpbp_background" name="_wpbp_background">
<optgroup label="images">
<option value="2774" >Image Slideshow Main</option>
<option value="2759" >test image slideshow</option>
<option value="2670" >test image</option>
</optgroup>
<optgroup label="solid">
<option value="2669" >Blue Solid Background</option>
<option value="2667" >Red Background</option>
</optgroup>
</select>
Any help would be greatly appreciated. Thanks
====================================================================== EDIT:
Here is the original function that I call to get the "backgrounds" custom post type elements:
/**
* Returns a list of backgrounds
*/
function get_backgrounds(){
$bgs = get_posts(array(
'post_type' => $this->cpt,
'numberposts' => -1,
'orderby' => 'title',
));
$backgrounds = array();
$backgrounds[__('-- Select Background --', $this->prefix)] = '';
foreach($bgs as $key => $value){
$backgrounds[$value->post_title] = $value->ID;
}
return $backgrounds;
}
When called the above code displays
Array
(
[-- Select Background --] =>
[YouTube Video 1] => 2736
[YouTube Playlist video] => 2777
[test video 1] => 2711
[test image slideshow] => 2759
[test image] => 2670
[Test Hosted Video] => 2747
[Test Audio File 2] => 2771
[Test audio file 1] => 2693
[Red Background] => 2667
[Purple Solid BG Color] => 2772
[Pattern 1] => 2718
[Image Slideshow Main] => 2774
[Carbon Pattern BG] => 2773
[Blue Solid Background] => 2669
[Another Self Hosted Video] => 2775
)
First code block that partially works:
// <optgroup> of the previous <option>
$previous = "";
// variable to set the first group
$first_group = true;
foreach ($field['options'] as $key => $value) {
$custom_fields = get_post_custom($value);
if (isset($custom_fields['bgtype'][0]) && $custom_fields['bgtype'][0]) {
$bgtypes = $custom_fields['bgtype'];
foreach($bgtypes as $typebg){
if ($typebg != $previous) {
if (!$first_group) {
echo '</optgroup>';
} else {
$first_group = false;
}
echo '<optgroup label="'.$typebg.'">';
$previous = $typebg;
}
echo '<option value="'.$value.'" '.selected($value, $field_val, false).'>'.$key.'</option>';
}
}
}
echo '</optgroup>'; // close last optgroup
echo '</select>';
The results of the first code block:
<select id="_wpbp_background" name="_wpbp_background">
<optgroup label="youtube">
<option value="2736" >YouTube Video 1</option>
<option value="2777" >YouTube Playlist video</option>
</optgroup>
<optgroup label="videos">
<option value="2711" >test video 1</option>
</optgroup>
<optgroup label="images">
<option value="2759" >test image slideshow</option>
<option value="2670" >test image</option>
</optgroup>
<optgroup label="videos">
<option value="2747" selected='selected'>Test Hosted Video</option>
</optgroup>
<optgroup label="audio">
<option value="2771" >Test Audio File 2</option>
<option value="2693" >Test audio file 1</option>
</optgroup>
<optgroup label="solid">
<option value="2667" >Red Background</option>
<option value="2772" >Purple Solid BG Color</option>
</optgroup>
<optgroup label="pattern">
<option value="2718" >Pattern 1</option>
</optgroup>
<optgroup label="images">
<option value="2774" >Image Slideshow Main</option>
</optgroup>
<optgroup label="pattern">
<option value="2773" >Carbon Pattern BG</option>
</optgroup>
<optgroup label="solid">
<option value="2669" >Blue Solid Background</option>
</optgroup>
<optgroup label="videos">
<option value="2775" >Another Self Hosted Video</option>
</optgroup>
</select>
As you can see this code block partially groups the elements by their "bytpe". It groups some of them but NOT ALL. The way I got it to group this way was to add the 'orderby' => 'title'
to the initial function to display the backgrounds.
**Second code block:**
echo '<select id="'.$field['id'].'" name="'.$field['id'].'">';
foreach ($field['options'] as $key => $value) {
$custom_fields = get_post_custom($value);
$bgtypes = $custom_fields['bgtype'];
foreach($bgtypes as $bgkey => $type){
if(strpos($type,'images') !== false):
$images.= '<optgroup label="'.$type.'">'.'<option value="'.$value.'" '.selected($value, $field_val, false).'>'.$key.'</option>'.'</optgroup>';
elseif(strpos($type,'youtube') !== false):
$youtube.= '<optgroup label="'.$type.'">'.'<option value="'.$value.'" '.selected($value, $field_val, false).'>'.$key.'</option>'.'</optgroup>';
else:
$other.= '<optgroup label="'.$type.'">'.'<option value="'.$value.'" '.selected($value, $field_val, false).'>'.$key.'</option>'.'</optgroup>';
endif;
}
}
echo $images;
echo $youtube;
echo $other;
echo '</select>';
On this code I changed the strpos function to if(strpos($type,'images') !== false):
to compare against the actual "bgtype" as the $bgkey variable was returning 0 for all results.
Unfortunately this code still returns the list not grouped by their "bgtypes".
Edit 3: New Code that returns "PostId", "Post Title" & "BGType".
// Get a list of all the created backgrounds
$bgs = get_posts(array(
'post_type' => 'wpbp-backgrounds',
'numberposts' => -1,
'orderby' => 'title',
));
foreach($bgs as $key => $value){
// Post Id
$cpid = $value->ID;
// Post Title
$cptitle = $value->post_title;
// BGType
$custom_fields = get_post_custom($cpid);
$cpbgtype = $custom_fields['bgtype'];
if (isset($custom_fields['bgtype'][0]) && $custom_fields['bgtype'][0]) {
//This is where I would create all the code and group them
}
}
The results of the above code using echo $cpid . ' - ' . $cptitle .' - '.$cpbgtype.'<br>';
are:
2736 - YouTube Video 1 - youtube
2777 - YouTube Playlist video - youtube
2711 - test video 1 - videos
2759 - test image slideshow - images
2670 - test image - images
2747 - Test Hosted Video - videos
2771 - Test Audio File 2 - audio
2693 - Test audio file 1 - audio
2667 - Red Background - solid
2772 - Purple Solid BG Color - solid
2718 - Pattern 1 - pattern
2774 - Image Slideshow Main - images
2773 - Carbon Pattern BG - pattern
2669 - Blue Solid Background - solid
2775 - Another Self Hosted Video - videos
This above code seems to provide all the details for the items. I am just not sure how to group them into optgroup and display them ordered in the dropdown.
Edit 4: Output of var_dump()
If I run this code: var_dump($cpbgtype);
I receive this output:
array(1) {
[0]=>
string(7) "youtube"
}
array(1) {
[0]=>
string(7) "youtube"
}
array(1) {
[0]=>
string(6) "videos"
}
array(1) {
[0]=>
string(6) "images"
}
array(1) {
[0]=>
string(6) "images"
}
array(1) {
[0]=>
string(6) "videos"
}
array(1) {
[0]=>
string(5) "audio"
}
array(1) {
[0]=>
string(5) "audio"
}
array(1) {
[0]=>
string(5) "solid"
}
array(1) {
[0]=>
string(5) "solid"
}
array(1) {
[0]=>
string(7) "pattern"
}
array(1) {
[0]=>
string(6) "images"
}
array(1) {
[0]=>
string(7) "pattern"
}
array(1) {
[0]=>
string(5) "solid"
}
array(1) {
[0]=>
string(6) "videos"
}
However if I run this code var_dump($custom_fields['bgtype'][0]);
I receive this output. Not sure which one to call as this one is actually how I can refer to each "bgtype"
string(7) "youtube"
string(7) "youtube"
string(6) "videos"
string(6) "images"
string(6) "images"
string(6) "videos"
string(5) "audio"
string(5) "audio"
string(5) "solid"
string(5) "solid"
string(7) "pattern"
string(6) "images"
string(7) "pattern"
string(5) "solid"
string(6) "videos"
Edit 5: Output of var_dump($custom_fields)
array(14) {
["_edit_lock"]=>
array(1) {
[0]=>
string(12) "1421540192:1"
}
["_edit_last"]=>
array(1) {
[0]=>
string(1) "1"
}
["bgtype"]=>
array(1) {
[0]=>
string(7) "youtube"
}
["poster"]=>
array(1) {
[0]=>
string(70) "http://localhost/wordpress-dev/wp-content/uploads/2015/01/mash_ups.png"
}
["volume"]=>
array(1) {
[0]=>
string(2) "10"
}
["mute"]=>
array(1) {
[0]=>
string(4) "true"
}
["showplay"]=>
array(1) {
[0]=>
string(4) "true"
}
["showmute"]=>
array(1) {
[0]=>
string(4) "true"
}
["paused"]=>
array(1) {
[0]=>
string(5) "false"
}
["loopvideo"]=>
array(1) {
[0]=>
string(5) "false"
}
["ytbtnbg"]=>
array(1) {
[0]=>
string(7) "#565656"
}
["ytbtntxt"]=>
array(1) {
[0]=>
string(7) "#ffffff"
}
["video_controls"]=>
array(1) {
[0]=>
string(11) "bottom_left"
}
["playlist"]=>
array(1) {
[0]=>
string(59) "ZKa8OEPCZrg,goKm9Oafs3E,OCHy1nUdfu8,mpCFLr0NPjA,i3WX-VeNKmk"
}
}
From this var_dump() I am after the BGType which in this case is:
["bgtype"]=>
array(1) {
[0]=>
string(7) "youtube"
}
This is whats returned for each individual background I call when in the loop
you could do a simple if test to see what the $key contains...
$field_val = get_post_meta($post->ID, $field['id'], true);
$bgtypes= array('youtube', 'videos', 'images', 'solid', 'audio'); // adjust this to create the headings. As far as i can see this will be more or less consistant?
foreach($bgtypes as $bgkey):
//remove plurals to make checking easier
if (substr($bgkey, -1) == 's')
$bgkey = substr($bgkey, 0, -1);
foreach($field['options'] as $option => $key):
if(stripos($option, $bgkey) !==false ):
$options[$bgkey][$option]= $key;
unset($field['options'][$option]);
endif;
endforeach;
endforeach;
$options['other']= $field['options'];
echo '<select id="'.$field['id'].'" name="'.$field['id'].'">';
foreach($options as $item=>$key):
echo '<optgroup label="'.$item.'">';
foreach($key as $line=>$data):
echo '<option value="'.$data.'" >'.$line.'</option>';
endforeach;
echo '</optgroup>';
endforeach;
echo '</select>';
i had to guess as to the output of some of the arrays but it should be close enough.
Answer to 3rd edit:
$bgs = get_posts(array(
'post_type' => 'wpbp-backgrounds',
'numberposts' => -1,
'orderby' => 'title',
));
foreach($bgs as $key => $value){
// Post Id
$cpid = $value->ID;
// Post Title
$cptitle = $value->post_title;
// BGType
$custom_fields = get_post_custom($cpid);
$cpbgtype = $custom_fields['bgtype'][0];
// since the data is associated with the post its easier to implement.
if (isset($custom_fields['bgtype'][0]) && $custom_fields['bgtype'][0]) {
$output[$cpbgtype][]= '<option value="'.$cpid.'" >'.$cptitle.'</option>' ;
}
}
echo '<select id="'.$field['id'].'" name="'.$field['id'].'">'; // dont know if the $field values are still there
foreach($output as $type=>$data):
echo '<optgroup label="'.$type.'">';
foreach($data as $item):
echo $item;
endforeach;
echo '</optgroup>';
endforeach;
echo '</select>';