Transcript
Page 1: WordCamp Jerusalem - Doing it Wrong

You’re doing it wrong!עשר טעויות נפוצות בפיתוח לוורדפרס

Monday, September 12, 11

Page 2: WordCamp Jerusalem - Doing it Wrong

You’re doing it wrong!עשר תשע טעויות נפוצות בפיתוח לוורדפרס

Monday, September 12, 11

Page 3: WordCamp Jerusalem - Doing it Wrong

Monday, September 12, 11

Page 4: WordCamp Jerusalem - Doing it Wrong

Monday, September 12, 11

Page 5: WordCamp Jerusalem - Doing it Wrong

מפתח VIP בחברת Automattic

צוות ה-VIP מפקח בין WordPress השאר על קוד

שיוצר מעל ל-1,000,000,000 דפים

נצפים בחודש

http://yoavfarhi.com @yoavf

Monday, September 12, 11

Page 6: WordCamp Jerusalem - Doing it Wrong

Monday, September 12, 11

Page 7: WordCamp Jerusalem - Doing it Wrong

Monday, September 12, 11

Page 8: WordCamp Jerusalem - Doing it Wrong

/me activates WP_DEBUG...Monday, September 12, 11

Page 9: WordCamp Jerusalem - Doing it Wrong

Monday, September 12, 11

Page 10: WordCamp Jerusalem - Doing it Wrong

1. WP_DEBUG

(wsod)

Monday, September 12, 11

Page 11: WordCamp Jerusalem - Doing it Wrong

WP_DEBUG 1/2

• Include notices

• Bypasses some error suppression (ie WPDB )

• Triggers notices for deprecated functions ex:

define('WP_DEBUG', true);

PHP Notice: get_links is deprecated since version 2.1! Use get_bookmarks() instead. in /Users/yoavfarhi/Sites/trunk/wp-includes/functions.php on line 3409

Monday, September 12, 11

Page 12: WordCamp Jerusalem - Doing it Wrong

WP_DEBUG 2/2

define('WP_DEBUG_DISPLAY', false);

define('WP_DEBUG_LOG', true);

Output to wp-content/debug.log

Don’t display

Monday, September 12, 11

Page 13: WordCamp Jerusalem - Doing it Wrong

2. Function Naming

Monday, September 12, 11

Page 14: WordCamp Jerusalem - Doing it Wrong

Imagine...

