Cześć

Timber

Wprowadzenie

Marcin Krzemiński

Co to jest?

  • Wtyczka do WordPressa stworzona przez Upstatement (Jared Novack)
  • Stworzona w celu ułatwienia pracy przy tworzeniu motywów
  • Separuje kod PHP od kodu HTML. Logika i dane dostarczane są przez PHP natomiast HTML tworzony jest przy pomocy systemu szablonów o nazwie Twig
  • Automatyczna integracja z popularną wtyczką Advanced Custom Fields

Dla kogo to jest?

Dla każdego ;)

Początkującym pozwoli pokonać barierę wejścia ze względu na łatwiejszą składnię.

Zaawansowanym pozwoli korzystać z dobrodziejstw Twiga.

Twig - brat bliźniak

  • System szablonów stworzony przez tych samych ludzi, którzy stworzyli framework PHP - Symfony
  • Prosty i zrozumiały nawet dla developerów z małym doświadczeniem
  • Wsparcie dla takich rozwiązań jak dziedziczenie, bloki (moduły) i wiele innych
  • Szybki bo kompilowany do czystego kodu PHP

Jak to wygląda w kodzie?


// single.php
$context = Timber::get_context();
$context['foo'] = 'Bar!';
$context['post'] = new Timber/Post();
Timber::render('single.twig', $context);
// single.twig
{% extends "base.twig" %}
{% block content %}

{{ foo }}

{{ post.title }}

{{ post.content }}
{% endblock %}

Instalacja i konfiguracja

Krok po kroku

1. Zainstaluj odpowiednią wtyczkę

2. Użyj timber-starter-theme

wp-content/plugins/timber-library → wp-content/themes/

3. Aktywuj timber-starter-theme

4. Zacznij kodować ;->

Trochę szczegółów

Struktura motywu 1 / 3

  • Wygląda jak standardowy motyw, prawda?
  • W folderze static umieszczamy nasze pliki JS, CSS/Sass, obrazki, fonty, itp. Oczywiście można trzymać swoje assety gdzie indziej jeśli jesteśmy przyzwyczajeni do innej struktury.
  • W folderze templates znajdują się szablony Twiga. Nazwa tego folderu także może być inna jeśli zechcemy. Konfigurację można zmienić w pliku functions.php.

Struktura motywu 2 / 3

  • Jak wspomniałem wcześniej wrzucamy tutaj nasze pliki JS, CSS/Sass, obrazki, fonty, itp.
  • Jeśli jesteśmy przyzwyczajeni do innej struktury to oczywiście możemy zrobić tak aby było nam wygodniej. Pamiętajmy aby zostawić plik static/no-timber.html ponieważ jest on używany w momencie gdy aktywujemy motyw, a zapomnimy włączyć wtyczkę.

Struktura motywu 3 / 3

  • Większość plików odpowiada tym z folderu nadrzędnego: archive, index, page, single, itd.
  • Plik base.twig jest naszym głównym kontenerem. Zawiera w sobie bloki a także importuje części naszego motywy. Następnie plik ten jest używany poprzez funkcję extend w poszczególnych szablonach. Możemy mieć kilka kontenerów jeśli zajdzie taka potrzeba. Plik ten oczywiście może się nazywać inaczej np.: pagelayout.twig, layout.twig, full-widht.twig, itd.

Trochę kodu

functions.php


