Transcript
Page 1: WordPress development paradigms, idiosyncrasies and other big words

WordPress Development Paradigms, Idiosyncrasies

and Other Big Words

Tom Auger, Zeitguys inc.

WordCamp Montreal, 2011

Page 2: WordPress development paradigms, idiosyncrasies and other big words

Introduction

• About me:– Developer of standalone RIAs and large-scale

server-side systems– Siebel integrator and database admin– Perl, PHP, JavaScript, ActionScript 3, SQL,

Python, Java, etc.

– Very much a “DIY Guy”

Page 3: WordPress development paradigms, idiosyncrasies and other big words

Surprising Learning Curve

• Lots of files!

• Confusing themes!

• Arcane symbols!– sprintf(__('Something %s', 'domain'), 'weird');

• Hooks everywhere!– add_action('init', 'obscure_func');– $var = apply_filters('obscure_filter');

• Oh my!

Page 4: WordPress development paradigms, idiosyncrasies and other big words

The biggest challenge...

• was learning what the topics were that I needed to learn about:– themes, templates, template parts and child themes– database access and the WP_Query in all its

instances– action and filter hooks– WordPress object types: posts, taxonomies and meta

data– i18n (l10n) – where to get reliable, high-level information and help

Page 5: WordPress development paradigms, idiosyncrasies and other big words

Meh.

• Let's just go skunkworks.

• I'm a seasoned dev after all...

Page 6: WordPress development paradigms, idiosyncrasies and other big words

DIY Approach = Low Level

• Direct database access

• In-place editing of plugin files

• Forking theme files

• In-place (gasp) editing of core files

• Brute force JavaScript injection

• Rolling your own sanitization and security measures

Page 7: WordPress development paradigms, idiosyncrasies and other big words

The Bad News

• Unsustainable, fragile to updates

• Non-scalable and highly one-off

• Big security gaps

• Missing out on built-in value-add intelligence

• Re-inventing the wheel

Page 8: WordPress development paradigms, idiosyncrasies and other big words

Example: Adding <p> to content

• The starting code:

$posts = get_posts(array(

'post_type' => 'my-custom-type'

));

foreach($posts as $post){

echo '<div>';

echo $post->post_content;

echo '<div>';

}

Page 9: WordPress development paradigms, idiosyncrasies and other big words

Option 1: Manually Wrap

• Wait... what about multiple paragraphs? or enclosing block tags?

$posts = get_posts(array(

'post_type' => 'my-custom-type'

));

foreach($posts as $post){

echo '<div>';

echo '<p>'.$post->post_content.'</p>;

echo '<div>';

}

Page 10: WordPress development paradigms, idiosyncrasies and other big words

Option 1b: RegEx

• Wheel, meet Tom. Tom, meet Wheel.

