I am a PHP novice and wrote this function. It is an alphabetical navigation which shows only the letter that have posts in both that letter and the currently filtered “genero” taxonomy term.
I use multiple taxonomy queries to find “artistas” posts that, for example, are tagged as both “rock” and “funk”.
The function works perfectly and outputs exactly what I want it to, but…
The multiple loops are really lagging the load time and, being the n00b that I am, am uncertain of how to optimize the function.
Any pointers or guidance would be VERY much appreciated. If you want I can trade time for time (i write some mean CSS) 🙂
thank you!
<?php
function bam_artist_alfa() {
$taxonomy = 'alfa';
$uri = my_url();
$home = 'http://buenosairesmusic.com/';
// save the terms that have posts in an array as a transient
if ( false === ( $alphabet = get_transient( 'bam_archive_alphabet' ) ) ) {
// It wasn't there, so regenerate the data and save the transient
$terms = get_terms($taxonomy);
$alphabet = array();
if($terms){
foreach ($terms as $term){
$alphabet[] = $term->slug;
}
}
set_transient( 'bam_archive_alphabet', $alphabet );
}
if(strstr($uri, '/artista/') ) {
$uri = str_replace('/artista/','/?alfa=', $uri);
$uri = substr_replace($uri ,"",-1);
}
$all_link = removeqsvar($uri, 'alfa');
$last = $all_link[strlen($all_link)-1];
if($last == '?') $all_link = substr_replace($all_link ,"",-1);
if($all_link == $home)
$all_link = $home.'artistas';
if( isset($_GET) && isset($_GET['alfa']) ) {
$is_alfa = (!is_tax('alfa') && !$_GET['alfa'] ? false : true );
} else {
$is_alfa = (!is_tax('alfa') ? false : true );
}
$all_current = ($is_alfa == true ? null : ' bg1 round-res' );
?>
<ul class="bbw bo alfa-nav c2">
<li class="all-link<?php echo $all_current; ?>">
<?php if(!$is_alfa) { echo 'A–Z'; } else { ?>
<a href="<?php echo $all_link; ?>">A–Z</a>
<?php }?>
</li>
<?php
$query = $_SERVER['QUERY_STRING'];
$genre = null;
$orden = (isset($_GET) && isset($_GET['orden']) ? '&orden=fecha' : null);
if( strstr($uri,'/genero/') ) {
$genre = str_replace('/genero/','/?genero=', $uri);
$genre = substr_replace($uri ,"",-1);
$genre = explode('/',$genre);
$genre = end($genre);
} elseif( isset($_GET) && isset($_GET['genero']) ) {
$genre = $_GET['genero'];
}
if(!empty($genre)) {
$spaces = strpos($genre,' ');
$genre = ($spaces === false ? $genre : explode(' ', $genre) );
}
function has_artists($i, $genre) {
if(empty($genre)) {
$termquery['tax_query'] = array(
array(
'taxonomy' => 'alfa',
'terms' => $i,
'field' => 'slug',
),
);
$termquery['post_type'] = 'artistas';
} else {
$alfaquery[] = array(
'taxonomy' => 'alfa',
'terms' => $i,
'field' => 'slug',
);
if(is_array($genre)) {
$genres[] = array(
'taxonomy' => 'genero',
'terms' => $genre,
'field' => 'slug',
'operator' => 'AND'
);
} else {
$genres[] = array(
'taxonomy' => 'genero',
'terms' => $genre,
'field' => 'slug',
);
}
$termquery['tax_query'] = array_merge($genres, $alfaquery);
$termquery['tax_query']['relation'] = "AND";
$termquery['post_type'] = 'artistas';
}
$has_artists = get_posts($termquery);
if($has_artists) {
return true;
} else {
return false;
}
}
foreach(range('a', 'z') as $i) :
$current = ($i == get_query_var($taxonomy)) ? "bg1 round-res" : "menu-item";
if(empty($genre)) {
$link = $home.'?alfa='.$i.$orden;
} else {
$genrestring = (is_array($genre) ? implode('+',$genre) : $genrestring = $genre );
$link = $home.'?alfa='.$i.'&genero='.$genrestring.$orden;
}
if ( has_artists($i,$genre) && $i != get_query_var($taxonomy) ){
?>
<li class="<?php echo $current; ?>">
<?php printf('<a href="%s">%s</a>', $link, strtoupper($i) ) ?>
</li>
<?php } else { ?>
<li class="<?php echo $current; if($i != get_query_var($taxonomy)) {echo ' empty';} ?>">
<?php echo strtoupper($i); ?>
</li>
<?php
}
endforeach;
?>
</ul>
<?php } ?>
I would just retrieve an array of alphabet/taxonomy terms that have posts. You do this, but doesn’t actually use it. This function will return an array of non-empty (alphabet) terms:
(Transient? – unless you have multiple post types using this taxonomy, (see below) I’m not sure if much is gained from using transients – and you can just call to
get_terms
and usewp_list_pluck
as shown). The following function uses transients.Don’t forget to update the transient when a post is updated.
This method assumes that the only post type using this taxonomy is ‘artistas’ – if it is being shared then a letter may claim to have artistas associated with it (in your menu) when it does not.
Shared taxonomy work-around
To get round this, you would have to query the posts and then loop through them and collect their terms. Either way – only 1, not 26 queries are being performed to get the ‘used’ alphabet. A transient would be more obviously time-saving in this scenario.
Usage:
I didn’t use the transients API yet but in this case I think it’s a good choice. You use it but only for a small part of the data.
To cache artists per alfa and genre you could do something like this (I assume):