Slide 1

Slide 1 text

WordPress For The Win! Juliette Reinders Folmer / @jrf_nl

Slide 2

Slide 2 text

#phpworld

Slide 3

Slide 3 text

#phpworld Who Am I? Self-employed, Independent Consultant Creator PHPCheatsheets phpcheatsheets.com Frequent Contributor to Open Source Projects

Slide 4

Slide 4 text

#phpworld

Slide 5

Slide 5 text

#phpworld  Themes  Plugins  SEO  Ease of use  Scalability  Support community  Regular updates  Learning curve  Setup costs  Maintenance costs  Hacker target

Slide 6

Slide 6 text

#phpworld

Slide 7

Slide 7 text

#phpworld Anatomy of WordPress

Slide 8

Slide 8 text

#phpworld Page footer Admin Bar Page content (loop) Page header (Invisible) HTML Sidebar containing widgets (Main) menu

Slide 9

Slide 9 text

#phpworld Admin Bar (Invisible) HTML Admin footer Admin Menu 1. Post types 2. Custom- izations 3. Extras Admin page (with dashboard widgets)

Slide 10

Slide 10 text

#phpworld Anatomy of WordPress Functionality  Core  Plugins  Themes  Languages  Js Libraries Content  Post Types  Taxonomies  Widgets  Users  Meta data/custom fields  Options  Shortcodes  OEmbeds

Slide 11

Slide 11 text

#phpworld Hooks

Slide 12

Slide 12 text

#phpworld Hooks See:  WordPress Codex & Developer Reference  Hooks database: http://adambrown.info/p/wp_hooks  Debug Bar – Action & filter hooks plugin

Slide 13

Slide 13 text

#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 );

Slide 14

Slide 14 text

#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

Slide 15

Slide 15 text

#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

Slide 16

Slide 16 text

#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

Slide 17

Slide 17 text

#phpworld The Loop

Slide 18

Slide 18 text

#phpworld The Loop if ( have_posts() ) : while ( have_posts() ) : the_post(); // // Post Content here // the_title() // the_content() // the_permalink() // ... endwhile; endif;

Slide 19

Slide 19 text

#phpworld WordPress in Practice

Slide 20

Slide 20 text

WordPress in Your Language

Slide 21

Slide 21 text

#phpworld Localized  ~60 languages + ~30 > 50%  GlotPress translate.wordpress.org

Slide 22

Slide 22 text

wp-config.php Tips & Tricks

Slide 23

Slide 23 text

#phpworld

Slide 24

Slide 24 text

#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 );

Slide 25

Slide 25 text

#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 );

Slide 26

Slide 26 text

#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 );

Slide 27

Slide 27 text

#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' );

Slide 28

Slide 28 text

#phpworld SSL /* Force secure logins and admin sessions */ define( 'FORCE_SSL_LOGIN', true ); define( 'FORCE_SSL_ADMIN', true );

Slide 29

Slide 29 text

#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' );

Slide 30

Slide 30 text

#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 );

Slide 31

Slide 31 text

#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' );

Slide 32

Slide 32 text

#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

Slide 33

Slide 33 text

#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');

Slide 34

Slide 34 text

#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 );

Slide 35

Slide 35 text

#phpworld

Slide 36

Slide 36 text

#phpworld FTP Credentials /* FTP settings */ define( 'FTP_HOST', 'hostname:port' ); define( 'FTP_USER', 'username' ); define( 'FTP_PASS', 'password' ); define( 'FTP_SSL', true );

Slide 37

Slide 37 text

#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);

Slide 38

Slide 38 text

#phpworld Basic Query Debugging /* Remember the DB queries run for the current page. */ define( 'SAVEQUERIES', true );

Slide 39

Slide 39 text

WP Cron

Slide 40

Slide 40 text

#phpworld WP Cron

Slide 41

Slide 41 text

#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);

Slide 42

Slide 42 text

#phpworld Disable WP-Cron /* Disable WP-cron in favor of real cron */ define( 'DISABLE_WP_CRON', true );

Slide 43

Slide 43 text

#phpworld

Slide 44

Slide 44 text

#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'

Slide 45

Slide 45 text

Theming Your Site

Slide 46

Slide 46 text

#phpworld

Slide 47

Slide 47 text

#phpworld

Slide 48

Slide 48 text

Child Themes

Slide 49

Slide 49 text

#phpworld Creating a Child Theme

Slide 50

Slide 50 text

#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 */

Slide 51

Slide 51 text

#phpworld Template Hierarchy Source: http://wphierarchy.com/

Slide 52

Slide 52 text

#phpworld Example singular.php

Slide 53

Slide 53 text

Functions.php

Slide 54

Slide 54 text

#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+

Slide 55

Slide 55 text

#phpworld Typical Theme Setup Functions // Hook 'init' register_nav_menus(); // Hook 'widget_init' register_sidebars();

Slide 56

Slide 56 text

#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' ) );

Slide 57

Slide 57 text

#phpworld Theme Customizer

Slide 58

Slide 58 text

#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 '
' . $esc_alt . '
' . $content; } add_filter( 'the_content', 'add_qr_code' );

Slide 59

Slide 59 text

#phpworld

Slide 60

Slide 60 text

#phpworld

Slide 61

Slide 61 text

#phpworld functions.php /* Change admin page footer Branding */ function my_admin_footer_text( $left ) { $left = '' . esc_html__( 'Webdevelopment, design and consultancy:', 'text-domain' ) . 'Advies en zo'; return $left; } add_filter( 'admin_footer_text', my_admin_footer_text' );

Slide 62

Slide 62 text

Extending WordPress

Slide 63

Slide 63 text

#phpworld

Slide 64

Slide 64 text

#phpworld

Slide 65

Slide 65 text

#phpworld

Slide 66

Slide 66 text

#phpworld Must-use Plugins

Slide 67

Slide 67 text

#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

Slide 68

Slide 68 text

Create a Plugin

Slide 69

Slide 69 text

#phpworld Starting a Plugin

Slide 70

Slide 70 text

#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  ...

Slide 71

Slide 71 text

#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 = ''; } return $html; } add_shortcode( 'calltoaction', 'display_call_to_action' );

Slide 72

Slide 72 text

#phpworld

Slide 73

Slide 73 text

#phpworld

Slide 74

Slide 74 text

#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' );

Slide 75

Slide 75 text

#phpworld

Slide 76

Slide 76 text

#phpworld

Slide 77

Slide 77 text

#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. );

Slide 78

Slide 78 text

#phpworld

Slide 79

Slide 79 text

#phpworld

Slide 80

Slide 80 text

#phpworld

Slide 81

Slide 81 text

#phpworld

Slide 82

Slide 82 text

#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 );

Slide 83

Slide 83 text

#phpworld

Slide 84

Slide 84 text

#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" );' ) );

Slide 85

Slide 85 text

#phpworld

Slide 86

Slide 86 text

#phpworld

Slide 87

Slide 87 text

#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() );

Slide 88

Slide 88 text

#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' ) );

Slide 89

Slide 89 text

Doing Things the WordPress Way

Slide 90

Slide 90 text

#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

Slide 91

Slide 91 text

#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!)

Slide 92

Slide 92 text

Developing & Debugging

Slide 93

Slide 93 text

#phpworld Useful Plugins Debug Bar + Extensions Developer Pig Latin User Switching Log Deprecated Notices What’s Running Demo Data Theme Check RTL Tester

Slide 94

Slide 94 text

#phpworld Tools

Slide 95

Slide 95 text

#phpworld Helpful Infrastructure WordPress Coding Standards CS WP Unit Testing Framework Varying Vagrant Vagrants WP CLI Generate WP WP Gear WPackagist vs TGMPA

Slide 96

Slide 96 text

#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/

Slide 97

Slide 97 text

#phpworld

Slide 98

Slide 98 text

Thank You! Slides: http://speakerdeck.com/jrf Feedback: https://joind.in/14755 Contact me: @jrf_nl jrf