$blockElements = implode("|", array('ADDRESS','BLOCKQUOTE','CENTER','DIR','DIV','DL', etc...);

$added_p = preg_replace(

'/(?:\s*<('.$blockElements.')(?:\s+[^>]+\s*)*>\s*(.+?)\s*<\/\1>(?:\r|\n|$)*)|(?:\s*(.+?)\s*(?:\r|\n|$|(?=<(?:'.$blockElements.')>))+)/is','<p$1>$2$3<\/p\1>\n', $post->post_content);

Page 11: WordPress development paradigms, idiosyncrasies and other big words

But wait... doesn't WP already do this?

• wpautop(), defined in formatting.php handles all the logic and edge cases

foreach($posts as $post){

echo '<div>';

echo wpautop($post->post_content);

echo '<div>';

}

Page 12: WordPress development paradigms, idiosyncrasies and other big words

So what about the_content()?

• Let's exploit those globals and template tags

foreach($posts as $post){

setup_postdata($post);

echo '<div>';

the_content();

echo '<div>';

}

wp_reset_postdata();

Page 13: WordPress development paradigms, idiosyncrasies and other big words

So how does the_content() do it?

• IDE – site-wide search (or use phpxref or WPSeek)

• In post-template.php:

function the_content($more_link_text = null, $stripteaser = 0) {$content = get_the_content($more_link_text, $stripteaser);$content = apply_filters('the_content', $content);$content = str_replace(']]>', ']]&gt;', $content);echo $content;

}

Page 14: WordPress development paradigms, idiosyncrasies and other big words

Keep following the White Rabbit

• Search for "the_content" within default-filters.php• It runs the following functions:

– capital_P_dangit– wptexturize– convert_smilies– convert_chars– wpautop– shortcode_unautop– prepend_attachment

• That's a lot of value add!

Page 15: WordPress development paradigms, idiosyncrasies and other big words

I want all that other good stuff, too!

• Leverage all those the_content methods

foreach($posts as $post){

echo '<div>';

echo apply_filters(

'the_content',

$page->post_content);

echo '<div>';

}

Page 16: WordPress development paradigms, idiosyncrasies and other big words

The lesson thus far

• TMTOWTDI, but not all ways are equal

• Use the method that:– is the most abstracted (high level)– requires the least amount of additional code– encapsulates the most value-added

intelligence

Page 17: WordPress development paradigms, idiosyncrasies and other big words

“Whenever you're going to write a code block that seems to be quite generic and common, check first if there's a WP function that can do it for you.” – Ozh Richard, de facto WP Plugin expert

Page 18: WordPress development paradigms, idiosyncrasies and other big words

Big Words

• Paradigm: a model or pattern that defines a way of thinking or working with a tool

• Idiosyncrasy: an unusual, distinctive and recognizable trait or pattern

• Idiom: a form of expression, natural to a language or context

Page 19: WordPress development paradigms, idiosyncrasies and other big words

WordPress Paradigms and Patterns

• Plugins

• Templates

• Hooks

• Post Types and Taxonomies

Page 20: WordPress development paradigms, idiosyncrasies and other big words

WordPress Idioms

• The Loop and the Query

• Template tags (and get_)

Page 21: WordPress development paradigms, idiosyncrasies and other big words

WordPress Idiosyncrasies

• $wpdb

• wp_enqueue_script()

• No TIME!! (part deux?)– wp_kses(), esc_attr()– body_class(), post_class(), comment_class()

Page 22: WordPress development paradigms, idiosyncrasies and other big words

Paradigm: Plugins

• Often confused with Widgets• Nothing more than a distributableway to

inject code at the start of the loading / execution cycle

• Not to be confused with pluggable functions

<?php /*Plugin Name: Name Of The Plugin*/?>

Page 23: WordPress development paradigms, idiosyncrasies and other big words

Paradigm:Themes and Templates

Page 24: WordPress development paradigms, idiosyncrasies and other big words

Themes

• Control visual look-and-feel of a site

• Require at minimum only index.php and style.css

• But wait, there's more, with functions.php:– Widgets– Admin options– Changes to core behaviour

Page 25: WordPress development paradigms, idiosyncrasies and other big words

Child Themes

• Best way to customize a theme for a specific client application

• Clever overloading scheme

• Leverage existing intelligence

%> wp-content/themes/my-child-theme/style.css/*Theme Name: Twenty Ten Child ThemeTemplate: twentyten*/

@import url('../twentyten/style.css');

Page 26: WordPress development paradigms, idiosyncrasies and other big words

Template Files

• PHP files, loaded contextually based on Query string

• Overloaded using a strict Template Hierarchy

• Follows conditional hierarchy

Page 27: WordPress development paradigms, idiosyncrasies and other big words
Page 28: WordPress development paradigms, idiosyncrasies and other big words

Template Parts

• Breaks down template hierarchy to custom level of granularity

• Code reuse design pattern• Allows multiple templates to share

sections

• Eg: events-by-date.php, events-by-category.php, all-events.php

• Note: local vars lose scope (uses "get")include(locate_template('template-part'));

get_template_part('template', 'part');

Page 29: WordPress development paradigms, idiosyncrasies and other big words

Page Templates

• Templates that can be admin-applied to Pages (not posts)

<?php/*Template Name: 3 Column*/?>

Page 30: WordPress development paradigms, idiosyncrasies and other big words

Post Formats

• Standardized contributor-assignable taxonomy for posts

• Meant to be consistent across all blogs

• aside, chat, gallery, link, image, quote, status, video, audio

<?php get_template_part( 'format', get_post_format());?>

Page 31: WordPress development paradigms, idiosyncrasies and other big words

Paradigm:Hooks, Actions and Filters

Page 32: WordPress development paradigms, idiosyncrasies and other big words

“WordPress action hooks are a means of providing a way for other developers to insert their own code in specific locations within your code, in order to change or expand the functionality of your code.” – Nathan Rice

http://www.nathanrice.net/blog/an-introduction-to-wordpress-action-hooks/

Page 33: WordPress development paradigms, idiosyncrasies and other big words

Hooks

• Spiritually related to GoF's Template Method Design Pattern

• Alternative extension method to subclassing

• Developers create hooks wherever they think other devs may wish to extend their code

• Documented under PluginAPI, but you will encounter them sooner than that

Page 34: WordPress development paradigms, idiosyncrasies and other big words

Actions vs. Filters

• Actions inject code into a workflow

• Filters take a variable, modify it and return the same type

// set up action hookdo_action('hook-name');

// set up filter hook$variable = apply_filters('filter-name',

$variable);

