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
- 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
→ Know thy codebase; when in doubt, ack
- 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.
- ack ‘function my_function_name’ for the source of a function
- ack ‘/crazy-regex/’
Slide: Files you might commonly need to reference
// 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
→ 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.
- 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.
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.
→ 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
You can also minimize HTTP requests by only enqueuing them on the pages you need them.
- ‘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.
→ 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
→ 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.
“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.
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
→ 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.
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.