Tagphp

Querying Custom Post Types with Page Navigation on Front Page

I was experimenting with displaying custom post types on the front page of a wordpress site using various methods.

I had first tried using get_posts(), but it couldn’t deal with pagination.

The next alternative was to use WP_Query(). At first I had tried to implement this in the home.php template, but next_posts_link() returned an error 404. It had teh same result when I tried in on front-page.php.

My last try was to implement this as a page template, and in the “Reading Settings” of the WordPress admin, selected to display a static page that used the page template.

static_front_page_setting

This made a difference, and it worked. So I’ve come to the conclusion that when implementing a solution to display custom post types with pagination on a website’s home page, using WP_Query() through a page template is the optimal way to do so.

Here’s the final code:

//get the correct paged figure on a static page - see related note (a)
if ( get_query_var('paged') ) {
   $paged = get_query_var('paged');
}
elseif ( get_query_var('page') ) {
   $paged = get_query_var('page');
}
else {
   $paged = 1;
}

// Query Custom Post Type posts. WP_query instead of get_posts for pagination purposes
$custom_posts = new WP_Query(
   array(
      'post_type' => 'my_custom_post_type',
      'paged' => $paged
   )
);

// Start the loop
if ( $custom_posts->have_posts() ) :
   while ( $custom_posts->have_posts() ) :
      $custom_posts->the_post();
      get_template_part( 'content-archive', get_post_type() );
   endwhile;
   wp_reset_postdata();
endif;

// next_posts_link() usage with max_num_pages - see related note (b)
next_posts_link( 'Older Entries', $custom_posts->max_num_pages );
previous_posts_link( 'Newer Entries' );

Related notes:
(a) https://codex.wordpress.org/Pagination
(b) https://codex.wordpress.org/Function_Reference/next_posts_link

Converting HTML entities to characters

I was trying to use WordPress post titles as email subject headers in such a way:

$subject = get_the_title();
wp_mail( $to, $subject, $message);

However this became a problem when the post title included smart quotes, em-dash, ellipsis and the likes of them. My email subject ended up looking like this:

Hey – This is my Post’s Title

where it should have been:

Hey - This is my Post's Title

Well, I solved this by using the php function html_entity_decode before sending the $subject to wp_mail():

$subject = html_entity_decode( get_the_title(), ENT_QUOTES, 'UTF-8' )

ENT_QUOTES denotes converting both double and single quotes. The last parameter defines the character set – it is set as UTF-8 since smart quotes and em-dashes are part of the UTF-8 set.

Using a proxy file to load content from external url

/* proxy.php */
<?php echo file_get_contents($_GET['url']);?>

then, assuming that you place proxy.php in the same directory of the html page:

$("#content").load('proxy.php?url=http://example.com');

PHP Dynamic Variables

This is otherwise known as “Variable variables”. Let’s begin.

Basically in PHP, we assign value to a variable like this:

$var = "word";

If we want a variable whose name is the value of the $var variable, we do so like this:

$$var = "press"; // $word = "press"

PHP parses $$var by first de-referencing the innermost variable, which means that $var becomes “word”. The expression that’s left is $word. This defines a new variable named word and assigned it the value “press”. We can nest dynamic variables to an infinitely in PHP, although this is not recommended because it can be very confusing once it gets beyond 2 to 3 levels.

There is a special syntax for using Variable variables, and any other complex variable, by calling the variable inside curly brackets:

echo "${$var}";

This syntax also helps resolve an ambiguity that occurs when defining Variable arrays. In order to use Variable variables with arrays, you have to resolve an ambiguity problem. That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable. The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.

Variable variables may not seem that useful and even confusing, but there are times when they can reduce the amount of code needed. For example, in an associative array that looks like:

$array[“hello”] = “word”;
$array[“world”] = “press”;

Associative arrays like this are returned by various functions in the PHP modules. mysql_fetch_array() is one example. The indices in the array usually refer to fields or entity names within the context of the module you are working with. It’s handy to turn these entity names into real PHP variables, so you can refer to them as simply $hello and $world. This is done as follows:

foreach( $array as $index=>$value ) {
    $$index = $value;
}

WordPress 3.1 and setup_postdata

