101

Title Text

 

Daniel Le Blanc  
CEO, ctrlweb  
Software Engineer  
    @danidou  

 

This is a hands-on talk

You can follow the steps on your own computer as we go.

What is Themosis?

  • A lightweight MVC Web Development Framework
  • Built on top of WordPress
  • Brings modern best development practices to popular CMS

WordPress

  • Very popular (28,2% of all websites!)
  • Stable, well-maintained Content Management System
  • User-friendly admin dashboard

Best of two worlds!

Themosis

  • MVC Architecture Pattern
  • Uses Composer, gulp, npm, SASS, WP-CLI...
  • Works with templating engines (ex.: Laravel Blades) 
  • Multiple environments management (dev, prod)
  • Better for complex data architecture & business logic

Best of two worlds!

Prerequisites

  • PHP >= 5.6.4
  • Composer - getcomposer.org
  • MySQL & Apache (of course)

Options

  • WP-CLI - Command Line Interface
  • Bower - Javascript Package Manager
  • Gulp - A development automation tool
  • SASS - A modern CSS extension

Installation in four steps

$ composer create-project themosis/themosis my-project-name

1 - Create the project

2 - Edit /config/environment.php

<?php

/*----------------------------------------------------*/
// Define environment type
/*----------------------------------------------------*/
return [
    'local' => ['*.dev', 'scotchbox'],
    'production' => 'themosis-101.com'
];

Installation in four steps

DB_NAME = "themosis101"
DB_USER = "root"
DB_PASSWORD = "root"
DB_HOST = "localhost"
WP_HOME = "http://themosis-101.dev"
WP_SITEURL = "http://themosis-101.dev/cms"

3 - Edit /.env.local

4 - Install and configure database

$ wp db create
Success: Database created.
$ wp core install --url=themosis-101.dev \
  --title="Themosis 101" --admin_user=daniel \
  --admin_password=verystrong \
  --admin_email=daniel@ctrlweb.ca
Success: WordPress installed successfully.

Project Structure

+-- bootstrap/
+-- config/
|   +-- environments/
|   +-- environment.php
|   +-- shared.php
+-- htdocs/
|   +-- cms/
|   +-- content/
|   |   +-- mu-plugins
|   |   +-- plugins
|   |   +-- themes/
|   |       +-- themosis-theme
|   +-- index.php
|   +-- wp-config.php
+-- library/
+-- storage/
+-- vendor/
+-- .env.local
+-- composer.json
+-- wp-cli.yml

Project Structure

+-- htdocs/
    +-- content/
        +-- themes/
            +-- themosis-theme/
                +-- assets/
                +-- dist/
                +-- languages/
                +-- resources/
                |   +-- admin/
                |   +-- config/
                |   +-- controllers/
                |   +-- helpers/
                |   +-- models/
                |   +-- providers/
                |   +-- views/
                |   +-- widgets/
                |   +-- routes.php
                +-- functions.php
                +-- style.css

MVC Workflow

Themosis Workflow

Routes

// WordPress "front" page
Route::get('front', 'Pages@home');

// WordPress page with defined template
Route::get('template', ['contact-template', 'uses' => 'Pages@contact']);

// Custom Post Type -- list and detail
Route::get('postTypeArchive', ['participant', 'uses' => 'Participants@all']);
Route::get('singular',        ['participant', 'uses' => 'Participant@get']);

// 404 page
Route::get('404', 'Pages@page404');

// Specified URL with POST, or even other HTTP verbs!
Route::post('/participants/{$id}', 'Participants@get');
Route::delete('postTypeArchive', ['project', 'uses' => 'Projects@delete']);

Match an URL and a HTTP verb to a function (normally a Controller)

Controllers

namespace Theme\Controllers;
use Themosis\Route\BaseController;

class Participants extends BaseController {

  public function __construct() {
    Asset::add('jquery', '//code.jquery.com/jquery-3.2.1.min.js', [], '3.2.1', true);
    Asset::add('jquery-validation', themosis_theme_assets().'/js/jquery.validate.min.js', 
        ['jquery'], '1.16.0', true);

    Asset::add('themosis-101', 'css/themosis-101.css', false, '1.0', 'all');
  }

  public function all() {
    return View::make('pages.participants', array('participants' => ParticipantsModel::all());
  }

  public function get($id) {
    return View::make('pages.participant', array('participant' => ParticipantsModel::get($id));
  }

}

Bridge between data and its visual representation. Orchestrates and delegates.

PostTypes / Metaboxes / Fields
(Admin)

PostType::make('participant', __('Participants'), __('Participant'))->set([
    'public' => true,
    'rewrite' => [
        'slug' => 'participants'
    ],
]);

Metabox::make('Details', 'participant')->set([
  Field::media( 'picture', ['title' => __('Picture'), 'type' => 'image']),
  Field::text( 'website', ['title' => __('Website'])),
]);

Create Custom Post Types and Fields in WordPress Admin. 

Models

class ParticipantModel {

  public static function all($hydrate = true) {
    $query = new WP_Query([
      'post_type'         => 'participant',
      'posts_per_page'    => -1,
      'post_status'       => 'publish'
    ]);

    $participants = $query->get_posts();
    if ($hydrate) {
      $participants = self::hydrate($participants);
    }
    return $participants;
  }

  private static function hydrate($participants) {
    foreach($participants as $participant) {
      $participant->picture = Meta::get($participant->ID, 'picture');
      $participant->website = Meta::get($participant->ID, 'website');
    }
    return $participants;
  }

}

Retrieve data stored in the database.

Templates (Views)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Themosis 101</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="{{ themosis_theme_assets() }}/css/themosis-101.css">
  <?php wp_head(); ?>
  @yield('custom-styles')
</head>
<body>
  <div class="container main-container">
    @yield('main')
  </div>
  <footer class="footer">
    @yield('footer')
  </footer>
  <?php wp_footer(); ?>
</body>
</html>

Represent data in a certain format (typically HTML)

/views/layouts/main.blade.php

Templates (Views)

@extends('layouts.page')

@section('main')
  <h1>Participants</h1>
  @foreach($participants as $participant)
    {{ $participant->website }}
  @endforeach
@endsection

@section('footer')
  © Copyright 2017 - ctrlweb
@endsection

/views/pages/participants.blade.php

Enough Talk!

Let's CODE!

Made with Slides.com