Jan/21/2015 WordPress Ottawa Meetup.
This talk is aimed at developers or designers interested in getting started with WordPress development. It's meant as a guide to help avoid common issues that trip up newcomers to WordPress.
1. ryan welcher • @ryanwelcher • me@ryanwelcher.com
G E T T I N G S TA RT E D W I T H
W O R D P R E S S D E V E L O P M E N T
RYA N W E L C H E R
2. ryan welcher • @ryanwelcher • me@ryanwelcher.com
A B O U T M E
• Ryan Welcher - me@ryanwelcher.com
• Web Developer for over 10 years
• Been working with WordPress since 2009
• Web Engineer at 10up
3. ryan welcher • @ryanwelcher • me@ryanwelcher.com
T H I S P R E S E N TAT I O N
• Sharing gotcha’s with the noobs :) - where to start and what not to do.
• Aimed at developers or designers just getting into WordPress
development.
• Not an introduction to programming concepts.
• Lots of topics, not a lot of depth for each.
• Assuming that you can install WordPress and are comfortable looking
at PHP.
• Open to suggestions.
4. ryan welcher • @ryanwelcher • me@ryanwelcher.com
P O S S I B L E TO P I C S
• local development
server
• Vagrant
• Varying Vagrant
Vagrants
• Development plugins
• WP_DEBUG
• Error handling
• Browser tools
• Software tools
• Getting WordPress core
• Coding standards
• Documentation
• PHPDocs
• PHP gotcha’s
• Single vs double quotes
• The White Screen of
Death
• Defensive development
• Shorthand control
structures
• Ternary operators
• Hacking core
• Data sanitization
• Nonces and security
• Actions
• Filters
• WP_Query
• custom post types
• custom taxonomies
• custom fields
• query_posts()
• get_posts()
• $wpdb
• shortcodes
• Widgets
• Writing a plugin
• Plugin headers
• Object-oriented
programming
• Design patterns
• Creating a theme
• Creating a child theme
• Theme template
hierarchy
• Enqueueing JS/CSS
correctly
• AJAX
• JSON
• The Command line
• WP_CLI
• Bash scripting
• Grunt
• my head just
exploded…
6. ryan welcher • @ryanwelcher • me@ryanwelcher.com
A C T U A L TO P I C S
• Setting up
• Tools
• Local Development Server
• Getting WordPress Core
• WordPress file structure
• Setting up WP_DEBUG
• Development Plugins
• PHP
• General PHP
• The White Screen of Death
• Defensive Development
• Single vs Double Quotes
• Shorthand Control Structures
• Ternary Operators
• WordPress
• Where does my code go?
• Hacking Core
• Hooks
• Path Helper Methods
• Adding Javascript and CSS correctly
• jQuery no-conflict mode
• The Loop
• Creating secondary loops
• Resource Links
9. ryan welcher • @ryanwelcher • me@ryanwelcher.com
TO O L S
• Code Editor / IDE ( Integrated Development Environment )
• Theme/Plugin editor in WordPress is too volatile!
• No word processing software.
• Software:
• Sublime Text - www.sublimetext.com
• Dreamweaver - www.adobe.com
• TextMate - macromates.com
• Phpstorm - www.jetbrains.com
10. ryan welcher • @ryanwelcher • me@ryanwelcher.com
TO O L S
• FTP (File Transfer Protocol) software.
• Copy files to and from a remote server.
• Software:
• Transmit - panic.com/transmit
• FileZilla - filezilla-project.org
• Fetch - fetchsoftworks.com
• Beyond Compare - www.scootersoftware.com
11. ryan welcher • @ryanwelcher • me@ryanwelcher.com
TO O L S
• Web Browser Tools
• Will help with debugging in the browser - i.e Javascript errors.
• Most modern browsers have tools either built-in or easily
installed.
• Usually right clicking and choosing “inspect element” will
open the tools.
• Internet Explorer - press F12
• FireFox - Install FireBug add-on first.
12. ryan welcher • @ryanwelcher • me@ryanwelcher.com
L O C A L D E V E L O P M E N T S E RV E R
• Why set one up?
• Gives you a safe “sandbox” to make mistakes with your code.
• Proper debugging configuration.
• Saves time vs FTP upload*
• How do I set one up?
• MAMP - www.mamp.info
• WAMP - www.wampserver.com
• Vagrant and VVV ( Varying Vagrant Vagrants )
14. F I L E S T R U C T U R E
• wp-config.php -
contains your website’s
base configuration
details such as database
connection info.
• wp-content - contains
all of the plugins, themes
and uploaded content.
• Everything else is
WordPress core and
should be left alone.
16. ryan welcher • @ryanwelcher • me@ryanwelcher.com
W P _ D E B U G
E D I T I N G W P - C O N F I G :
H T T P : / / C O D E X . W O R D P R E S S . O R G / E D I T I N G _ W P - C O N F I G . P H P
To this.
17. ryan welcher • @ryanwelcher • me@ryanwelcher.com
P L U G I N S
• Developer - https://wordpress.org/plugins/developer/
• Helps you optimize your development environment by making sure that you have
all the essential tools and plugins installed.
• Log Deprecated Notices - https://wordpress.org/plugins/log-deprecated-
notices/
• Logs the usage of deprecated files, functions, and function arguments, and
identifies where the deprecated functionality is being used.
• Debug Bar - https://wordpress.org/plugins/debug-bar/
• Adds a debug menu to the admin bar that shows query, cache, and other helpful
debugging information.
• Lots of add-on plugins available
20. ryan welcher • @ryanwelcher • me@ryanwelcher.com
G E N E R A L P H P
• PHP variables must start with a $ followed by a letter or underscore
• Valid: $foo, $_foo
• Invalid: _foo, $123_foo, $!foo
• Don’t use shorthand PHP tags
• Good: <?php … ?>
• Bad : <?= … ?> or <? … ?>
• Your php.ini file may not allow shorthand tags and will cause a world of hurt.
• PHP lines must always end with a semi-colon.
• You’ll know if you forgot one … duh duh duhhhhhh.
22. ryan welcher • @ryanwelcher • me@ryanwelcher.com
W H I T E S C R E E N O F D E AT H
• Check your syntax
• Missing a $ or invalid variable name.
• Missing semi-colon.
• Missing a curly brace.
• Too many or not enough parens.
• Check your debug.log file in wp-content folder.
• The last line will give you a file name and line number.
• PHP {ERROR _TYPE}: { ERROR_DESC } in { FILENAME } on line { # }
• PHP Parse error : syntax error, unexpected ‘=‘ in / … /functions.php on line
62
24. ryan welcher • @ryanwelcher • me@ryanwelcher.com
D E F E N S I V E D E V E L O P M E N T
• Planning for and handling
failure.
• Checking all the things
BEFORE using them.
• Example functions:
• isset()
• gettype()
• empty()
• function_exists()
• defined()
• is_wp_error()
• WordPress functions can
return on failure:
• False
• WP_Error object
28. ryan welcher • @ryanwelcher • me@ryanwelcher.com
S I N G L E V S D O U B L E Q U O T E S
• Double quotes parse variables as their value.
• Use single quotes unless you have something to parse.
29. S H O RT H A N D
C O N T R O L
S T R U C T U R E S
• if, while, foreach, etc
statements without the
curly braces.
• Nice for switching
between PHP and HTML
cleanly.
• Gotcha - IDE’s will not
catch errors.
32. ryan welcher • @ryanwelcher • me@ryanwelcher.com
T E R N A RY O P E R ATO R S
• Single line if/else statement
• Handy for variable assignment
• Format: ( if statement is true ) ? do this : else, do this;
34. ryan welcher • @ryanwelcher • me@ryanwelcher.com
W H E R E D O E S M Y C O D E G O ?
• Plugins
• wp-content
• plugins
• your-plugin
• your-plugin.php
• Themes
• wp-content
• themes
• your-theme
• functions.php
36. ryan welcher • @ryanwelcher • me@ryanwelcher.com
H A C K I N G C O R E
• What?
• Make code changes to files outside of the wp-content folder.
• Also applies to downloaded themes/plugins.
• Why not?
• Site is no longer future-proof.
• Compatibility issues with other plugins/themes.
• May introduce security holes.
• When core/theme/plugin updates, your changes are gone!
• Your hacking what plugins are meant to do - use hooks instead.
37. ryan welcher • @ryanwelcher • me@ryanwelcher.com
H O O K S
• Provided by WordPress to allow us to 'hook' our code into
the rest of WordPress Core.
• A hook is a function that invokes an event that triggers all
other functions hooked into that event.
• 2 Kinds of hooks:
• Actions - Points in the code where WordPress gives us
the ability to add tasks.
• Filters - Allow us to edit content/data before it’s output.
38. ryan welcher • @ryanwelcher • me@ryanwelcher.com
A C T I O N S
• has_action()
• add_action()
• do_action()
• do_action_ref_array()
• did_action()
• remove_action()
• remove_all_actions()
• doing_action()
A C T I O N S : H T T P : / / C O D E X . W O R D P R E S S . O R G / P L U G I N _ A P I /
A C T I O N _ R E F E R E N C E
39. ryan welcher • @ryanwelcher • me@ryanwelcher.com
A C T I O N S
• do_action( $tag, $arg … )
• Invokes an action.
• Use to invoke your own actions.
• add_action( $tag, $function_to_add, $priority = 10, $accepted_args = 1 )
• Hooks into an action invoked by do_action().
• remove_action( $tag, $function_to_remove, $priority )
• removes a function from an invoked action.
• arguments must match the add_action call exactly.
42. ryan welcher • @ryanwelcher • me@ryanwelcher.com
F I LT E R S : H T T P : / / C O D E X . W O R D P R E S S . O R G / P L U G I N _ A P I /
F I LT E R _ R E F E R E N C E
• has_filter()
• add_filter()
• apply_filters()
• apply_filters_ref_array()
• current_filter()
• remove_filter()
• remove_all_filters()
• doing_filter()
F I LT E R S
43. ryan welcher • @ryanwelcher • me@ryanwelcher.com
F I LT E R S
• apply_filters( $tag, $value, $var … )
• Invokes a filter.
• Returns the result of $value after all hooked functions are applied to it.
• Use to invoke your own filters.
• add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 )
• Hooks into a filter invoked by apply_filter().
• $function_to_add always takes a parameter and must return data.
• remove_filter( $tag, $function_to_remove, $priority )
• removes a function from an invoked filter.
• arguments must match the add_filter call exactly.
46. ryan welcher • @ryanwelcher • me@ryanwelcher.com
PAT H H E L P E R M E T H O D S
Let WordPress do the work for you!
47. ryan welcher • @ryanwelcher • me@ryanwelcher.com
PAT H H E L P E R M E T H O D S
• Plugins
• plugins_url()
• plugin_dir_url()
• plugin_dir_path()
• plugin_basename()
• Themes
• get_template_directory_uri()
• get_stylesheet_directory_uri()
• get_stylesheet_uri()
• get_theme_root_uri()
• get_theme_root()
• get_theme_roots()
• get_stylesheet_directory()
• get_template_directory()
• Site Home
• home_url()
• get_home_path()
• WordPress
• admin_url()
• site_url()
• content_url()
• includes_url()
• wp_upload_dir()
• get_bloginfo()
48. ryan welcher • @ryanwelcher • me@ryanwelcher.com
A D D I N G J S A N D C S S C O R R E C T LY
• wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer )
• Handles dependencies, load order and duplication of files.
• wp_enqueue_style( $handle, $src, $deps, $ver, $media )
• Both are used with the wp_enqueue_scripts action for the front-end.
• Other hooks
• admin_enqueue_scripts
• login_enqueue_scripts
50. ryan welcher • @ryanwelcher • me@ryanwelcher.com
J Q U E RY N O - C O N F L I C T
• WordPress loads it’s version of jQuery in no-conflict
mode to play nicely with other libraries.
• $ shorthand is replaced with jQuery
51. ryan welcher • @ryanwelcher • me@ryanwelcher.com
T H E L O O P
• “The Loop” is the main process of WordPress.
• You use The Loop in your template files to show content to
visitors.
• Any HTML or PHP code in The Loop will be processed on each
post.
• There are special functions or Template Tags that are meant to
be used inside The Loop.
• The Loop uses global variables called $wp_query and $post
behind the scenes.
53. ryan welcher • @ryanwelcher • me@ryanwelcher.com
T E M P L AT E TA G S
• the_category()
• the_title()
• the_title_attribute()
• the_meta()
• the_content()
• the_excerpt()
• the_permalink()
• the_ID()
• the_tags()
• the_date()
• the_time()
• the_shortlink()
54. ryan welcher • @ryanwelcher • me@ryanwelcher.com
C R E AT I N G S E C O N D A RY L O O P S
• As a developer you will be creating secondary loops all
the time.
• 3 options to create secondary loop:
• query_posts()
• get_posts()
• WP_Query Class
• We have to be careful not to interfere with “The Loop”.
55. ryan welcher • @ryanwelcher • me@ryanwelcher.com
C R E AT I N G S E C O N D A RY L O O P S
• query_posts()
• Don’t use this, even the Codex says you shouldn’t.
• Inefficient.
• Alters The Loop.
• If that’s your goal, use the pre_get_posts hook instead.
• If you have to use it, always call wp_reset_query()
afterwards to reset The Loop.
56. ryan welcher • @ryanwelcher • me@ryanwelcher.com
C R E AT I N G S E C O N D A RY L O O P S
• get_posts( $args )
• Safe to use anywhere.
• $args can be a string or an associative array.
• Returns an array of WP_Post objects.
• Need to use setup_postdata() in order to have access to Template Tags like
the_title() and the_content()
• You must pass $post to setup_postdata() no other variable name will work.
• It will change the global $post variable used by The Loop.
• Must be followed by a call to wp_reset_postdata() to reset the global $post
variable.
58. ryan welcher • @ryanwelcher • me@ryanwelcher.com
C R E AT I N G S E C O N D A RY L O O P S
• WP_Query Class
• Powers both query_posts() and get_posts() behind the scenes.
• You can create your own instances and use them safely anywhere.
• Less restrictive but more complicated.
• Methods:
• have_posts()
• the_post()
• will change the global $post variable used by The Loop.
• Must be followed by a call to wp_reset_postdata() to reset the global $post
variable.
60. ryan welcher • @ryanwelcher • me@ryanwelcher.com
L E A R N I N G R E S O U R C E S
• The Codex - codex.wordpress.org
• WordPress Stack Exchange - wordpress.stackexchange.com
• WordPress Support Forums - wordpress.org/support
• WordPress Core
• WordPress coding standards - make.wordpress.org/core/handbook/coding-
standards/
• PHP Documentation - php.net/manual/en
• lynda.com
• Tuts+ - http://tutsplus.com/