After upgrading one of my websites to WordPress to version 3.1, the loops that contained setup_postdata() created a mess. After some testing, I realised that setup_postdata() will only return the correct data if the argument passed is $post, i.e. setup_postdata($post). I had used setup_postdata( $ancestor ) instead and it created a mess after the upgrade.

Now I had this running in my code:

foreach( $ancestors as $ancestor )  {
   setup_postdata( $ancestor );
   // Do things with the_title()
   // Do things with the_post_thumbnail()
   // Do things with the_permalink()
   // Do things with get_post_custom()
   // Do alot of other things with $ancestor
}

I could solve this mess by changing to the below code, but this required changing all $ancestor variables to $post

foreach( $ancestors as $post )  {
   setup_postdata( $post );
   // Do things with the_title()
   // Do things with the_post_thumbnail()
   // Do things with the_permalink()
   // Do things with get_post_custom()
   // Do alot of other things with $post 
}

But I reckoned it wasn’t as efficient, and also it might create more bugs due to the edit of so many variable calls. In the end I opted for a quick fix to pass $ancestor into the $post variable just before setup_postdata( $post ). In this way, I’ll still able to get the correct data from the_title(), the_post_thumbnail(), the_permalink() and get_post_custom(), without having to change all $ancestor calls to $post that come after.

foreach( $ancestors as $ancestor )  {
   $post = $ancestor;
   setup_postdata( $post );
   // Do things with the_title()
   // Do things with the_post_thumbnail()
   // Do things with the_permalink()
   // Do things with get_post_custom()
   // Do alot of other things with $ancestor
}

Ok, hope this might be useful if you faced the same issue. Anyone has alternative solutions?

Ways to load template files in WordPress

The below methods mostly uses get_template_directory() to retrieve the parent theme directory and get_stylesheet_directory() if you are using a child theme and retrieving the  of  child theme directory.

Using include() and require()

These are built-in PHP functions and you can use them to load template files like this. Note that they do not check file existence, and you’ll get an error if the file do not exist.

include( get_template_directory() . '/file.php' );
require( get_template_directory() . '/file.php' );
include( get_stylesheet_directory() . '/file.php' );
require( get_stylesheet_directory() . '/file.php' );
include( get_template_directory() . '/subdir/file.php' );
require( get_template_directory() . '/subdir/file.php' );
include( get_stylesheet_directory() . '/subdir/file.php' );
require( get_stylesheet_directory() . '/subdir/file.php' );

You can also use include_once() and require_once().

Using load_template()

load_template() is a WordPress function that works just like include() and require(). It does not check for file existence as well.

load_template( get_template_directory() . '/file.php' );
load_template( get_stylesheet_directory() . '/file.php' );

Using locate_template()

locate_template() checks for file existence. It searches files in both parent theme and child theme directory, and overloads from the child theme.

locate_template($template_names, $load, $require_once);
  • $template_names can be a single filename or an array of names.
  • $load is a boolean parameter. It defaults to false and when true, the searched file(s) are loaded.
  • $require_once is a boolean parameter and defaults to true – when true, it loads the file using php require_once() function, else it loads using php require().

You can code it like this

locate_template( 'file.php', true );
locate_template( 'subdir/file.php, true );
locate_template( array( 'file1.php', 'file2.php' ), true);

Using get_template_part()

get_template_part() (as of WordPress 3.0) loads a template part into a template (other than header, sidebar, footer). This makes it easier for a theme to reuse sections of code in an easy to overload way if using child themes. This function will load a file named “{slug}-{name}.php”. The $name is optional, and if it’s empty, the function will include file named “{slug}.php”.

get_template_part( $slug, $name );

If you want to load a file named options-general.php, you can code it like this:

get_template_part( 'options', 'general' );

If you want to load from a subdirectory, you can code it like this:

get_template_part( 'subdir/options', 'general' );

Best Practices

Although there are several ways to load files in WordPress, we have to consider carefully which methods are best for particular cases. Considerations might include whether we want to allow child themes to overwrite certain functions etc. Justin Tadlock has written a comprehensive article on how to load files within WordPress themes, and gives ample analysis for best practices.

© 2017 Bucket Press

Top