#wcphx: Five tenets to mastering WordPress development

Enlightenment is knowing what your code is doing and why. Thankfully, instead of having to depend on your inner calm, there are a number of tools and strategies you can use to better see what’s going on. We’ll survey a range of topics you should explore to turn your frustration into bliss.

Feeling better already? In this session, we’ll touch on everything from debugging to best practices to coding standards to version control to performance and optimization. You’ll hear the insights WordPress.com VIP shares every day.

Session notes are below the slides.

Who am I?

My name is Daniel Bachhuber and I work as a code wrangler on Automattic’s WordPress.com VIP team. We work with publishers like TIME, The New York Times, TechCrunch, Cheezburger, and more who use WordPress at scale.

The point of this presentation is to cover the things you mostly learn the hard way. Now you can learn them the easy way. Some of these topics were covered by Erick’s talk this morning… I’ll quickly review.

Why is this talk important?

  • Make your code secure, performant, and protect against the future
  • Let others love your code too

1. Do it locally

Set yourself up for success

→ WP_DEBUG opens your eyes

Why:

  • It’s a quick and easy way to see what’s going wrong with your code for fatal errors
  • See PHP notices and other things you might normally miss
  • Make sure you’re using the best WordPress functions for the job

WP_DEBUG does the following:

  • Turns on the display of PHP errors and warnings
  • Triggers notices for deprecated functions

Slide: Show the whitescreen of death and then with WP_DEBUG on

5 ways to debug WordPress” and “Debugging WordPress” – Andrew Nacin

→ Know thy codebase; when in doubt, ack

Why:

  • Code is gospel. You might read tutorials or examples on the web that say one thing or the other; code will tell you the truth.
  • Reading code is a literacy of WordPress development. Dive into it to figure out what’s going on.

Use ack to quickly search your code base. It’s better and faster than grep.

Slides: Different usages of ack

Some usage:

  • ack ‘function my_function_name’ for the source of a function
  • ack ‘/crazy-regex/’

Slide: Files you might commonly need to reference

[sourcecode language=”php”]
// Some of your functions for sanitizing input
// and formatting output, including esc_*(),
// sanitize_*(), and capital_P_dangit()
wp-includes/formatting.php

// Post manipulation, including
// register_post_type(), get_posts(), etc.
wp-includes/post.php

// Reference for modifying the Query
wp-includes/query.php

// Functions you can override in your theme
// or plugin
wp-includes/pluggable.php
[/sourcecode]

→ Install Debug Bar, it’s like Firebug for your WordPress

By default, the Debug Bar gives you information about the execution of the page.

Slide: Debug Bar by default

Define SAVEQUERIES to do the following:

  • Saves each query
  • Identifies which function calls it
  • Saves how long it took to run

Slide: Debug Bar with SAVEQUERIES

Debug Bar Extender adds some profiling information

Slide: Debug Bar Extender

→ Use version control and write descriptive commit messages

Version control is an awesome historical record of your project. SVN and Git are two popular types of version control, the former is used for the WordPress.org project and the latter was popularized by Github, a social coding site.

Version control gives you these advantages:

  • More easily communicate the changes you’re making with the rest of your team.
  • Work on multiple features at the same time.
  • Roll back if necessary; better than backups.
  • Automated deployment — no more copy and pasting over FTP.

Slide: What a diff on Github looks like

What makes a good commit message:

  • Consider your audience: writing for coworkers and for historical purposes.
  • Explain why you made the change, not what it was. What it was should be self-explanatory from the code
  • Link to Trac tickets or other relevant conversation.

Slide: What good and bad commit messages look like

Neat example of Wired Magazine accepting contributions via Github for an article.

2. Follow best practices

Let others love your code too

→ Don’t modify core. Do extend it properly.

Why: your changes will get blown away, you won’t upgrade regularly, and the sky will fall on your head.

WordPress has an extensive system of action and filter hooks you can use to extend functionality and modify values. It’s the “window into WordPress”.

Sometimes you will need to do ugly workarounds. Don’t worry, it’s better than modifying core.

Slide: Filter workaround for core problem with custom statuses

If you find something limiting in the API, open a Trac ticket!

→ Prefix all the things

Prefix all of your functions and variables to avoid collisions; better yet, write your functionality into classes.

In WordPress, prefix everything” – Andrew Nacin

Slide: Example of non-prefixed vs. prefixed

→ Coding standards are standards for a reason

Why: You’re not the only one working with your code. WordPress’ coding standards are a common language for others to understand your code.

  • Tabs, not spaces, for indentation. Allows the most flexibility between clients.
  • under_score for functions and variables. Everyone else does.
  • Capitalize_Classes. This too.
  • use-hyphens-to-separate-words-in-files.php. This three.

Slide: The coding standards I run into most commonly with VIP

3. Use the correct hooks and APIs

There are so many

→ Use the WP_HTTP class for remote requests

