Wordpress,
Y U haz no template engine?

Timber =

Wordpress + Twig

http://wordpress.org + 

http://twig.sensiolabs.org/

=

http://upstatement.com/timber/

 

Wordpress...

<?php get_header(); ?>

	<div id="primary" class="site-content">
		<div id="content" role="main">
		<?php if ( have_posts() ) : ?>

			<?php /* Start the Loop */ ?>
			<?php while ( have_posts() ) : the_post(); ?>
				<?php get_template_part( 'content', get_post_format() ); ?>
			<?php endwhile; ?>

			<?php twentytwelve_content_nav( 'nav-below' ); ?>

		<?php else : ?>

			<article id="post-0" class="post no-results not-found">

			<?php if ( current_user_can( 'edit_posts' ) ) :
				// Show a different message to a logged-in user who can add posts.
			?>
				<header class="entry-header">
					<h1 class="entry-title"><?php _e( 'No posts to display', 'twentytwelve' ); ?></h1>
				</header>

				<div class="entry-content">
					<p><?php printf( __( 'Ready to publish your first post? <a href="%s">Get started here</a>.', 'twentytwelve' ), admin_url( 'post-new.php' ) ); ?></p>
				</div><!-- .entry-content -->

			<?php else :
				// Show the default message to everyone else.
			?>
				<header class="entry-header">
					<h1 class="entry-title"><?php _e( 'Nothing Found', 'twentytwelve' ); ?></h1>
				</header>

				<div class="entry-content">
					<p><?php _e( 'Apologies, but no results were found. Perhaps searching will help find a related post.', 'twentytwelve' ); ?></p>
					<?php get_search_form(); ?>
				</div><!-- .entry-content -->
			<?php endif; // end current_user_can() check ?>

			</article><!-- #post-0 -->

		<?php endif; // end have_posts() check ?>

		</div><!-- #content -->
	</div><!-- #primary -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>

index.php

index.twig

Timber

$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);
{% extends "base.twig" %}

{% block content %}
  <h2>{{foo}}</h2>
  <p>{{qux}}</p>
    {% for post in posts %}
      {% include ['tease-'~post.post_type~'.twig', 'tease.twig'] %}
    {% endfor %}

{% endblock %}

Timber Boilerplate

Starter-Theme

Timber

$context = Timber::get_context();
$context['foo'] = 'bar';
Timber::render('single.twig', $context);

static methods

Timber::get_context();
 $args = 'post_type=movies&numberposts=8&orderby=rand';
 $context['posts'] = Timber::get_posts($args);
Timber::get_posts($query = false, $class = 'TimberPost');

TimberPost

ID                  // ID of the post
post_author         // ID of the post author
post_date           // timestamp in local time
post_date_gmt       // timestamp in gmt time
post_content        // Full (unprocessed) body of the post
post_title          // title of the post
post_excerpt        // excerpt field of the post, caption if or custom string
post_mime_type      // mime type for attachment posts
comment_count       // number of comments
terms               // taxonomy terms
...
{{custom_field}}    // whatever custom field you've added

single.php

single.twig

TimberPost

$context = Timber::get_context();
$context['post'] = new TimberPost();
Timber::render('single.twig', $context);
<h1 class="headline">{{post.post_title}}</h1>
<div class="body">
  {{post.content}}
</div>
<h4 class="prep-time">
  Prep time: {{post.prep_time}}
</h4>

access even custom meta fields easily

TimberPost

<h2>{{post.title}}</h2>
<div class="tease-text">{{post.get_preview(40)}}</div>

method: get_preview()

get_preview($len = 50, $force = false, $readmore = 'Read More', $strip = true)

TimberPost

<h2>{{post.title}}</h2>
{% if post.thumbnail %}
  <img src="{{post.thumbnail.src}}" class="post-thumb"/>
{% endif %}}

method: thumbnail()

thumbnail()

TimberPost

class MySitePost extends TimberPost {

    var $_issue;

    public function issue() {
        $issues = $this->get_terms('issues');
        if (is_array($issues) && count($issues)) {
            return $issues[0];
        }
    }
}

Property or method missing?
Extend Timber!

$myPosts = Timber::get_posts($queryargs, "MySitePost")

TimberImage

<img src="{{post.get_thumbnail.get_src|resize(600, 400)}}" />


// thumbnail() returns get_thumbnail()
// src() returns get_src()
<img src="{{post.thumbnail.src|resize(600,400)}}" />

resize filter

get_src|resize($width, $height = 0, 
$crop = 'default')

Timber / Twig

/* functions.php */

add_filter('get_twig', 'add_to_twig');

function add_to_twig($twig) {
    /* this is where you can add your own fuctions to twig */
    $twig->addExtension(new Twig_Extension_StringLoader());
    $twig->addFilter('whatever', new Twig_Filter_Function('my_whatever'));
    return $twig;
}

function my_whatever($text) {
    $text .= ' or whatever';
    return $text;
}

Adding filters to twig

<h2>{{ post.title|whatever }}</h2>
<h2>Hello World! or whatever</h2>

TimberMenu

/* functions.php*/ 

add_filter('timber_context', 'add_to_context');
function add_to_context($data){

    $data['foo'] = 'I am some other typical value set in your functions.php file, unrelated to the menu';
    $data['menu'] = new TimberMenu();
    return $data;
}

define in global context

register_nav_menu('my_special_menu', 'Special Menu ftw');

...  
$data['special_menau'] = new TimberMenu('my_special_menu');
...

TimberMenu

<nav>
  <ul class="main-nav">
    {% for item in menu.get_items %}
        <li class="nav-main-item {{item.classes | join(' ')}}"><a class="nav-main-link" href="{{item.get_link}}">{{item.title}}</a>
           {% if item.get_children %}
              <ul class="nav-drop">
              {% for child in item.get_children %}
               <li class="nav-drop-item"><a href="{{child.get_link}}">{{child.title}}</a></li>
              {% endfor %}
              </ul>
           {% endif %}
        </li>
   {% endfor %}
  </ul>
</nav>

no walker-function ever again!

Wordpress

{{wp_head}}

{{wp_footer}}


{{function('my_function','my_param')}}


{% do action('my_action') %}


{{dump(post)}}

*.twig

hooks & functions

Wordpress

<p class="entry-meta"><?php _e('Posted on', 'my-text-domain') ?> [...]</p>

internationalization

<p class="entry-meta">{{__('Posted on', 'my-text-domain')}} [...]</p>

*.php (old)

*.twig (new is always better)

Timber

Timber::add_route('blog/:name', function($params){
    $query = 'posts_per_page=3&post_type='.$params['name'];
    Timber::load_template('archive.php', $query);
});

Timber::add_route('blog/:name/page/:pg', function($params){
    $query = 'posts_per_page=3&post_type='.$params['name'].'&paged='.$params['pg'];
    Timber::load_template('archive.php', $query);
});

Routing à la node.js

Timber + Wordpress

  • Twig Template Engine
  • Better Post-Objects
  • Better Image-Objects
  • Twig-Filter (resizing and cropping!)
  • Better Menu-Handling
  • Integrated WP-Functions
  • Routing
  • Caching
  • ...

 

Timber + Wordpress

=

http://upstatement.com/timber/

thx, @mileonnet

TimberWP

By mileonnet

TimberWP

  • 1,089