Developing Complex WordPress Sites without Fear of Failure (with MVC)
1. #complexwp | wplib.org | @mikeschinkel
Developing Complex
WordPress Sites*
*Without Fear of Failure
Presenter: Mike Schinkel
WordCamp Raleigh 2015
2. #complexwp | wplib.org | @mikeschinkel
What to Expect
• Target Audience for the Talk
• Overview of Professional Workflow
• Use of Object Orientation
• Demo of code from a real-world project
• How to make it easy by using WPLib
3. #complexwp | wplib.org | @mikeschinkel
Prerequisites
• Experience building WordPress websites
• Comfortable developing in PHP
4. #complexwp | wplib.org | @mikeschinkel
About Me
• Self-Styled WordPress Architect
• Typical Work: $100k+ Agency Projects
• Many WordCamps, LoopConf
• WordPress is my 4th developer ecosystem
2006-2009: Drupal
1993-2006: Visual Basic
1986-1993: Clipper - a dBase Compiler
• Yada, yada
5. #complexwp | wplib.org | @mikeschinkel
Avoiding a WordPress
House of Cards
A.K.A. Avoiding
Kevin Spacey
6. #complexwp | wplib.org | @mikeschinkel
Best For Large Budget Projects
Where clients
just expect
us to:
7. #complexwp | wplib.org | @mikeschinkel
This approach NOT for "Tinkerers"
Who want to
fiddle with it after
you leave.
(And then yell at you
and ask for support
when they break it.)
8. #complexwp | wplib.org | @mikeschinkel
Disallow Adding of Plugins and
Themes in the Admin Consule
• Use a Custom
Theme
• Minimize 3rd
Party Plugins
9. #complexwp | wplib.org | @mikeschinkel
Use a Professional Workflow
● A Professional IDE
o PhpStorm+XDebug
● Version Control/Branching
o For Features, and
o For Bug Fixes
● A Deployment Process
o Development (Local)
o Test Server
o Staging Server
o Production Server
● See "Advanced WordPress Workflow”
o That is Micah Wood's talk, next session...
10. #complexwp | wplib.org | @mikeschinkel
Use an Intelligent Process
• Focus on Requirements
• Create clickable mockups using
moqups.com
• Then Architecture
• Decide on Post Types, Taxonomies, etc
• Separate Theming from
Architecture & Backend Coding
• Best if people with the different skills
are in the different roles
• Maximize “Deployable” Code
• User-entered Configuration Sux
11. #complexwp | wplib.org | @mikeschinkel
Use an Object Oriented Architecture
•Heard of MVC?
• Embrace Models and Views.
• And Items,
• And Lists,
• And Applications.
• And Helpers,
• And Templates,
• And Modules.
• More on those in a bit…
12. #complexwp | wplib.org | @mikeschinkel
Wherest thou Objects?
• Post Types
• Taxonomies
• User Roles
• And more!
13. #complexwp | wplib.org | @mikeschinkel
• Controllers = the "C" in MVC
• But Objects/Classes for
Routing != WordPress
• But you can usually hack it:
URL Routing In WordPress
http://tinyurl.com/wp-url-routing
WordPress handles the Controller (mostly)
14. #complexwp | wplib.org | @mikeschinkel
DEMO
Reviewing the Code of a
Real World Client Project
Warts and All
(see http://github/wplib for online examples)
15. #complexwp | wplib.org | @mikeschinkel
Make it easy with WPLib
• Designed for PHP Developers
• Assumes Persistent Cache
• Great for Building Reusable Code
16. #complexwp | wplib.org | @mikeschinkel
•It is Small
•Does not try to do that much
•Highly Consistent!
•Presents Structured Constraints
•Compatible with (all?) other Frameworks
•WPLib provides incremental value
•Can be used a little, or a lot
•Solves a problem no one else(?) is addressing
WPLib's Positive Attributes
17. #complexwp | wplib.org | @mikeschinkel
• One Application per site
• Provides root class for a site/app.
• Provides global but site-specific functionality, i.e.
$list = MyApp::get_featured_slide_list([$query]);
MyAPP::the_current_campaign_html();
$url = MyAPP::get_asset_url( 'images/visa-logo.png' );
if ( MyApp::is_featured_slider_enabled() ) {
//...
}
The Application Class
18. #complexwp | wplib.org | @mikeschinkel
Theme Class
• One Theme Class per theme
• Put your theme hooks here, e.g.
'wp_head'
'wp_enqueue_scripts'
• Location for theme global functionality, e.g.
$theme->the_ad_html();
$theme->the_slider_html();
• Lots of functionality in parent class, e.g.
$theme->the_header_html(); // same as get_header()
$theme->the_site_name();
$page_id = $theme->front_page_id();
19. #complexwp | wplib.org | @mikeschinkel
Model Classes
• Most of the “business logic" goes here.
• All the “facts” about a type of Item
• One per Item type
class MyApp_Story_Model extends WPLib_Post_Model {
function has_sponsor() {
$has = get_post_meta( $this->ID(), '_myapp_has_sponsor', true );
return 1 == intval( $has );
}
}
20. #complexwp | wplib.org | @mikeschinkel
View Classes
• Specific methods for outputting Item info
• One or more Views per Item type
• Maybe one View for HTML, one for JSON, etc.
• Most functionality needed in parent class
class MyApp_Featured_Slide_View extends WPLib_Post_View_Base {
function the_embed_code_html() {
echo $this->embed_code();
}
function the_embed_code_textarea() {
echo htmlspecialchars( $this->embed_code() );
}
}
21. #complexwp | wplib.org | @mikeschinkel
Item Classes
• Container for a Model and a View.
• ONLY class of Model+View+Item you actually use
• Most functionality in the parent class
• Rarely has much if any code
class MyApp_Campaign extends WPLib_Post_Base {
const POST_TYPE = MyApp_Campaigns::POST_TYPE;
const VAR_NAME = 'campaign';
}
22. #complexwp | wplib.org | @mikeschinkel
List Classes
• Smart arrays of Items
• Can be custom classes with use-case specific methods
• But usually you only need the Default List Class
foreach( MyApp_Featured_Slides::get_list() as $slide ) {
$slide->the_template( 'slide-card' );
}
// OR JUST:
MyApp_Featured_Slides::get_list()->the_template( 'slide-card' );
23. #complexwp | wplib.org | @mikeschinkel
Helper Classes
• Think of a Helper as "A List of Related Functions"
• Contributes Static Methods
• To your Application class
• We do the same for the WPLib class
• Enables making small, easy to learn APIs
• The Application class is the method "router"
• Helper Method names must be unique across an Application
• Better approach than a single "God" Class
• Allows for many smaller files
• Clearer source code organization
• Better source file management
25. #complexwp | wplib.org | @mikeschinkel
Module Classes
• Provides Functionality
• Like a Plugin
• Designed for Developers
• Unlike a Plugin
• Designed to be small
• If one grows too big, split it up!
• Should be highly cohesive
• Group related functionality together
26. #complexwp | wplib.org | @mikeschinkel
• A Main "Entry Point" file
• Contains a main class
• Should hook all hooks needed on page load
• Optimized to load efficiently
• Zero or more /includes/ files
• One class per file
• Include files are autoloaded
• Architected to be Composible
• Reusability: Yeah Baby!
Module Classes (cont'd)
27. #complexwp | wplib.org | @mikeschinkel
WPLib Templates
• Like Template Parts
• Not template files like single.php, home.php, et. al.
• Typically scoped to an Item
• Or scoped to the Theme class ($theme)
• Or with no scope (called using MyApp::)
• Loaded by $item->the_template('part') method
• Templates in {theme}/templates/{part}.php
28. #complexwp | wplib.org | @mikeschinkel
Constraints are your Friends
• Templates should contain NO
implementation details
•Should contain ONLY site-specific HTML or
CSS and method calls.
•No WP_Query, no get_post_meta(), etc.
29. #complexwp | wplib.org | @mikeschinkel
• Contains NO site-specific HTML or CSS
•Auto-generate "the_" methods
•For rendering output
•Conventions for escaping output
•"_url"
•"_attr"
•"_html"
•suffix, etc.
View Methods
30. #complexwp | wplib.org | @mikeschinkel
A Few Well-Known Constants
•POST_TYPE
•Use to specify the post type in a Post Type Module.
•TAXONOMY
•Use to specify the taxonomy in a Taxonomy Module.
•ROLE
•Use to specify the user role in a User Role Module.
•VAR_NAME
•Use to specify an $item's auto assigned variable name in a template.
•INSTANCE_CLASS
•Use to specify the $item's class name in an MVI module class.
31. #complexwp | wplib.org | @mikeschinkel
To Learn More about WPLib
•Clone from GitHub, Review sample apps:
•github.com/wplib
•Visit wplib.org
•For Quick Start and other Docs
•Submit issues on GitHub:
•github.com/wplib/wplib/issues
•Ask questions on Twitter:
•@mikeschinkel / @wpscholar
•Discuss on Slack
•Ok: wordpress.slack.com (mikeschinkel/wpscholar)
•Best: thecodersguild.slack.com#wplib
•Email mike@newclarity.net for access