1. WordPress Has A Ton Of Built-In Scripts
Using the great
wp_enqueue_script()
and
wp_enqueue_style()
, you can include styles and scripts easily with dependency management. But did you know that WordPress has a lot of scripts already built in? jQuery, many elements of jQuery UI, jQuery Form, SWF Object, Tiny MCE, Jcrop and Thickbox are just some the better known ones. The whole list can be
found in the WordPress Codex. If you’re interested in learning how to use the enqueue functions effectively, I recommend “
The Developer’s Guide to Conflict-Free JavaScript and CSS in WordPress” right here on Smashing Magazine!
2. Replace Built-In Scripts By Deregistering Them
If you live on the bleeding edge, you can use versions of scripts other than the built-in ones. Using a newer jQuery version is common (though not necessarily good) practice, which can be done in the following way.
function my_scripts_method() {
wp_deregister_script( 'jquery' );
wp_register_script( 'jquery', get_template_directory_uri() . '/js/jquery-new.js');
wp_enqueue_script( 'jquery' );
}
add_action('wp_enqueue_scripts', 'my_scripts_method');
But do not do this just to brag about using latest stuff. WordPress includes the version of jQuery that it does to ensure maximum compatibility.
Use another version of jQuery only when encountering compatibility issues, such a plugin that specifically requires it.
3. Force Perfect JPG Images
This is a classic example of why working on a team is beneficial. My good friend Lars told me that WordPress doesn’t use 100% quality for images served on the website, to conserve space and bandwidth. He also showed me a solution, of course:
add_filter( 'jpeg_quality', 'smashing_jpeg_quality' );
function smashing_jpeg_quality() {
return 100;
}
WordPress uses a default quality of 90%. This is fine in most cases; I doubt many people can see the difference. But if top-notch image quality is a must on your website (for a portfolio, photography, etc.), modifying the value might be best.
4. FeedBurner Redirection
FeedBurner is used on almost every blog that I’ve worked on, and yet I never know how exactly to set it up by heart. Thanks to Elio for writing “
10 Tips to Optimize Your WordPress Theme,” which contains this snippet:
add_action( 'template_redirect' , 'smashing_rss_redirect');
function smashing_rss_redirect() {
if ( is_feed() AND !preg_match( '/feedburner|feedvalidator/i', $_SERVER['HTTP_USER_AGENT'] ) ){
header( 'Location: http://feeds.feedburner.com/my_smashing_feed' );
header( 'HTTP/1.1 302 Temporary Redirect' );
}
}
5. Using General Taxonomy Functions
A number of taxonomy functions can handle your custom taxonomies as well as the built-in tags and categories. The Codex’s
reference of functions contains the full list of taxonomy functions. I particularly like using
get_term()
,
get_terms()
and
wp_get_object_terms()
. To make things more modular, I use these functions as much as I can, even for tags and categories.
6. Setting Up Sessions In WordPress
Sessions are great for storing information between pages and are widely used on websites. WordPress doesn’t use them at all internally, so the session is never set. Using the following method, you can start a session on all pages before any output.
add_action( 'init', 'smashing_session_start' );
function smashing_session_start() {
if ( !session_id() ) {
session_start();
}
}
Note that, while sessions are generally pretty safe, implement IP checking or added nonce protection just to be on the safe side. As long as you’re transmitting non-sensitive data, though, you’ll fine. Check out Mark Jaquith’s great
article on nonces for more info.
7. List All Hooked Functions
I started writing a function to do this. When I did a quick Google search, it turned out that
WP Recipes had exactly what I needed.
function list_hooked_functions($tag=false){
global $wp_filter;
if ($tag) {
$hook[$tag]=$wp_filter[$tag];
if (!is_array($hook[$tag])) {
trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
return;
}
}
else {
$hook=$wp_filter;
ksort($hook);
}
echo '<pre>';
foreach($hook as $tag => $priority){
echo "<br />>>>>>t<strong>$tag</strong><br />";
ksort($priority);
foreach($priority as $priority => $function){
echo $priority;
foreach($function as $name => $properties) {
echo "t$name<br />";
}
}
}
echo '</pre>';
return;
}
Used without an argument, you’ll get a nice list of all hooked functions. This will be a bit long, so you can specify a hook to narrow the list a bit. This is particularly useful when debugging or fiddling around with hook priorities. Knowing what’s hooked intowp_head()
in what order is important, and this function is a great asset!
8. Automatically Add Paragraph Tags To Anything
WordPress does this automatically to the content and the excerpt, but there’s no reason not to use it elsewhere. The function responsible for turning double line breaks into paragraphs is
wpautop()
.
$my_text = 'Welcome!
Smashing Magazine is a great place to learn new things.
I hope you’re having a nice time!';
echo wpautop( $my_text );
Sometimes you’ll want to disable this filter by default, which you can do by removing it from the content and excerpt, like so:
remove_filter( 'the_content', 'wpautop' );
remove_filter( 'the_excerpt', 'wpautop' );
9. Send Emails Using WordPress
$message = 'Hello, thanks for reading my post! I hope to see you back soon.';
wp_mail( 'someonesemail@example.com', 'Thanks for reading my post!', $message);
You can also send HTML content by using a filter:
add_filter ("wp_mail_content_type", "smashing_mail_content_type");
function smashing_mail_content_type() {
return "text/html";
}
10. Native Pagination Links
It came as a surprise to me about six months ago that you don’t need any plugins to pull off proper paging (i.e. not just “Previous” and “Next” links); you can do it with a native function. The paginate_links()
function is a handy little thing that lets you show pagination for any type of content, not just a WordPress loop.
$list = new WP_Query( $query_args );
$pagination = array(
'base' => str_replace( 99999, '%#%', get_pagenum_link( 99999 ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $list->max_num_pages,
'next_text' => 'next',
'prev_text' => 'previous'
);
echo '<div class="pagination primary-links">' . paginate_links( $pagination ) . '</div>';$list = range(1, 100);
$items_per_page = 12;
$pagination = array(
'base' => get_bloginfo( 'url' ) . '/mypage/%_%',
'format' => '?paged=%#%',
'current' => $_GET['current_page'],
'total' => ceil( max($list) / $items_per_page ),
'next_text' => 'go forth',
'prev_text' => 'go back'
);
echo '<div class="pagination primary-links">' . paginate_links( $pagination ) . '</div>';
11. Upload Files With Ease
WordPress has a bunch of great uploading functions for everything from checking the file type to finding the uploads directory. A more obscure function is
wp_upload_bits()
, which you can use to upload a file to the uploads directory.
$upload = wp_upload_bits( $_FILES['myfile']['name'], null, file_get_contents( $_FILES['myfile']['tmp_name'] ) );
echo 'Well uploaded! The path to this file is ' . $upload['file'] . ' and the url to this file is ' . $upload['url'];
12. Twitter-Like Time Display
This was another shock to me a while back, especially since it has been in WordPress since version 1.5! If you’d like to show viewers a relative date in a human-readable format, like “5 minutes ago” or “one month ago,” try the
human_timed_diff()
function.
$diff = human_time_diff( '2012-05-05 12:05:00', '2012-05-05 12:10:00' );
echo 'This comment was submitted ' . $diff . 'ago';
13. Log In As Any User
If you’re building a complex website with many roles, being able to switch between them quickly and easily would be useful. The
wp_set_auth_cookie()
lets you log the current user in based on ID.
$user_id = 4;
wp_set_auth_cookie( $user_id );
Take great care when using this function; left unchecked, it could log every user in as user number 4. Even while testing, I target it specifically to my IP, and maybe even to a special URL string just to be sure. That said, with proper safety, it can be used as part of a custom log-in script.
14. Add Custom Profile Fields In The Admin Area
I can’t say that WordPress offers much in the way of profile customization in the administration area. Especially nowadays, when you want to show the Twitter and other social accounts of authors, this is a shortcoming. It can be fixed easily, though. Have a look here:
<?php
add_action( 'show_user_profile', 'smashing_profile_fields' );
add_action( 'edit_user_profile', 'smashing_profile_fields' );
function smashing_profile_fields( $user ) {
?>
<h3>Social Sites</h3>
<table class="form-table">
<tr>
<th><label for="twitter">Twitter</label></th>
<td>
<input type="text" name="twitter" id="twitter" value="<?php echo esc_attr( get_the_author_meta( 'twitter', $user->ID ) ); ?>" /><br />
<span class="description">Your Twitter Username</span>
</td>
</tr>
<tr>
<th><label for="twitter">Facebook</label></th>
<td>
<input type="text" name="facebook" id="facebook" value="<?php echo esc_attr( get_the_author_meta( 'facebook', $user->ID ) ); ?>" /><br />
<span class="description">Your Facebook Profile URL</span>
</td>
</tr>
<tr>
<th><label for="twitter">Linkedin</label></th>
<td>
<input type="text" name="linkedin" id="linkedin" value="<?php echo esc_attr( get_the_author_meta( 'linkedin', $user->ID ) ); ?>" /><br />
<span class="description">Your Linkedin Profile URL</span>
</td>
</tr>
</table>
<?php
}
add_action( 'personal_options_update', 'smashing_save_profile_fields' );
add_action( 'edit_user_profile_update', 'smashing_save_profile_fields' );
function smashing_save_profile_fields( $user_id ) {
if ( !current_user_can( 'edit_user', $user_id ) )
return false;
update_user_meta( $user_id, 'twitter', $_POST['twitter'] );
update_user_meta( $user_id, 'facebook', $_POST['facebook'] );
update_user_meta( $user_id, 'linkedin', $_POST['linkedin'] );
}
15. Sanitize URLs With Ease
When working with URLs, always make sure they are properly formed and don’t contain any invalid or dangerous characters. The
esc_url() function lets you do just that.
$my_url = 'http://mypage.com/?awesome=true';
$url = esc_url( $my_url );
Be sure to check out all of the other escape functions. You can find a list of them at the bottom of the page that I linked to in the related section.
16. Empower Text Widgets
To make text widgets so much better, you can enable the use of shortcodes in them. This is a great tool for theme developers because it makes your product much more flexible for the user.
add_filter( 'widget_text', 'do_shortcode' );
17. Add Custom Post Types To The RSS Feed
Not being able to do this easily from the admin area is a big issue. Many website owners separate their content into custom posts, and they also want all of their items to show up in the feeds. Never fear — a function is here!
add_filter('request', 'smashing_custom_feed');
function smashing_custom_feed( $vars ) {
if ( isset( $vars['feed'] ) ) {
$vars['post_type'] = get_post_types();
}
return $vars;
}
While this is great, it forces all of your post types into the feed. If you’d like to add just some of your custom post types to the feed, you can list them separately.
add_filter('request', 'smashing_custom_feed');
$post_type_list = array( 'post', 'products' );
function smashing_custom_feed( $vars ) {
if ( isset( $vars['feed'] ) AND !isset( $vars['post_type'] ) ) {
$vars['post_type'] = $post_type_list;
}
return $vars;
}
18. Don’t Break WordPress Loops
Multiple loops are great but can wreak havoc if not used correctly. To make sure your loop runs smoothly and you can still use all of the functions that rely on globals, store the original query in a temporary variable.
$tmp_query = $wp_query;
query_posts('cat=5&order=ASC');
while( have_posts() ) : the_post()
?>
<a href="<?php the_permalink() ?>'><?php the_title() ?></a><br />
<?php
$wp_query = $tmp_query;
19. Custom Database Queries
If you need something more than what the default WordPress functions give you, you can use
$wpdb
, the WordPress database class to query the database directly.
$recent_users = $wpdb->get_results( "SELECT display_name, user_registered FROM $wpdb->users ORDER BY user_registered DESC LIMIT 0,10" );
20. Customize WordPress Post Revisions
The post revisions feature in WordPress is great, but the majority of users don’t use it. Database entries are created for revisions, even if they are not used. While they’re not a huge hit on your server’s performance, if you don’t use revisions, you can disable them by placing the following code in your wp-config.php
file.
define( 'WP_POST_REVISIONS', FALSE );define( 'WP_POST_REVISIONS', 5 );
20. Styling Author Comments
If you’d like author comments to jump out, simply use the bypostauthor
class in your CSS.
li.bypostauthor {
background:#fafafa;
color:#555;
}
21. Storing Your Whole Page In A Variable
In some cases, storing your whole output in a variable can be very helpful. This allows you to make global changes, compress or obfuscate code and more very easily. All we need is PHP output buffering and two hooks.
add_action('wp_head', 'smashing_buffer_start');
add_action('wp_footer', 'smashing_buffer_end');
function smashing_buffer_start() {
ob_start( 'smashing_callback' );
}
function buffer_end() {
ob_end_flush();
}
function smashing_callback( $content ) {
$content = str_replace( 'great', 'awesome', $content );
echo $content;
}