The transport mechanisms available for WordPress to use vary from server to server, especially if you’re releasing code to be used on shared servers. That’s why you should use the WP_HTTP class… it uses the best mechanism available.

Slide: different HTTP functions you can use

→  Find the proper action for your action

‘init’ isn’t everything. Invest some time into finding the right action to avoid bugginess later. Make sure all order of execution code in your functions.php and/or plugin is hooked into an action.

‘after_setup_theme’ is a good place for:

  • Registering nav menus
  • Setting your post thumbnail sizes
  • Adding theme support

Slide: after_setup_theme

‘wp_enqueue_scripts’ is where you should enqueue all of your scripts and styles. Define a dependency if you need to. Enqueuing on ‘wp_print_styles’ may cause issues.

You can also minimize HTTP requests by only enqueuing them on the pages you need them.

Slide: wp_enqueue_scripts

Others:

  • ‘add_meta_boxes’ is a good place to register your meta boxes
  • ‘admin_menu’ for adding admin menus
  • ‘widgets_init’ is a good place for registering widgets

4. Protect yourself

Don’t trust strangers

→ Properly handle your user-submitted data

Validate that the data is what you need. Follow a whitelist approach

Sanitize what the user has submitted:

  • sanitize_text_field() // strips tags, checks for invalid UTF-8, remove line breaks, tabs and extra white space
  • intval() // integer value
  • wp_filter_post_kses() // sanitize for allowed HTML tags and attr
  • sanitize_title() // strip PHP and HTML tags
  • sanitize_key() // lowercase alphanumeric characters, dashes and underscores

Slide: All of the core sanitize functions you can use

Make sure you sanitize your data at the point of accessing it.

Slide: Sanitize at the point of using your data

Data Validation” in the WordPress.org codex
wp-includes/formatting.php includes all of the functions

→ Escape data on output

There are different escaping functions you can use to protect your HTML. Make sure your HTML is what it’s supposed to be:

  • esc_html() // escape for data within HTML, checks for invalid UTF-8
  • esc_attr() // escape for HTML attributes, checks for invalid UTF-8
  • esc_js() // escape single quotes, htmlspecialchar ” < > &, fix line endings.
  • esc_textarea() // escapes data for use in a textarea
  • esc_url() // removes a bunch of invalid characters from your URL, makes it good

Slide: Different escaping functions you can use

Slide: Escape at the point of printing data

→ Nonce (numbers used once) to make sure people are who they say they are

Use Nonces for security (XSRF) and checking user intention (Edit vs. Quick Edit)

Nonces are temporary (24 hours), tied to specific users (if authenticated) and actions, and in some cases, referrers.

Slide: Adding a nonce to your form, and then checking for it on form process

WordPress 2.0.3: Nonces” – Mark Jaquith

→ When you must use SQL, $wpdb->prepare()

$wpdb->prepare() properly escapes strings.

Use %s and %d depending on whether you’re using a string or a digit; quote marks will be auto-added for strings.

Slide: Usage of $wpdb->prepare

Protect queries against SQL injection attacks” in the WordPress.org codex.

5. Optimize

Performance matters — make it fast

→ Know your Query

query_posts() should be used in one and only case if you need to modify main query of page. It sets a lot of global variables and will lead to obscure and horrible bugs if used in any other place and for any other purpose.

get_posts() is very similar in mechanics and accepts same arguments, but returns array of posts, doesn’t modify global variables and is safe to use anywhere.

WP_Query class power both behind the scenes, but you can also create and work with own object of it. Bit more complex, less restrictions, also safe to use anywhere.

Slide: Different ways of the Query

WP_Query actually does four SQL queries

  • Main posts get
  • postmeta get
  • taxonomy terms get
  • SQL calc rows

Slide: How you can disable extra queries on the Query

Slide: How you should modify the query

When should you use WP_Query vs query_posts() vs get_posts()?
You don’t know Query” – Andrew Nacin

→ Cache expensive data

If a given set of data takes more than ~200 ms to generate, you should cache it.

WordPress has three different types of caching:

  • Transients -Transient data, persistent across page loads but could expire at any time.
  • Object cache – Page load by page load, unless you use an object caching backend like memcache or APC.
  • Options – Data will always persist, maybe can’t handle a lot of it.

→ Cache remote requests, or offload to the frontend

Remote requests are when your code has to pull some data from somewhere else. Retrieving that data can be expensive. Uncached, every millisecond the remote request takes are milliseconds added to the page load. And these are for every visit to your site.

Sometimes, we can rely on the API to be fast enough that we can just request and cache on the frontend.

Slide: Remote request on the PHP end

Oh, but we actually need new live data all the time. Trying to invalidate the cache and repopulate all of the time is bad news bear. Let’s just move this to some Javascript on the frontend

Slide: Offload the request entirely to the frontend

The beginning

The best thing you can do is read others’ code and share your own. If you have a friend or colleague you can match up with, swap code and leave feedback for each other. It’s tremendously beneficial for both parties. A good WordPress developer never stops learning.