wordpress development paradigms, idiosyncrasies and other big words

71
WordPress Development Paradigms, Idiosyncrasies and Other Big Words Tom Auger, Zeitguys inc. WordCamp Montreal, 2011

Upload: tomauger

Post on 27-Jan-2015

115 views

Category:

Technology


2 download

DESCRIPTION

For seasoned developers approaching WordPress customization or development for the first time the biggest challenge is often not learning the API and method calls: it's grasping the idiosyncrasies of the WordPress framework. In this 45-minute presentation aimed at web coders who are interested in diving into WordPress customization and development, you will learn the key idioms that will accelerate your learning curve and help you approach the framework from a best practices perspective: template hierarchies, themes and child themes, taxonomies, filters and action hooks, execution order and other need-to-know concepts will be presented as well as tips on what the most active online developer communities are and the best places to go for quick (free) help and advice.

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