Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WordPress for the Win! - PHPWorld

WordPress for the Win! - PHPWorld

Presented on November 18th 2015 at PHPWorld, Washington, D.C., USA.
https://world.phparch.com/
---------------------------------------------------------------
WordPress nowadays powers more than 20% of all websites, and with its extensive plugin infrastructure, it is a serious contender in the CMS market. The learning curve for PHP developers to work with WP is very shallow compared to, for instance, Drupal or Typo3. In this talk, which is intended for experienced PHP developers, I will introduce you to essential WordPress concepts and functionality, which will allow you to start rapid development using WordPress. Learn how to develop for WordPress like a pro, and take WordPress to the next level.
---------------------------------------------------------------

If you download the slides, the links should be clickable. Unfortunately they don't seem to be in the online deck, so here's a list of relevant & interesting links in semi-random order:

The Basics:
------------------------------
https://codex.wordpress.org/
https://developer.wordpress.org/reference/
http://adambrown.info/p/wp_hooks
https://codex.wordpress.org/Plugin_API
https://codex.wordpress.org/Plugin_API/Action_Reference
https://codex.wordpress.org/Plugin_API/Filter_Reference
https://codex.wordpress.org/The_Loop

WordPress in Your language:
------------------------------
https://make.wordpress.org/polyglots/handbook/tools/glotpress-translate-wordpress-org/
https://translate.wordpress.org/

wp-config.php Tips & Tricks
------------------------------
https://codex.wordpress.org/Editing_wp-config.php

WP Cron
------------------------------
https://developer.wordpress.org/plugins/cron/
https://wordpress.org/plugins/wp-cron-control/

Theming your Site
------------------------------
https://wordpress.org/themes
https://codex.wordpress.org/Child_Themes
http://wphierarchy.com/
https://make.wordpress.org/themes/

Functions.php
------------------------------
https://codex.wordpress.org/Functions_File_Explained
https://codex.wordpress.org/Function_Reference/add_theme_support
https://codex.wordpress.org/Function_Reference/register_nav_menu
https://codex.wordpress.org/Function_Reference/register_sidebar
https://codex.wordpress.org/Theme_Customization_API

Extending WordPress
------------------------------
http://wordpress.org/plugins/
https://codex.wordpress.org/Must_Use_Plugins

Create a Plugin
------------------------------
https://make.wordpress.org/plugins/
https://codex.wordpress.org/Writing_a_Plugin
https://codex.wordpress.org/Shortcode_API
https://codex.wordpress.org/Embeds
https://codex.wordpress.org/Function_Reference/register_post_type
https://codex.wordpress.org/Function_Reference/register_taxonomy
https://codex.wordpress.org/Settings_API
https://codex.wordpress.org/Widgets_API
https://codex.wordpress.org/Function_Reference/wp_enqueue_style
https://codex.wordpress.org/Function_Reference/wp_enqueue_script
https://codex.wordpress.org/Function_Reference/wp_localize_script
https://developer.wordpress.org/plugins/the-basics/activation-deactivation-hooks/
https://developer.wordpress.org/plugins/the-basics/uninstall-methods/

Doing Things the WordPress Way
------------------------------
https://codex.wordpress.org/WordPress_APIs
http://codex.wordpress.org/Function_Reference

Developing & Debugging
------------------------------
https://wordpress.org/plugins/search.php?q=debug+bar
https://wordpress.org/plugins/developer/
https://wordpress.org/plugins/piglatin/
https://wordpress.org/plugins/user-switching/
https://wordpress.org/plugins/log-deprecated-notices/
https://wordpress.org/plugins/whats-running/
https://wordpress.org/plugins/demo-data-creator/
https://wordpress.org/plugins/theme-check/
https://wordpress.org/plugins/rtl-tester/

https://make.wordpress.org/core/handbook/best-practices/coding-standards/
https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards
https://make.wordpress.org/core/handbook/testing/automated-testing/phpunit/
https://github.com/Varying-Vagrant-Vagrants/VVV
http://wp-cli.org/
http://wpcligui.com/
https://generatewp.com/
http://wpgear.org/
http://wpackagist.org/
http://tgmpluginactivation.com/

Closing
------------------------------
http://twitter.com/jrf_nl
http://profiles.wordpress.org/jrf

