Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Upcoming SlideShare
What to Upload to SlideShare
What to Upload to SlideShare
Loading in …3
×
1 of 68

[Bristol WordPress] Supercharging WordPress Development

0

Share

Download to read offline

Slide links:
- https://lumberjack.rareloop.com
- https://docs.lumberjack.rareloop.com
- https://github.com/Rareloop/lumberjack-bedrock-installer
- https://github.com/Rareloop/lumberjack
- https://github.com/Rareloop/lumberjack-validation
- https://github.com/Rareloop/hatchet

- https://lizkeogh.com/2017/08/31/reflecting-reality/amp
- https://www.upstatement.com/timber
- https://roots.io/bedrock
- https://scotch.io/bar-talk/s-o-l-i-d-the-first-five-principles-of-object-oriented-design
- https://github.com/zendframework/zend-diactoros
- https://www.php-fig.org
- http://php-di.org

---

Often WordPress themes are not easy to change, maintain or fun to work on. This can rule WordPress out as a viable option for bespoke, non-trivial websites.

In this talk we’ll dive into how this happens & look at how we can benefit from software engineering techniques to help make your code easier to change. I’ll also show how using Lumberjack, a powerful MVC framework built on Timber, can be used to power-up your themes.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

[Bristol WordPress] Supercharging WordPress Development

  1. 1. Supercharging 
 WordPress Development by Adam Tomat @adamtomat Slack
  2. 2. Digital Product Studio
  3. 3. Projects vs Products
  4. 4. Projects Cost of Introduction - Only adding new code (e.g. controllers, models etc)
  5. 5. Cost of Change - Making changes to existing code Cost of Ownership - Refactoring, writing tests etc Products
  6. 6. Konstantin Kudryashov - Laracon EU 2015
  7. 7. – Liz Keogh “You’re not really ‘done’ until the software has been retired and is no longer used at all”
  8. 8. Make your website
 easier to change.
  9. 9. I ❤ PHP I ❤ WordPress
  10. 10. “Not Waving But Drowning” - Stevie Smith
  11. 11. Starts with drips
  12. 12. Cognitive Behavioural Therapy
  13. 13. • Traffic on the way to work • Worrying about your body image • Not getting enough sleep • Financial difficulties • Worries about keeping a job • Being isolated Life: What can fill up your bathtub?
  14. 14. • Slow getting setup on project • Applying the same change/code across multiple files • Unstructured and undocumented setup • Introducing bugs or regressions • Painful deployments • Different conventions/style within the code (inconsistent) • Difficult to change • Unable to change the current situation WordPress: What fills your bathtub?
  15. 15. What does this code look like?
  16. 16. $the_query = new WP_Query([ 'posts_per_page' => 5, 'tag' => 'club' ]); if ($the_query->have_posts()) : ?> <h4>Recent Articles</h4> <ul> <?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?> <li class="article"> <h3><?php the_title(); ?></h3> <?php the_excerpt(10); ?> <a href="<?php the_permalink(); ?>">Read more</a> </li> <?php endwhile; ?> </ul> <?php endif; ?> t Mix of concerns: Presentation logic & Database queries " This file has multiple reasons to change index.php
  17. 17. $the_query = new WP_Query([ 'posts_per_page' => 5, 'tag' => 'club' ]); if ($the_query->have_posts()) : ?> <h4>Recent Articles</h4> <ul> <?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?> <li class="article"> <h3><?php the_title(); ?></h3> <?php the_excerpt(10); ?> <a href="<?php the_permalink(); ?>">Read more</a> </li> <?php endwhile; ?> </ul> <?php endif; ?> t Procedural " Procedural code is often not DRY or reusable.
 
 It’s difficult to change. Hard to read. index.php
  18. 18. odel C M V iew ontroller
  19. 19. https://www.rareloop.com/posts/comparing-modern-mvc-wordpress-frameworks/ WordPress MVC Frameworks
  20. 20. CONTENT SITE BESPOKE SYSTEM Project Spectrum
  21. 21. Timber!
  22. 22. <?php $context = Timber::get_context(); $context['posts'] = Timber::get_posts([ 'posts_per_page' => 5, 'tag' => 'club' ]); Timber::render('index.twig', $context); {% if posts is not empty %} <h4>Recent Articles</h4> <ul> {% for post in posts %} <li class="article"> <h3>{{ $post->title }}</h3> {{ $post->preview }} <a href="{{ $post->link }}">Read the full story</a> </li> {% endfor %} </ul> {% endif %} index.twig index.php
  23. 23. What are the problems with Timber controllers?
  24. 24. <?php $context = Timber::get_context(); $context['posts'] = Timber::get_posts([ 'posts_per_page' => 5, 'tag' => 'club' ]); Timber::render('index.twig', $context); index.php t Procedural " Procedural code is often not DRY or reusable.
 
 It’s difficult to change. Hard to read.
  25. 25. index.php class IndexController { } public function handle() { $context = Timber::get_context(); $context['posts'] = Timber::get_posts([ 'posts_per_page' => 5, 'tag' => 'club' ]); } extends BaseController return view('index.twig', $context);
  26. 26. index.php class IndexController extends BaseController { public function handle() { $context = Timber::get_context(); $context['posts'] = $this->getPosts(); return view('index.twig', $context); } private function getPosts() { return Timber::get_posts([ 'posts_per_page' => 5, 'tag' => 'club' ]); } }
  27. 27. Benefits • Write Object Orientated code rather than Procedural code • Separation of concerns • Easier to write DRY code • Can use inheritance to extend a base class for common functionality • Can encapsulate more complex routines in private functions
  28. 28. Setting up a project
 &
 Deploys
  29. 29. Traditional WordPress Theme WordPressTimber Yoast ACF
  30. 30. // ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define('DB_NAME', 'wordpress'); /** MySQL database username */ define('DB_USER', 'root'); /** MySQL database password */ define('DB_PASSWORD', ‘letmein'); /** MySQL hostname */ define('DB_HOST', 'localhost'); /** Database Charset to use in creating database tables. */ define('DB_CHARSET', 'utf8'); /** The Database Collate type. Don't change this if in doubt. */ define('DB_COLLATE', ''); wp-config.php
  31. 31. Bedrock 🙌
  32. 32. Theme Bedrock Bedrock WordPress v5.2.* Timber v1.9.* Wordpress SEO v10.0.* ACF v5.8.2
  33. 33. How does Lumberjack fit into this?
  34. 34. Lumberjack Starter Theme Lumberjack + Bedrock = ❤ Bedrock Lumberjack Core v4.3.* WordPress v5.2.* Timber v1.9.* Wordpress SEO v10.0.* ACF v5.8.2
  35. 35. Take Lumberjack for a spin
  36. 36. Supercharged Config
  37. 37. Some PHP file $apiKey = config('app.google_maps_api_key'); config/app.php return [ 'google_maps_api_key' => getenv('GOOGLE_MAPS_API_KEY', 'dummy-api-key'), ];
  38. 38. return [ 'logs' => [ 'enabled' => true, 'location' => '/tmp', ], ]; config/app.php Some PHP file $location = config(‘app.logs.location'); // => '/tmp'
  39. 39. Benefits • Structured file system • Dependencies managed (install with 1 command) • Supercharged config • Easier & safer deploys
  40. 40. Querying Data
  41. 41. $args = [ 'post_type' => 'product', 'posts_per_page' => 10, 'orderby' => 'title', 'order' => 'ASC', 'meta_query' => [ 'relation' => 'AND', [ 'key' => 'available_from_date', 'value' => [$from_date, $to_date], 'compare' => 'BETWEEN', 'type' => 'DATE', ], [ 'key' => 'available_to_date', 'value' => [$from_date, $to_date], 'compare' => 'BETWEEN', 'type' => 'DATE', ], ] ]; $query = new WP_Query($args); $posts = $query->get_posts();
  42. 42. use TimberPost; $post = new Post(1); $collection = Timber::get_posts($wpQueryArray); Timber Post Object
  43. 43. use RareloopLumberjackPost; use AppPostTypesProduct; $post = new Post(1); $collection = Post::query($wpQueryArray); $product = new Product(1); $collection = Product::query($wpQueryArray); Lumberjack Post Object
  44. 44. class Product extends Post { public function getPhotos() : array { // Do database query to get the assigned photos } } Encapsulate Business Logic $product = new Product(123); $photos = $product->getPhotos();
  45. 45. class Product extends Post { } Register Custom Post Types // config/posttypes.php return [ 'register' => [ AppPostTypesProduct::class, ], ]; protected static function getPostTypeConfig() { return [ 'labels' => [ 'name' => __('Products'), 'singular_name' => __('Product'), ], 'public' => true, 'has_archive' => false, ]; } public static function getPostType() { return 'product'; }
  46. 46. Supercharged Queries
  47. 47. Advanced Queries $productType = new ProductType; $products = Product::builder() ->whereMeta('type', '"' . $productType->id . '"', 'LIKE') ->limit(10) ->orderBy('title', 'asc') ->get();
  48. 48. Using the Query Builder directly $products = QueryBuilder::wherePostType([ Product::getPostType(), GiftSet::getPostType(), ]) ->limit(10) ->orderBy(‘title', 'asc') ->get();
  49. 49. Supercharged Custom Requests
  50. 50. Router::get('hello/world', function () { return HtmlResponse('<h1>Hello World!</h1>'); }); Simple Routes use RareloopLumberjackFacadesRouter; use ZendDiactorosResponseHtmlResponse;
  51. 51. Router::get('hello/{name}', function ($name) { return HtmlResponse('<h1>Hello ' . $name . '!</h1>'); }); echo Router::url('hello.world', ['name' => 'adam']); ->name('hello.world'); Params & Named Routes
  52. 52. Router::get('hello/world', 'HelloController@show'); Controller Definitions
  53. 53. AJAX endpoint that returns JSON class ArticleCommentController { } Router::post('articles/{id}/comments', 'ArticleCommentController@store'); public function store(int $id) { } $comment = request()->input('comment'); wp_new_comment([ 'comment_post_ID' => $id, 'comment_author' => get_current_user_id(), 'comment_content' => $comment, ]); return new JsonResponse([ 'data' => [ 'content' => $comment, ] ], 201);
  54. 54. • Extend WordPress site with custom URL endpoints (e.g. for ajax, forms) • Access to all REST based verbs • Can add Groups, for collecting similar resources together • Named routes • You have a convention & documentation Router benefits
  55. 55. • PSR11 Dependency Injection Container (using PHP-DI) • Facades • Exception Handling (PSR3) • Validation (currently an external package) • View Models More power at your fingertips ✨ • Service Providers • Hatchet (CLI) • Global helper functions (e.g. config(‘app.environment’); ) • ‘Responsable’ objects (from Laravel) - in, but currently undocumented
  56. 56. - Jared Novack - Timber creator “Lumberjack is the deluxe version of what Modern WordPress should look like today.
 
 The team has done a great job of making it easy to build complicated custom applications while taking advantage of the best parts of WordPress.”
  57. 57. • Evaluate the product mindset for you (and your team?) • WordPress is awesome, we can make it even more awesome! • Challenge and push your stack forward. Don’t accept dripping taps • Write code which is easier to change, where applicable • Give MVC WordPress a go • Use only what you need to in Lumberjack In summary…
  58. 58. docs.lumberjack.rareloop.com Documentation rareloop.com/careers Join Our Team lumberjack.rareloop.com Website
  59. 59. Get Involved ⭐

×