Page 35: WordPress development paradigms, idiosyncrasies and other big words

Leveraging Action Hooks

• Use an action hook to do something at a specific point in the execution cycle

• Multiple sources can register for a single action hook

add_action('init', 'stuff_to_do_at_init');

Page 36: WordPress development paradigms, idiosyncrasies and other big words

General Execution Order

• muplugins_loaded• plugins_loaded• sanitize_comment_cookies• setup_theme• load_textdomain• after_setup_theme• auth_cookie_malformed• set_current_user• init• widgets_init• register_sidebar• wp_register_sidebar_widget• wp_loaded• parse_request*• send_headers*• parse_query*• pre_get_posts*• posts_selection• wp*

• template_redirect• get_header• wp_head• wp_enqueue_scripts• wp_print_styles• wp_print_scripts• get_template_part_loop• loop_start*• the_post*• loop_end*• get_sidebar• dynamic_sidebar• get_search_form• wp_meta• get_footer• twentyten_credits• wp_footer• wp_print_footer_scripts• shutdown

http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request

Page 37: WordPress development paradigms, idiosyncrasies and other big words

Action examples

add_action('init', 'register_my_custom_post');

add_action('init', 'register_my_custom_taxonomy');

add_action('widgets_init', 'register_my_widget');

add_action('wp_enqueue_scripts', 'add_my_js_libs');

add_action('save_post', 'save_my_custom_meta');

Page 38: WordPress development paradigms, idiosyncrasies and other big words

Leveraging Filter Hooks

• Use a filter hook to modify output or an internal variable

add_filter('the_content', 'change_content');

function change_content($content){$content = 'All your base are belong to us!!!';return $content;

}

Page 39: WordPress development paradigms, idiosyncrasies and other big words

Priority and Parameters

• add_filter can take two additional arguments: $priority and $num_args

add_filter('contextual_help', 'my_help', 10, 3);

function my_help($text, $screen_id, $screen){if ($screen_id == 'edit-my_custom_post_type'){

$text = '<p>You are on your own pal</p>';}return $text;

}

Page 40: WordPress development paradigms, idiosyncrasies and other big words

Filter Examples

add_filter( 'excerpt_more', 'custom_more' );