Bonus (re: question from the audience)
------------------------------
Moving WP - DB search & replace tool:
https://interconnectit.com/products/search-and-replace-for-wordpress-databases/

Juliette Reinders Folmer

November 18, 2015
Tweet

More Decks by Juliette Reinders Folmer

Other Decks in Programming

Transcript

  1. #phpworld  Themes  Plugins  SEO  Ease of

    use  Scalability  Support community  Regular updates  Learning curve  Setup costs  Maintenance costs  Hacker target
  2. #phpworld Page footer Admin Bar Page content (loop) Page header

    (Invisible) HTML <head> Sidebar containing widgets (Main) menu
  3. #phpworld Admin Bar (Invisible) HTML <head> Admin footer Admin Menu

    1. Post types 2. Custom- izations 3. Extras Admin page (with dashboard widgets)
  4. #phpworld Anatomy of WordPress Functionality  Core  Plugins 

    Themes  Languages  Js Libraries Content  Post Types  Taxonomies  Widgets  Users  Meta data/custom fields  Options  Shortcodes  OEmbeds
  5. #phpworld Hooks See:  WordPress Codex & Developer Reference 

    Hooks database: http://adambrown.info/p/wp_hooks  Debug Bar – Action & filter hooks plugin
  6. #phpworld Hooking into WP apply_filter( 'hook_name', 'function_name', $priority = 10,

    $accepted_args = 1 ); add_action( 'hook_name', 'function_name', $priority = 10, $accepted_args = 1 ); add_action( 'hook_name', array( $this, 'method_name' ), $priority = 10, $accepted_args = 1 ); add_action( 'hook_name', array( __CLASS__, 'static_method_name' ), $priority = 10, $accepted_args = 1 );
  7. #phpworld Action Hooks Front-end muplugins _loaded plugins _loaded setup _theme

    set_current _user after_setup _theme init wp_loaded parse _request posts _selection wp wp_head the_post wp_meta wp_footer admin_bar _menu
  8. #phpworld Action Hooks Back-end muplugins _loaded plugins _loaded setup _theme

    set_current _user after_setup _theme init wp_loaded admin _menu admin_init current _screen load- {page} posts _selection wp admin _head admin_bar _menu admin _notices the_post admin _footer
  9. #phpworld Action Hooks Back-end muplugins _loaded plugins _loaded setup _theme

    set_current _user after_setup _theme init wp_loaded admin _menu admin_init current _screen load- {page} posts _selection wp admin _head admin_bar _menu admin _notices the_post admin _footer
  10. #phpworld The Loop if ( have_posts() ) : while (

    have_posts() ) : the_post(); // // Post Content here // the_title() // the_content() // the_permalink() // ... endwhile; endif;
  11. #phpworld Localized  ~60 languages + ~30 > 50% 

    GlotPress translate.wordpress.org
  12. #phpworld Manage Saved Data /* Change how WP deals with

    post revisions, trash and auto-saves */ define( 'WP_POST_REVISIONS', 20 ); define( 'AUTOSAVE_INTERVAL', 60 ); // seconds define( 'EMPTY_TRASH_DAYS', 30 ); // days define( 'MEDIA_TRASH', true );
  13. #phpworld Performance /* Enable Compression, concatenation and cache */ define(

    'COMPRESS_CSS', true ); define( 'COMPRESS_SCRIPTS', true ); define( 'CONCATENATE_SCRIPTS', true ); define( 'ENFORCE_GZIP', true ); define( 'WP_CACHE', true );
  14. #phpworld Multisite /* Set up WordPress as Multi-site */ define(

    'WP_ALLOW_MULTISITE', true ); define( 'NOBLOGREDIRECT', 'http://mywp.com' ); /* After setup - will be provided by WP */ define( 'MULTISITE', true ); define( 'SUBDOMAIN_INSTALL', true ); define( 'DOMAIN_CURRENT_SITE', 'mywp.com' ); define( 'PATH_CURRENT_SITE', '/' ); define( 'SITE_ID_CURRENT_SITE', 1 ); define( 'BLOG_ID_CURRENT_SITE', 1 );
  15. #phpworld Custom User Tables /* Overrule the WP User tables

    */ define( 'CUSTOM_USER_TABLE', $table_prefix . 'my_users' ); define( 'CUSTOM_USER_META_TABLE', $table_prefix . 'my_usermeta' );
  16. #phpworld SSL /* Force secure logins and admin sessions */

    define( 'FORCE_SSL_LOGIN', true ); define( 'FORCE_SSL_ADMIN', true );
  17. #phpworld PHP Memory Limit /* Try to increase PHP Memory

    */ define( 'WP_MEMORY_LIMIT', '128M' ); /* Potentially increase it even more in the admin area */ define( 'WP_MAX_MEMORY_LIMIT', '256M' );
  18. #phpworld No File Editing /* Disable Plugin and Theme Update

    and Installation and/or plugin/theme editor */ define( 'DISALLOW_FILE_EDIT', true ); define( 'DISALLOW_FILE_MODS', true );
  19. #phpworld Limit External URL Access /* Block WP from making

    external calls */ define( 'WP_HTTP_BLOCK_EXTERNAL', true ); /* Limit allowed external hosts */ define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org,*.github.com' );
  20. #phpworld Custom Directory Paths [1] /* Overrule some directory and

    url paths. Mind: no traling slashes! */ define( 'WP_CONTENT_DIR', dirname( __FILE__ ) . '/blog/wp-content' ); define( 'WP_CONTENT_URL', 'http://mywp.com/blog/wp-content' ); define( 'UPLOADS', 'blog/wp-content/uploads' ); // Relative to ABSPATH
  21. #phpworld Custom Directory Paths [2] /* Overrule some directory and

    url paths. Mind: no traling slashes! */ define( 'WP_PLUGIN_DIR', dirname( __FILE__ ) . '/blog/wp-content/plugins' ); define( 'WP_PLUGIN_URL', 'http://mywp.com/blog/wp-content/plugins' ); define( 'WPMU_PLUGIN_DIR', dirname( __FILE__ ) . '/blog/wp-content/mu-plugins' ); define( 'WPMU_PLUGIN_URL', 'http://mywp.com/blog/wp-content/mu-plugins');
  22. #phpworld Adjust Auto-Updating /* Disable the auto-updater (WP 3.7+) */

    define( 'AUTOMATIC_UPDATER_DISABLED', true ); /* Use true/false to change the default behavior */ define( 'WP_AUTO_UPDATE_CORE', 'minor' ); /* Prevent the table upgrade function being run in favor of manually running it */ define( 'DO_NOT_UPGRADE_GLOBAL_TABLES', true );
  23. #phpworld FTP Credentials /* FTP settings */ define( 'FTP_HOST', 'hostname:port'

    ); define( 'FTP_USER', 'username' ); define( 'FTP_PASS', 'password' ); define( 'FTP_SSL', true );
  24. #phpworld Debugging /* Enable debugging */ define( 'WP_DEBUG', true); define(

    'WP_DEBUG_DISPLAY', true); /* Error logging to /wp-content/debug.log */ define( 'WP_DEBUG_LOG', true); /* Load non-minified versions of all scripts, css, disables compression and concatenation */ define( 'SCRIPT_DEBUG', true);
  25. #phpworld Basic Query Debugging /* Remember the DB queries run

    for the current page. */ define( 'SAVEQUERIES', true );
  26. #phpworld Adjust WP-Cron /* Prevent Cron running too often (plugins)

    */ define( 'WP_CRON_LOCK_TIMEOUT', 60 ); // seconds /* Run wp-cron with a redirect */ define('ALTERNATE_WP_CRON', true);
  27. #phpworld Disable WP-Cron /* Disable WP-cron in favor of real

    cron */ define( 'DISABLE_WP_CRON', true );
  28. #phpworld Real Cron with Cron Control */5 * * *

    * /usr/local/bin/php -q /path/to/wp/wp-content/ plugins/wp-cron-control/wp-cron-control.php http://mywp.com 38a37a2d5b94bc02ce0472a238d493df wget -q 'http://mywp.com/wp-cron.php?doing_wp_cron &38a37a2d5b94bc02ce0472a238d493df'
  29. #phpworld Child Theme – style.css /* Theme Name: Twenty Fifteen

    Child Theme URI: http://localhost/ Template: twentyfifteen Author: Advies en zo Author URI: http://adviesenzo.nl/ Description: My Child theme Text Domain: twentyfifteen-child Version: 1.0.0 */
  30. #phpworld Example singular.php <?php get_header(); ?> <div id="primary" class="content-area"> <?php

    while ( have_posts() ) : the_post(); if ( is_singular( array( 'employee' ) ) ) { get_template_part( 'template-parts/content', 'employee' ); } else { get_template_part( 'template-parts/content', 'singular' ); } endwhile; ?> </div><!-- #primary --> <?php get_footer(); ?>
  31. #phpworld Typical Theme Setup Functions // Hook 'after_setup_theme' add_theme_support( 'post-formats',

    $formats ); add_theme_support( 'post-thumbnails', $post_types ); add_theme_support( 'custom-background', $defaults ); add_theme_support( 'custom-header', $defaults ); add_theme_support( 'automatic-feed-links' ); // RSS add_theme_support( 'html5', $locations ); add_theme_support( 'title-tag' ); // WP 4.1+
  32. #phpworld Theme Customizer class MyTheme_Customizer { public static function register(

    $customizer ) { $customizer->add_section( 'my_section', $args ); $customizer->add_setting( 'my_setting', $args ); $customizer->add_control( $id, $args ); } public static function header_output() { // Customizer CSS } } add_action( 'customize_register', array( 'MyTheme_Customizer', 'register' ) ); add_action( 'wp_head', array( 'MyTheme_Customizer', 'header_output' ) );
  33. #phpworld functions.php function add_qr_code( $content ) { $url = 'http://api.qrserver.com/v1/create-

    qr-code/ ?size=100x100&data=' . urlencode( get_the_permalink() ); $esc_alt = the_title_attribute( array( 'before' => 'QR Code for', 'echo' => false ) ); return '<div class="qr-code"> <img src="' . esc_url( $url ) . '" alt="' . $esc_alt . '"/> </div>' . $content; } add_filter( 'the_content', 'add_qr_code' );
  34. #phpworld functions.php /* Change admin page footer Branding */ function

    my_admin_footer_text( $left ) { $left = '<img src="' . esc_url( get_stylesheet_directory_uri() . '/images/AEZ_logobw- 32x32.png' ) . '" width="32" height="32" align="left" />' . esc_html__( 'Webdevelopment, design and consultancy:', 'text-domain' ) . '<a href="http://adviesenzo.nl/">Advies en zo</a>'; return $left; } add_filter( 'admin_footer_text', my_admin_footer_text' );
  35. #phpworld Loading Order wp-config.php Must-use plugins Plugins • [MS] Network-activated

    plugins • Site-activated plugins Theme • Child-theme functions.php • Parent-theme functions.php
  36. #phpworld Starting a Plugin <?php /** * Plugin Name: Demo

    Quotes Plugin * Plugin URI: https://github.com/jrfnl/wp-plugin-best-practices-demo * Description: Demo plugin - Best Practices Tutorial * Version: 1.0 * Author: Juliette Reinders Folmer * Author URI: http://adviesenzo.nl/ * Text Domain: demo-quotes-plugin * Domain Path: /languages * License: GPL v3 */
  37. #phpworld What Every Plugin Needs  Hook your functionality onto

    actions and filters  Loading your localization files  Do something  Load CSS  Load JS  Add admin page or add to another admin page  Help information  Activation/ Upgrade routines  Uninstall routines  ...
  38. #phpworld Add a shortcode function display_call_to_action( $atts ) { $atts

    = shortcode_atts( array( 'user' => 'office', // Default ), $atts, 'calltoaction' ); $user = get_user_by( 'login', $atts['user'] ); $html = ''; if( $user ) { $html = '<!-- Here goes the actual box html -->'; } return $html; } add_shortcode( 'calltoaction', 'display_call_to_action' );
  39. #phpworld Add Oembed Provider // Register Speakerdeck as an oembed

    provider. function add_speakerdeck_oembed() { wp_oembed_add_provider( // URL format '`http[s]?://(www\.)?speakerdeck\.com/[^/]*/.*`i', // Endpoint 'https://speakerdeck.com/oembed.json', true // Is format a regex ? ); } add_action( 'init', 'add_speakerdeck_oembed' );
  40. #phpworld Add Custom Content Types & Taxonomies register_post_type( $post_type_name, //

    Post type name. Max of 20 chars. Uppercase and spaces not allowed. $args // Arguments for post type. ); register_taxonomy( $taxonomy_name, // Taxonomy internal name. Max 32 chars. Uppercase and spaces not allowed. array( $post_type_name ), // Post types to register this taxonomy for. $args // Arguments for taxonomy. );
  41. #phpworld Add a Settings Page register_setting( $option_group, $option_name, $sanitize_callback );

    get/update/delete_option( $option_name ); add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $page_slug, $call_back ); add_settings_section( $section_id, $title, $callback, $page_slug ); add_settings_field( $id, $title, $callback, $page_slug, $section_id, $args ); settings_fields( $option_group ) do_settings_sections( $page_slug ); do_settings_fields( $page_slug, $section_id );
  42. #phpworld Add a Widget class My_Widget extends WP_Widget { //

    widget actual processes public function __construct() {} // outputs the content of the widget public function widget( $args, $instance ) {} // outputs the options form on admin public function form( $instance ) {} // processes widget options to be saved public function update( $new_instance, $old_instance ) {} } add_action( 'widgets_init', create_function( '', 'return register_widget( "My_Widget" );' ) );
  43. #phpworld Enqueue Scripts & Styles wp_register_style( 'handle', plugins_url( 'css/style' .

    $suffix . '.css', __FILE__ ), array(), VERSION, 'all' ); wp_enqueue_style( 'handle' ); wp_register_script( 'handle', plugins_url( 'js/file' . $suffix . '.js', __FILE__ ), array( 'jquery', 'wp-ajax-response' ), VERSION, true ); // load in footer wp_enqueue_script( 'handle' ); wp_localize_script( 'handle', 'i18n_js_objectname', array() );
  44. #phpworld (De-)Activation, Upgrade, Uninstall  (De-)Activation:  Upgrading -> save

    plugin version nr & compare  Uninstall -> uninstall.php file /* Set up the (de-)activation actions */ register_activation_hook( __FILE__, array( 'Plugin_Class', 'activate' ) ); register_deactivation_hook( __FILE__, array( 'Plugin_Class', 'deactivate' ) );
  45. #phpworld Don’t Reinvent the Wheel Dashboard Widgets API Database API

    HTTP API File Header API Filesystem API Heartbeat API Metadata API Options API Plugin API Quicktags API REST API * Rewrite API Settings API Shortcode API Theme modification API Theme customization API Transients API Widgets API XML-RPC WordPress API * Expected in WP 4.4
  46. #phpworld Use WP Functions PHP  mysqli_...()  file_put_contents() 

    json_encode()  mail()  unserialize()  htmlspecialchars()  add/stripslashes()  strtotime() / date()  http_build_query()  $_SERVER['HTTPS'] ... WP  $wpdb->....()  $wp_filesystem->put_contents()  wp_json_encode()  wp_mail()  maybe_unserialize()  esc_html()  wp_unslash()  mysql2date() / current_time()  add_query_arg()  is_ssl() ... (I mean it!)
  47. #phpworld Useful Plugins Debug Bar + Extensions Developer Pig Latin

    User Switching Log Deprecated Notices What’s Running Demo Data Theme Check RTL Tester
  48. #phpworld Helpful Infrastructure WordPress Coding Standards CS WP Unit Testing

    Framework Varying Vagrant Vagrants WP CLI Generate WP WP Gear WPackagist vs TGMPA
  49. #phpworld Photo Credits  WordPress - mkhmarketing (crayons) http://www.flickr.com/photos/mkhmarketing/8469030267/ 

    Bridge - Glenn Euloth http://www.flickr.com/photos/eulothg/4956082108/  WordPress - Jenn Vargas http://www.flickr.com/photos/foreverdigital/2768397344/  Billie Holiday – William P. Gottlieb http://lcweb2.loc.gov/diglib/ihas/loc.natlib.gottlieb.04251/default.html  Anatomy - Eva di Martino http://www.pureblacklove.com  Hooks - Raul Lieberwirth http://www.flickr.com/photos/lanier67/185311136/  Loop - Gabe Kinsman http://www.flickr.com/photos/auguris/5286612308/  WordPress - Saad Irfan (core, plugins, themes) http://www.flickr.com/photos/saadirfan/5722057280/