Plugin 1function custom_script() { //...}

Theme / Plugin 2function custom_script() { //...}

Monday, September 12, 11

Page 15: WordCamp Jerusalem - Doing it Wrong

Imagine...

Plugin 1function custom_script() { //...}

Theme / Plugin 2function custom_script() { //...}

Fatal Error

Monday, September 12, 11

Page 16: WordCamp Jerusalem - Doing it Wrong

Imagine...

Plugin 1function custom_script() { //...}

Theme / Plugin 2function custom_script() { //...}

Angry Client

Monday, September 12, 11

Page 17: WordCamp Jerusalem - Doing it Wrong

Imagine...

Plugin 1function custom_script() { //...}

Theme / Plugin 2function custom_script() { //...}

Call From Client

Monday, September 12, 11

Page 18: WordCamp Jerusalem - Doing it Wrong

Imagine...

Plugin 1function custom_script() { //...}

Theme / Plugin 2function custom_script() { //...}

Time / Money

Monday, September 12, 11

Page 19: WordCamp Jerusalem - Doing it Wrong

Imagine...

Plugin 1function custom_script() { //...}

Theme / Plugin 2function custom_script() { //...}

We don’t want that!

Monday, September 12, 11

Page 20: WordCamp Jerusalem - Doing it Wrong

Imagine...

Plugin 1function custom_script() { //...}

Theme / Plugin 2function custom_script() { //...}

Solution: Prefix

Monday, September 12, 11

Page 21: WordCamp Jerusalem - Doing it Wrong

Prefix!

Plugin 1function plugin1_custom_script() { //...}

Theme / Plugin 2function themename_custom_script() { //...}

Monday, September 12, 11

Page 22: WordCamp Jerusalem - Doing it Wrong

Prefix!

Plugin 1function plugin1_custom_script() { //...}

Theme / Plugin 2function themename_custom_script() { //...}

Happy!

Monday, September 12, 11

Page 23: WordCamp Jerusalem - Doing it Wrong

Or: Use a Classclass my_plugin {

function custom_script() { //... }

function whatever() { //... }

}

new my_plugin;

Monday, September 12, 11

Page 24: WordCamp Jerusalem - Doing it Wrong

nomy_id AND {$table_prefix}terms.term_id = {$table_prefix}term_taxonomy.term_taxonomy_idonomy.term_id AND {$table_prefix}posts.ID = {$table_prefix}postmetata.post_id AND {$table_prefix}

3. Direct SQL Queries

Monday, September 12, 11

Page 25: WordCamp Jerusalem - Doing it Wrong

$last_posts = (array)$wpdb->get_results(" SELECT post_date, ID, post_title, name, {$table_prefix}terms.term_id FROM {$table_prefix}posts, {$table_prefix}term_relationships, {$table_prefix}terms, {$table_prefix}postmeta, {$table_prefix}term_taxonomy WHERE {$table_prefix}posts.ID = {$table_prefix}term_relationships.object_id AND {$table_prefix}term_taxonomy.term_taxonomy_id = {$table_prefix}term_relationships.term_taxonomy_id AND {$table_prefix}terms.term_id = {$table_prefix}term_taxonomy.term_id AND {$table_prefix}posts.ID = {$table_prefix}postmeta.post_id AND {$table_prefix}postmeta.meta_key = '_mini_post' AND {$table_prefix}postmeta.meta_value = 0 AND post_status = 'publish' AND {$table_prefix}terms.term_id != 25 AND {$table_prefix}terms.term_id != 24 AND {$table_prefix}term_taxonomy.taxonomy = 'category' ");Monday, September 12, 11

Page 26: WordCamp Jerusalem - Doing it Wrong

$last_posts = (array)$wpdb->get_results(" SELECT post_date, ID, post_title, name, {$table_prefix}terms.term_id FROM {$table_prefix}posts, {$table_prefix}term_relationships, {$table_prefix}terms, {$table_prefix}postmeta, {$table_prefix}term_taxonomy WHERE {$table_prefix}posts.ID = {$table_prefix}term_relationships.object_id AND {$table_prefix}term_taxonomy.term_taxonomy_id = {$table_prefix}term_relationships.term_taxonomy_id AND {$table_prefix}terms.term_id = {$table_prefix}term_taxonomy.term_id AND {$table_prefix}posts.ID = {$table_prefix}postmeta.post_id AND {$table_prefix}postmeta.meta_key = '_mini_post' AND {$table_prefix}postmeta.meta_value = 0 AND post_status = 'publish' AND {$table_prefix}terms.term_id != 25 AND {$table_prefix}terms.term_id != 24 AND {$table_prefix}term_taxonomy.taxonomy = 'category' ");

WRONG!

Monday, September 12, 11

Page 27: WordCamp Jerusalem - Doing it Wrong

$args = array( 'post_type' => 'post', 'post_status' => 'publish', 'tax_query' => array( array( 'taxonomy' => 'category', 'terms' => array( '25', '24'), 'field' => 'id', 'operator' => 'NOT IN', ) ), 'meta_query' => array( array( 'key' => '_mini_post', 'value' => 0, ) ));

$last_posts = new WP_Query( $args );

Monday, September 12, 11

Page 28: WordCamp Jerusalem - Doing it Wrong

$args = array( 'post_type' => 'post', 'post_status' => 'publish', 'tax_query' => array( array( 'taxonomy' => 'category', 'terms' => array( '25', '24'), 'field' => 'id', 'operator' => 'NOT IN', ) ), 'meta_query' => array( array( 'key' => '_mini_post', 'value' => 0, ) ));

$last_posts = new WP_Query( $args );

Monday, September 12, 11

Page 29: WordCamp Jerusalem - Doing it Wrong

This is so much better because:

Monday, September 12, 11

Page 30: WordCamp Jerusalem - Doing it Wrong

This is so much better because:

• It is easier to read, easier to change

Monday, September 12, 11

Page 31: WordCamp Jerusalem - Doing it Wrong

This is so much better because:

• It is easier to read, easier to change

• It is more secure

Monday, September 12, 11

Page 32: WordCamp Jerusalem - Doing it Wrong

This is so much better because:

• It is easier to read, easier to change

• It is more secure

• It Uses WP object caching and so faster

Monday, September 12, 11

Page 33: WordCamp Jerusalem - Doing it Wrong

This is so much better because:

• It is easier to read, easier to change

• It is more secure

• It Uses WP object caching and so faster

• It is platform indifferent

Monday, September 12, 11

Page 34: WordCamp Jerusalem - Doing it Wrong

This is so much better because:

• It is easier to read, easier to change

• It is more secure

• It Uses WP object caching and so faster

• It is platform indifferent

• It is future proof

Monday, September 12, 11

Page 35: WordCamp Jerusalem - Doing it Wrong

This is so much better because:

• It is easier to read, easier to change

• It is more secure

• It Uses WP object caching and so faster

• It is platform indifferent

• It is future proof

• It is bound to be improved

Monday, September 12, 11

Page 36: WordCamp Jerusalem - Doing it Wrong

4. Loading JS/CSS/etc

Monday, September 12, 11

Page 37: WordCamp Jerusalem - Doing it Wrong

Javascript

Monday, September 12, 11

Page 40: WordCamp Jerusalem - Doing it Wrong

<script type='text/javascript' src='http://thisismysite.com/wp-content/themes/mytheme/js/newsletter.js'></script>

Wrong!

function mytheme_load_script() { wp_enqueue_script( 'newsletter', 'http://thisismysite.com/wp-content/themes/mytheme/js/newsletter.js', array( 'jquery' ), '0.1' ); }

add_action( 'wp_enqueue_scripts', 'mytheme_load_script');

Javascript

Monday, September 12, 11

Page 41: WordCamp Jerusalem - Doing it Wrong

<script type='text/javascript' src='http://thisismysite.com/wp-content/themes/mytheme/js/newsletter.js'></script>

Wrong!

function mytheme_load_script() { wp_enqueue_script( 'newsletter', 'http://thisismysite.com/wp-content/themes/mytheme/js/newsletter.js', array( 'jquery' ), '0.1' ); }

add_action( 'wp_enqueue_scripts', 'mytheme_load_script');

Ok, but what if ...

Javascript

Monday, September 12, 11

Page 43: WordCamp Jerusalem - Doing it Wrong

Wrong!

Right!

Javascript

<script type='text/javascript' src='http://thisismysite.com/wp-content/themes/mytheme/js/newsletter.js'></script>

function mytheme_load_script() { wp_enqueue_script( 'newsletter', get_template_directory_uri() . '/js/newsletter.js', array( 'jquery' ), '0.1' ); }

add_action( 'wp_enqueue_scripts', 'mytheme_load_script');

Monday, September 12, 11

Page 44: WordCamp Jerusalem - Doing it Wrong

Use wp_enqueue_* because:

• DRY - don’t repeat yourself

• You can set dependencies

• And manage versions

• And easily move to the footer

• And control where it loads (admin/page/...)

Monday, September 12, 11

Page 45: WordCamp Jerusalem - Doing it Wrong

Never assume a file location

Monday, September 12, 11

Page 46: WordCamp Jerusalem - Doing it Wrong

Never assume a file location

• There’s a function for that:

Monday, September 12, 11

Page 47: WordCamp Jerusalem - Doing it Wrong

Never assume a file location

• There’s a function for that:

site_url()

Monday, September 12, 11

Page 48: WordCamp Jerusalem - Doing it Wrong

Never assume a file location

• There’s a function for that:

site_url()plugins_url()

Monday, September 12, 11

Page 49: WordCamp Jerusalem - Doing it Wrong

Never assume a file location

• There’s a function for that:

site_url()plugins_url()content_url()

Monday, September 12, 11

Page 50: WordCamp Jerusalem - Doing it Wrong

Never assume a file location

• There’s a function for that:

site_url()plugins_url()content_url()get_theme_directory() *

Monday, September 12, 11

Page 51: WordCamp Jerusalem - Doing it Wrong

Never assume a file location

• There’s a function for that:

site_url()plugins_url()content_url()get_theme_directory() *get_theme_directory_uri() *

Monday, September 12, 11

Page 52: WordCamp Jerusalem - Doing it Wrong

Never assume a file location

• There’s a function for that:

site_url()plugins_url()content_url()get_theme_directory() *get_theme_directory_uri() *includes_url()

Monday, September 12, 11

Page 53: WordCamp Jerusalem - Doing it Wrong

Never assume a file location

• There’s a function for that:

site_url()plugins_url()content_url()get_theme_directory() *get_theme_directory_uri() *includes_url()admin_url()

Monday, September 12, 11

Page 54: WordCamp Jerusalem - Doing it Wrong

5. Fetching remote content

Monday, September 12, 11

Page 55: WordCamp Jerusalem - Doing it Wrong

What’s your transport?

file_get_contents() ?CURL ?

fsockopen() ?stream_socket_client() ?

Monday, September 12, 11

Page 56: WordCamp Jerusalem - Doing it Wrong

What’s your transport?

file_get_contents() ?CURL ?

fsockopen() ?stream_socket_client() ?

WRONG!

Monday, September 12, 11

Page 57: WordCamp Jerusalem - Doing it Wrong

Helper functions

//Simple Get$resp = wp_remote_get( 'http://example.com/' );

//Simple Post$args = array( 'body' => 'some data', 'user-agent' => 'your plugin');$resp = wp_remote_post( 'http://example.com', $args );

The WP_Http class

Monday, September 12, 11

Page 58: WordCamp Jerusalem - Doing it Wrong

The WP_Http class

• Cookies

• Headers

• Authentication

• Timeouts

• Etc...

* Add your own caching

Supports

Monday, September 12, 11

Page 59: WordCamp Jerusalem - Doing it Wrong

6. Doing Ajax

Monday, September 12, 11

Page 60: WordCamp Jerusalem - Doing it Wrong

Doing Ajax

Monday, September 12, 11

Page 61: WordCamp Jerusalem - Doing it Wrong

Doing Ajax<script>var ajaxurl = <?php echo plugins_url( 'ajax.php', __FILE__ ); ?>

$('#button').click(function(){ $.post(ajaxurl, function(data) { $('.result').html(data); }); });</script>

front-end:

Monday, September 12, 11

Page 62: WordCamp Jerusalem - Doing it Wrong

Doing Ajax<script>var ajaxurl = <?php echo plugins_url( 'ajax.php', __FILE__ ); ?>

$('#button').click(function(){ $.post(ajaxurl, function(data) { $('.result').html(data); }); });</script>

<?phprequire_once('../../../wp-load.php');//...

front-end:

ajax.php:

Monday, September 12, 11

Page 63: WordCamp Jerusalem - Doing it Wrong

Doing Ajax<script>var ajaxurl = <?php echo plugins_url( 'ajax.php', __FILE__ ); ?>

$('#button').click(function(){ $.post(ajaxurl, function(data) { $('.result').html(data); }); });</script>

<?phprequire_once('../../../wp-load.php');//...

front-end:

ajax.php:WRONG!

Monday, September 12, 11

Page 64: WordCamp Jerusalem - Doing it Wrong

Doing Ajax

Monday, September 12, 11

Page 65: WordCamp Jerusalem - Doing it Wrong

Doing Ajax<script>var ajaxurl = <?php echo admin_url( 'admin-ajax.php'); ?>

$('#button').click(function(){ var data = { action: 'my_action', }; $.post(ajaxurl, function(data) { $('.result').html(data); }); });</script>

front-end:

Monday, September 12, 11

Page 66: WordCamp Jerusalem - Doing it Wrong

Doing Ajax

add_action('wp_ajax_my_action', 'plugin_action_callback');add_action('wp_ajax_nopriv_my_action', 'plugin_action_callback');

function plugin_action_callback() { // do whatever echo $whatever; die();}

<script>var ajaxurl = <?php echo admin_url( 'admin-ajax.php'); ?>

$('#button').click(function(){ var data = { action: 'my_action', }; $.post(ajaxurl, function(data) { $('.result').html(data); }); });</script>

front-end:

php:

Monday, September 12, 11

Page 67: WordCamp Jerusalem - Doing it Wrong

7. Security? What ‘bout it?

http://xkcd.com/327/

Monday, September 12, 11

Page 68: WordCamp Jerusalem - Doing it Wrong

Never trust user input

Monday, September 12, 11

Page 69: WordCamp Jerusalem - Doing it Wrong

Never trust user input

<h1>Search results for: <?php echo $_GET['s']; ?></h1>

1. XSS

http://mysite.com/?s=</h1><script>alert('This Javascript can do anything!');</script>

Monday, September 12, 11

Page 70: WordCamp Jerusalem - Doing it Wrong

Never trust user input

<h1>Search results for: <?php echo $_GET['s']; ?></h1>

1. XSS

http://mysite.com/?s=</h1><script>alert('This Javascript can do anything!');</script>Wrong!

Monday, September 12, 11

Page 71: WordCamp Jerusalem - Doing it Wrong

Never trust user input

<h1>Search results for: <?php echo $_GET['s']; ?></h1>

1. XSS

http://mysite.com/?s=</h1><script>alert('This Javascript can do anything!');</script>Wrong!

<h1>Search results for: <?php echo esc_attr( $_GET['s'] ) ; ?></h1>

get_search_query()

Escape late, escape EVERYTHING

Solution:

Monday, September 12, 11

Page 72: WordCamp Jerusalem - Doing it Wrong

Never trust user input

Monday, September 12, 11

Page 73: WordCamp Jerusalem - Doing it Wrong

Never trust user input2.SQL Injection $wpdb->query( " UPDATE $wpdb->posts SET post_title = ". $POST['title'] ." WHERE ID = 1" );

Monday, September 12, 11

Page 74: WordCamp Jerusalem - Doing it Wrong

Never trust user input2.SQL Injection $wpdb->query( " UPDATE $wpdb->posts SET post_title = ". $POST['title'] ." WHERE ID = 1" );

Wrong!

Monday, September 12, 11

Page 75: WordCamp Jerusalem - Doing it Wrong

Never trust user input2.SQL Injection $wpdb->query( " UPDATE $wpdb->posts SET post_title = ". $POST['title'] ." WHERE ID = 1" );

Wrong!

Solution:• Use APIS ( $wpdb->update, $wpdb->prepare )• Validate data ( whitelist > blacklist )

Monday, September 12, 11

Page 76: WordCamp Jerusalem - Doing it Wrong

Never trust user input

Monday, September 12, 11

Page 77: WordCamp Jerusalem - Doing it Wrong

Never trust user input

3.CSRFAuthorization VS Intention

Monday, September 12, 11

Page 78: WordCamp Jerusalem - Doing it Wrong

Never trust user input

3.CSRFAuthorization VS Intention

Use nonces, not just current_user_can()

wp_create_nonce(), wp_verify_nonce(), check_admin_referer()

Solution:

Monday, September 12, 11

Page 79: WordCamp Jerusalem - Doing it Wrong

8. Trunk?Monday, September 12, 11

Page 80: WordCamp Jerusalem - Doing it Wrong

$ mkdir blog

$ cd blog

$ svn co http://core.svn.wordpress.org/trunk/ .

Mac / Linux

Monday, September 12, 11

Page 81: WordCamp Jerusalem - Doing it Wrong

Windows / Tortoise SVN

Monday, September 12, 11

Page 82: WordCamp Jerusalem - Doing it Wrong

Running on Trunk

No, not for production

Monday, September 12, 11

Page 83: WordCamp Jerusalem - Doing it Wrong

9. Not ContributingMonday, September 12, 11

Page 84: WordCamp Jerusalem - Doing it Wrong

Contributing

Monday, September 12, 11

Page 85: WordCamp Jerusalem - Doing it Wrong

Contributing

• Core patches/testing/documentation

Monday, September 12, 11

Page 86: WordCamp Jerusalem - Doing it Wrong

Contributing

• Core patches/testing/documentation

• Release plugins and themes

Monday, September 12, 11

Page 87: WordCamp Jerusalem - Doing it Wrong

Contributing

• Core patches/testing/documentation

• Release plugins and themes

• Translations and i18n

Monday, September 12, 11

Page 88: WordCamp Jerusalem - Doing it Wrong

Contributing

• Core patches/testing/documentation

• Release plugins and themes

• Translations and i18n

• Forums support

Monday, September 12, 11

Page 89: WordCamp Jerusalem - Doing it Wrong

Contributing

• Core patches/testing/documentation

• Release plugins and themes

• Translations and i18n

• Forums support

• Tip! (or Buy)

Monday, September 12, 11

Page 90: WordCamp Jerusalem - Doing it Wrong

Questions ?Monday, September 12, 11


Top Related