add_filter( 'excerpt_length', 'my_length', 999 );function my_length($length){

return 6; // six is average, right?}

Page 41: WordPress development paradigms, idiosyncrasies and other big words

Existing Filters and Actions

• WordPress already registers filters and actions

• Find them in wp-includes/default-filters.php

• remove_filter($tag, $function, $priority)

• remove_action() is an alias

Page 42: WordPress development paradigms, idiosyncrasies and other big words

So How Do I Find Them?

• Partial lists in the codex:– codex.wordpress.org/Plugin_API/Filter_Reference

– codex.wordpress.org/Plugin_API/Action_Reference • Use a good IDE like Eclipse/PHP, Aptana,

NetBeans, PHPStorm etc... and search for:– do_action(), and do_action_ref_array()– apply_filters(), and apply_filters_ref_array()

• http://adambrown.info/p/wp_hooks

Page 43: WordPress development paradigms, idiosyncrasies and other big words

Good Citizenship

• Add your own action and filter hooks wherever it may be appropriate:– things a dev may wish to override but you

don't want to expose to an Admin user– default values (max/min limits etc)– logical spots for extension

• Example: zg-event-query (filter)

• For the love of Pete, document it!

Page 44: WordPress development paradigms, idiosyncrasies and other big words

Idiom:The Loop and The Query

Page 45: WordPress development paradigms, idiosyncrasies and other big words

Getting Your Content: "The Loop"

• One "The Loop" per page

• Sets globals (eg: $post)

• Drives all template tags (eg: the_content())

• Driven by "the query": the request string

• Affects conditional tags

• Can be supplanted by query_posts()

Page 46: WordPress development paradigms, idiosyncrasies and other big words

Secondary Loops

• Used in widgets and sidebars, sub-content and related content

• Must be careful not to clobber globals and affect the main Loop

• Leverage get_posts() or get_pages() for inobtrusive secondary loops

• Or get dirty with WP_Query class• Either way, be sure to read Codex WP_Query

Page 47: WordPress development paradigms, idiosyncrasies and other big words

Suspicious Stuff

• Leverage template tags in secondary loops by:– using the_post() method on WP_Query

instance– or setup_postdata() on a $post object

$the_query = new WP_Query( $args );while ( $the_query->have_posts() ){ $the_query->the_post();

the_title();}wp_reset_postdata();

Page 48: WordPress development paradigms, idiosyncrasies and other big words

Template Tags and get_

• Template tags– Used exclusively within The Loop– Always echo their results– Rarely (?) take arguments (always working on

the global $post object)

• get_– Most template tags have a get_ equivalent– Does not echo result– Usually takes the ID of a post as argument

Page 49: WordPress development paradigms, idiosyncrasies and other big words

Template Tag vs. get_

• Use Template Tag when:– you're in The Loop!

• Use get_ when:– you want the value, not the echo– you're not in The Loop– you are in the loop but want a related item

(eg: attachment)

Page 50: WordPress development paradigms, idiosyncrasies and other big words

Idiosyncrasy:$wpdb

Page 51: WordPress development paradigms, idiosyncrasies and other big words

wpdb Class

• Instantiated once and globalized in $wpdb

• Provides API to low-level DB calls– $wpdb->query()– $wpdb->get_results()– $wpdb->get_var()

Page 52: WordPress development paradigms, idiosyncrasies and other big words

Example: Events

• Custom post type "event"

• Categorized by taxonomy "event-type"

• Event start_date stored in meta

• Let's select: all 'speaking' events with a start date of '2011-07-09'

Page 53: WordPress development paradigms, idiosyncrasies and other big words

Pure SQLselect * from wp_postsjoin wp_term_relationships

on ID = object_idjoin wp_term_taxonomy

on wp_term_taxonomy.term_taxonomy_id =wp_term_relationships.term_taxonomy_idand taxonomy = 'event-type'

join wp_termson wp_term_taxonomy.term_id =wp_terms.term_idand wp_terms.slug = 'speaking'

join wp_postmetaon wp_postmeta.post_id = IDand meta_key = 'event-date'and meta_value = '2011-07-09'

wherepost_type = 'event'and post_status = 'published'

Page 54: WordPress development paradigms, idiosyncrasies and other big words

More Properer SQLselect * from wp_posts as Pjoin wp_term_relationships TR_EVENT

on P.ID = TR_EVENT.object_idjoin wp_term_taxonomy TT_EVENT

on TT_EVENT.term_taxonomy_id =TR_EVENT.term_taxonomy_id

TT_EVENT.taxonomy = 'event-type'join wp_terms T_EVENT

on TT_EVENT.term_id = T_EVENT.term_idand T_EVENT.slug = 'speaking'

join wp_postmeta M_DATEon M_DATE.post_id = P.IDand M_DATE.meta_key = 'event-date'and M_DATE.meta_value = '2011-07-09'

whereP.post_type = 'event'and P.post_status = 'published'

Page 55: WordPress development paradigms, idiosyncrasies and other big words

Don't Use Table Names!select * from {$wpdb->posts} Pjoin {$wpdb->term_relationships} TR_EVENT

on P.ID = TR_EVENT.object_idjoin {$wpdb->term_taxonomy} TT_EVENT

on TT_EVENT.term_taxonomy_id =TR_EVENT.term_taxonomy_id

TT_EVENT.taxonomy = 'event-type'join {$wpdb->terms} T_EVENT

on TT_EVENT.term_id =T_EVENT.term_idand T_EVENT.slug = 'speaking'

join {$wpdb->postmeta} M_DATEon M_DATE.post_id = P.IDand M_DATE.meta_key = 'event-date'and M_DATE.meta_value = '2011-07-09'

whereP.post_type = 'event'and P.post_status = 'published'

Page 56: WordPress development paradigms, idiosyncrasies and other big words

More Saferer Query$wpdb->prepare("select * from {$wpdb->posts} Pjoin {$wpdb->term_relationships} TR_EVENT

on P.ID = TR_EVENT.object_idjoin {$wpdb->term_taxonomy} TT_EVENT

on TT_EVENT.term_taxonomy_id =TR_EVENT.term_taxonomy_id

TT_EVENT.taxonomy = 'event-type'join {$wpdb->terms} T_EVENT

on TT_EVENT.term_id =T_EVENT.term_idand T_EVENT.slug = %s

join {$wpdb->postmeta} M_DATEon M_DATE.post_id = P.IDand M_DATE.meta_key = 'event-date'and M_DATE.meta_value = %s

whereP.post_type = 'event'and P.post_status = 'published'",

'speaking', '2011-07-09');

Page 57: WordPress development paradigms, idiosyncrasies and other big words

But, Whenever We Can...

get_posts(array('post_type' => 'event','tax_query' => array(array(

'taxonomy' => 'event-type','field' => 'slug''terms' => 'speaking'

)),'meta_query' => array(array(

'key' => 'event-date','value' => $todays_date

))));

Page 58: WordPress development paradigms, idiosyncrasies and other big words

Use Built-Ins Whenever You Can

• Take advantage of cacheing and optimization

• Future-proof code

• Chances are, there's a function or method to do what you want– Look in Codex under WP_Query– Look in source under query.php, post.php,

category.php, taxonomy.php

Page 59: WordPress development paradigms, idiosyncrasies and other big words

Idiosyncrasy:wp_enqueue_script

Page 60: WordPress development paradigms, idiosyncrasies and other big words

We Love jQuery

• (Don't)– Jump into header.php– Add <script src="my-jquery-min.js"></script>

• (Don't)– add_action('wp_head', 'add_my_jquery');

Page 61: WordPress development paradigms, idiosyncrasies and other big words

Enqueue = The Canadian Way, eh?

• DO

add_action('wp_enqueue_scripts', 'add_my_scripts');function add_my_scripts(){

wp_enqueue_scripts('jquery-ui-core',get_stylesheet_directory_uri() .

'/script',array('jquery'),'1.8.14',false // in-header

);}

add_action('admin_enqueue_scripts', 'add_admin_scripts'); // careful here...

Page 62: WordPress development paradigms, idiosyncrasies and other big words

No One Likes Conflict

• jQuery runs in "no-conflict" mode...

jQuery(document).ready(function($) { $('#mydiv').css({color:'red', border:'2px solid red'});});

(function($) {var test = "hello, world!";function testMe(){

alert(test);}$(document).ready(testMe);

})(jQuery);

Page 63: WordPress development paradigms, idiosyncrasies and other big words

Resources and Forums

• Documentation:– Codex (of course)– Google: "wordpress add_action"– Adam Brown– WPSeek, phpxref– Your own IDE

• Help:– wordpress.org/support (yeah, not really...)– www.experts-exchange.com

• http://www.experts-exchange.com/Web_Development/Blogs/WordPress/

– wordpress.stackexchange.com

Page 64: WordPress development paradigms, idiosyncrasies and other big words

Thanks!

www.tomauger.com

www.zeitguys.com

@TomAuger

Page 65: WordPress development paradigms, idiosyncrasies and other big words

Other Stuff for more time

Page 66: WordPress development paradigms, idiosyncrasies and other big words

Paradigm:Post Types and Taxonomies

Page 67: WordPress development paradigms, idiosyncrasies and other big words

Posts

• Posts are the atomic element for all WordPress content – "actual" posts– pages– comments– attachments– drafts and revisions– custom post types

Page 68: WordPress development paradigms, idiosyncrasies and other big words

Taxonomies

• Taxonomies are the relational device that group posts together.– categories, – tags, – nav menus– post formats?– custom taxonomies

• Groupings that are shared by different items

Page 69: WordPress development paradigms, idiosyncrasies and other big words

What About Meta?

• Use meta for discrete, non-grouping data, unique to the content item (eg: price)

• Sortables (eg: year)

• Groups that are not meaningfully shared (eg: Otto's TV show seasons across different shows)

Page 70: WordPress development paradigms, idiosyncrasies and other big words

Custom Post vs. Custom Tax

• Use Custom Post for content that:– should not appear in your feed– represents a distinct type of "content"– is always associated with a set of metadata– may require a customized input form– needs a separate capability / access– needs its own private taxonomy

• Examples: products, events, albums

Page 71: WordPress development paradigms, idiosyncrasies and other big words

Custom Post vs. Custom Tax

• Use a custom taxonomy when:– You want additional ways to group items

together– You want a way to filter out a set of items– You want a new metabox

• Eg: colour, software posts, manufacturers


Top Related