if ( ! class_exists( 'Timber' ) ) {
  add_action( 'admin_notices', function() {
      echo '

Timber not activated. Make sure you activate the plugin in ' . esc_url( admin_url( 'plugins.php') ) . '

'; }); add_filter('template_include', function($template) { return get_stylesheet_directory() . '/static/no-timber.html'; }); return; } Timber::$dirname = array('templates', 'views'); class StarterSite extends TimberSite { function __construct() { add_theme_support( 'post-formats' ); add_theme_support( 'post-thumbnails' ); add_theme_support( 'menus' ); add_filter( 'timber_context', array( $this, 'add_to_context' ) ); add_filter( 'get_twig', array( $this, 'add_to_twig' ) ); add_action( 'init', array( $this, 'register_post_types' ) ); add_action( 'init', array( $this, 'register_taxonomies' ) ); parent::__construct(); } function register_post_types() { //this is where you can register custom post types } function register_taxonomies() { //this is where you can register custom taxonomies } function add_to_context( $context ) { $context['foo'] = 'bar'; $context['stuff'] = 'I am a value set in your functions.php file'; $context['notes'] = 'These values are available everytime you call Timber::get_context();'; $context['menu'] = new TimberMenu(); $context['site'] = $this; return $context; } function myfoo( $text ) { $text .= ' bar!'; return $text; } function add_to_twig( $twig ) { /* this is where you can add your own functions to twig */ $twig->addExtension( new Twig_Extension_StringLoader() ); $twig->addFilter('myfoo', new Twig_SimpleFilter('myfoo', array($this, 'myfoo'))); return $twig; } } new StarterSite();

base.twig


{% block html_head_container %}
  {% include 'html-header.twig' %}
  {% block head %}
  {% endblock %}
  
{% endblock %}


  
{% block header %}

{{ site.name }}

{% endblock %}
{% if title %}

{{ title }}

{% endif %} {% if sidebar %} {% endif %}
{% block footer %}
{% include 'footer.twig' %}
{{ function('wp_footer') }} {% endblock %}

index.php


$context = Timber::get_context();
$context['posts'] = Timber::get_posts();
$context['foo'] = 'bar';
$templates = array( 'index.twig' );
if ( is_home() ) {
  array_unshift( $templates, 'home.twig' );
}
Timber::render( $templates, $context );

index.twig


{% extends "base.twig" %}

{% block content %}
  

{{ foo }}

{% for post in posts %} {% include ['tease-'~post.post_type~'.twig', 'tease.twig'] %} {% else %} Nie mamy żadnych postów, tej ;(. {% endfor %} {% endblock %}

page.php


$context = Timber::get_context();
$post = new TimberPost();
$context['post'] = $post;
$templates = array( 'page-' . $post->post_name . '.twig', 'page.twig' );
Timber::render( $templates, $context );

page.twig


{% extends "base.twig" %}

{% block content %}
  

{{ post.title }}

{{ post.content }}
{% endblock %}

page-plugin.twig


{% extends "base.twig" %}

{% block content %}
  
{{ post.content }}
{% endblock %}

menu.twig


{% if menu %}
  
    {% for item in menu %}
  • {{ item.title }} {% include "menu.twig" with { 'menu': item.get_children } %}
  • {% endfor %}
{% endif %}

Integracja z ACF

Pole tekstowe / WYSIWYG


{{ post.title }}

{{ post.get_field('my_wysiwyg_field') }}

Obrazek


Uwaga: Pole powinno zwracać ID obrazka.

Galeria zdjęć


{% for image in post.get_field('gallery') %}
  
{% endfor %}

Repeater


{{ post.title }}

{% for item in post.get_field('my_repeater') %}

{{ item.name }}

{{ item.info }}
{% endfor %}

Zagnieżdżony Repeater


// Źle
{% for gear in post.get_field('gear_items') %}
  

{{ gear.brand_name }}

{% for gear_feature in gear.get_field('features') %}
  • {{ gear_feature }}
  • {% endfor %} {% endfor %} // Dobrze {% for gear in post.get_field('gear_items') %}

    {{ gear.brand_name }}

    {% for gear_feature in gear.features %}
  • {{ gear_feature }}
  • {% endfor %} {% endfor %}

    Jeszcze więcej kodu ...

    Zmienne dostępne globalnie

    
    // site
    {{ site.description }}
    {{ site.name }}
    {{ site.title }}
    {{ site.url }}
    ...
    
    // theme
    {{ theme.link }} // dla motywu nadrzędnego
    {{ theme.parent.link }} // dla motywu potomnego
    {{ theme.path }} // scieżka do pliku CSS aktywnego motywu
    ...
              

    Obsługa obrazków

    
    // Podstawowe
    Image for {{ post.title }}
    
    // Z użyciem zdefiniowanych rozmiarów
    Image for {{ post.title }}
    
    // Skalowanie
    
    
    
    // Konwertowanie
    
     // filtry od lewej do prawej
              

    Operacje na tekście

    
    // Formatowanie daty
    {{ post.post_date|date('d-m-Y') }} // 03-04-2017
    {{ now|date('Y') }} // 2017
    
    // Generowanie lorem ipsum
    // wymaga doinstalowania: https://github.com/timber/sugar
    {{ dummy(500)|wpautop }} // 500 wyrazów
    {{ post.title|dummy(15) }} // 15 wyrazów jeśli post.title pusty
              

    Internacjonalizacja

    
    // Standardowo
    
    
    // Notacja sprintf
    
              

    Odpalanie funkcji z poziomu pliku szablonu

    
    // Bez parametru
    {{ function('twenty_ten_entry_meta') }}
    
    // Z parametrem, w wersji skróconej
    {{ fn('get_the_title', post.ID) }}
              

    Debugowanie

    Konfiguracja

    
    // wp-config.php
    define('WP_DEBUG', true);
              

    Użycie

    
    // single.twig
    {{ dump(post) }}
    
    // wynik
    /Users/marcin/Sites/private/timber/wp-content/plugins/timber-library/vendor/twig/twig/lib/Twig/Extension/Debug.php:60:
    object(Timber\Post)[2842]
      public 'ImageClass' => string 'Timber\Image' (length=12)
      public 'PostClass' => string 'Timber\Post' (length=11)
      public 'TermClass' => string 'Timber\Term' (length=11)
      public 'object_type' => string 'post' (length=4)
      protected '_content' => null
      protected '_permalink' => null
      protected '_next' =>
        array (size=0)
          empty
      protected '_prev' =>
        array (size=0)
          empty
      public 'class' => string 'post-2 page type-page status-publish hentry' (length=43)
      public 'id' => int 2
      public 'ID' => int 2
      public 'post_author' => string '1' (length=1)
      public 'post_content' => string 'This is an example page. It's different from a blog post because it will stay in one place and will show up in your site navigation (in most themes). Most people start with an About page that introduces them to potential site visitors. It might say something like this:
    
    
    Hi there! I'm a bike messenger by day, aspiring actor by night, and this is my website. I live in Los Angeles, have a great dog named Jack, and I like piña coladas. (And gettin' caught in the rain.)
    ...or somet'... (length=954) public 'post_date' => string '2017-03-20 15:10:47' (length=19) public 'post_excerpt' => string '' (length=0) public 'post_parent' => int 0 public 'post_status' => string 'publish' (length=7) public 'post_title' => string 'Sample Page' (length=11) public 'post_type' => string 'page' (length=4) public 'slug' => string 'sample-page' (length=11) protected '__type' => null public '_wp_page_template' => string 'default' (length=7) public 'post_date_gmt' => string '2017-03-20 15:10:47' (length=19) public 'comment_status' => string 'closed' (length=6) public 'ping_status' => string 'open' (length=4) public 'post_password' => string '' (length=0) public 'post_name' => string 'sample-page' (length=11) public 'to_ping' => string '' (length=0) public 'pinged' => string '' (length=0) public 'post_modified' => string '2017-03-20 15:10:47' (length=19) public 'post_modified_gmt' => string '2017-03-20 15:10:47' (length=19) public 'post_content_filtered' => string '' (length=0) public 'guid' => string 'http://timber.dev/?page_id=2' (length=28) public 'menu_order' => int 0 public 'post_mime_type' => string '' (length=0) public 'comment_count' => string '0' (length=1) public 'filter' => string 'raw' (length=3) public 'status' => string 'publish' (length=7) public 'custom' => array (size=1) '_wp_page_template' => string 'default' (length=7)

    Podsumowanie

    • Timber to nie to samo co Tinder ;)
    • Upraszcza tworzenie motywów poprzez separację logiki od warstwy prezentacji
    • Dziedziczenie i modularyzacja na poziomie plików (szablonów) dzięki integracji z Twigiem
    • Integracja z ACF

    Wiedza

    Chcesz pracować z Timberem?

    Jeśli chcesz tworzyć projekty z oparciu o Timbera i nie tylko to zajrzyj na xfive.co/jobs/.

    * jeśli to nie problem to wspomnij, że trafiłeś tam dzięki mojej prezentacji a może dostanę za to mały bonusik ;)

    Dzięki za uwagę

    www.krzeminski.net


    Prezetancja dostępna pod: