Best Practices for Plugin Development
Core Developer, WordPress.org Tech Ninja, Audrey Capital
@nacin
how not to write a plugin
ur doin it wrong
DEVELOPERS: Y U NO CODE WELL
One of these things is not like the others
lsp_add_scripts() lsp_add_custom_meta() lsp_create_html() lsp_save_meta() install()
function nacin_project_func_name() {}
class Nacin_Project { function __construct() {} function init() {} function activate() {} }
class Nacin_Project { static $instance; function __construct() { self::$instance = $this; } } new Nacin_Project;
class Nacin_Project { function __construct() { add_action( 'init', array( $this, 'init' ) ); } function init() { // Add hooks here } }
HTTP Make HTTP requests
cURL example
Let’s fetch a URL: $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,
true); curl_setopt($ch, CURLOPT_HEADER, false); Curl_setopt($ch, CURLOPT_FOLLOWLOCATION,
true); $result = curl_exec($ch); curl_close($ch);
var_dump( function_exists( 'curl_init' ) );
bool(false)
And what about:
§ Cookies § Headers § Proxies
§ HTTP Auth § POST § Timeouts
wp_remote_request( $url, $args = array() );
Pick a card, any card
cURL streams
fopen fsockopen
HTTP extension
2000 lines of work already done for you
Helpers We make it so easy.
Functions designed for filters
__return_true(); __return_false(); __return_zero(); __return_empty_array();
Serialization maybe_serialize(); maybe_unserialize(); is_serialized(); is_serialized_string();
Server helpers apache_mod_loaded($module); got_mod_rewrite(); insert_with_markers(); extract_with_markers();
URLs
Bad: Better: Yes:
get_option('home'); get_bloginfo('url'); home_url();
URLs
Bad: Better: Yes:
get_option('siteurl');
get_bloginfo('wpurl');
site_url();
Bad: ABSPATH. 'wp-‐content/plugins/nacin'
Still bad: WP_CONTENT_DIR . 'plugins/nacin'
Better: WP_PLUGIN_DIR . '/nacin' Yes: dirname( __FILE__ )
Bad: get_bloginfo('url') . 'wp-‐content/plugins/nacin/a.php'
Better: WP_CONTENT_URL . '/plugins/nacin/a.php'
Yes: plugins_url( 'a.php', __FILE__ )
Default Function Arguments
function myfunc( $args = array() ) { $defaults = array( 'first_arg' => true, 'second_arg' => 'foo' ); $args = wp_parse_args($args, $defaults);
Even allows for query string calls: nacin_my_func( 'first_arg=false' );
Post Types Taxonomies
Widgets Shortcodes
Options Transients
Cache Cron
Formatting HTTP
Embeds
Settings Capabilities Templates
Query i18n/L10n
Admin Menus Meta Boxes
Multisite Updates
Filesystem Admin Bar
Other nifty helpers
download_url( $target ); unzip_file( $file, $to );
wp_handle_sideload( $file );
register_activation_hook( __FILE__, 'my_activation_hook');
Ready your plugin (add_option) Set and flush rewrite rules Modify roles/capabilities
register_deactivation_hook( __FILE__, 'my_deactivation_hook');
Restore and flush rewrite rules Restore roles/capabilities But don’t remove your options
Uninstall hook
Clean up after yourself.
uninstall.php
if (!defined('WP_UNINSTALL_PLUGIN')) die(); delete_option('my_plugin_option');
There’s also a hook, like activation and
deactivation, but it has its caveats.
But be considerate of my data.
Here’s a secret…
I hate activation hooks.
Use the right level of the API.
Don’t make any assumptions. Ever.
Friends don’t let friends use direct database queries.
Security. Please. Please. Please.
Authentication vs. Intention
Nonces for CSRF protection. But check
capabilities too.
Plugins can do anything.
Plugins can do anything.
Be considerate of other plugins.
Consult the code.
Documentation is nice, but…
Please…
Read and follow.
the coding standards.
“I love the feeling
I get from my work being used by 30 million .
Benefit from lessons in development and user experience.
(Consultants, hint hint.)
”I learned more in 3 months than I had learned in 3 years .
Thanks!
@nacin
Top Related