Combine get_page_by_title to exclude pages from wp_list_pages
-
07-03-2021 - |
Question
I am using get_page_by_title
to exclude a few pages from wp_list_pages
, my code looks like:
<?php
$page1 = get_page_by_title('title1');
$page2 = get_page_by_title('title2');
wp_list_pages("title_li=&exclude='.$page1->ID.','.$page2->ID.'")
?>
This code works, but I was wondering if there was any way to combine it so that it could be shorter - something like:
<?php
$pages = get_page_by_title(array('title1','title2'));
wp_list_pages("title_li=&exclude='.$pages->ID.'")
?>
This didn't work, but figured it's pretty close...just thinking the code could be simplified a bit.
Any ideas?
Thanks,
Josh
Solution
get_page_by_title()
source code shows it runs a single mysql query. You can streamline your two calls of the function to be just one query by writing a custom one:
global $wpdb;
$qry = "SELECT ID FROM $wpdb->posts WHERE (post_title = %s OR post_title = %s) AND post_status = 'publish'";
$sql = $wpdb->prepare($qry, 'title1', 'title2' );
$res = $wpdb->get_results( $sql );
$getIDs = array();
foreach ($res as $result)
$getIDs[] = $result->ID;
$exclude = implode(',', $getIDs);
However, I think you should make it less simple, adding a cache to it to reduce the database query of _posts
for such a small thing:
global $wpdb;
if ( false === ( $exclude = get_transient( 'myplugin_exclude' ) ) ) {
$qry = "SELECT ID FROM $wpdb->posts WHERE (post_title = %s OR post_title = %s) AND post_status = 'publish'";
$sql = $wpdb->prepare($qry, 'title1', 'title2' );
$res = $wpdb->get_results( $sql );
$getIDs = array();
foreach ($res as $result)
$getIDs[] = $result->ID;
$exclude = implode(',', $getIDs);
set_transient( 'myplugin_exclude', $exclude, 60*60*24 ); // once a day
}
wp_list_pages("title_li=&exclude={$exclude}");
and now that it's lengthy, I suppose wrapping it in a function wouldn't hurt - help keep things clean and help for reusability:
function get_two_pages_ids_by_titles($title1,$title2,$name) {
global $wpdb;
if ( false === ( $exclude = get_transient( $name ) ) ) {
$qry = "SELECT ID FROM $wpdb->posts WHERE (post_title = %s OR post_title = %s) AND post_status = 'publish'";
$sql = $wpdb->prepare($qry, $title1, $title2 );
$res = $wpdb->get_results( $sql );
$getIDs = array();
foreach ($res as $result)
$getIDs[] = $result->ID;
$exclude = implode(',', $getIDs);
set_transient( $name, $exclude, 60*60*24 ); // once a day
}
return $exclude;
}
Then you could just simply do:
<?php
$exclude = get_two_pages_ids_by_titles('title1','title2','listpages_exclude');
wp_list_pages("title_li=&exclude=".$exclude);
?>
Obviously get_two_pages_ids_by_titles
is a little silly and too specific. Accepting an array of titles and returning one of ids would be better - but this should help guid a way to get what you're after.
🎅🏻 Hope that helps.