0
votes

I am new to Timber/Twig/PHP and have a fairly specific requirement. I have a page-home.php / page-home.twig which displays a couple of ACF fields, testimonials as a custom post type, and the latest 3 blog posts.

I'm mostly fine with the Twig frontend part, but having difficulties with setting up the php template files.

I've read the Timber docs and got the impression that ACF is baked in, so that the field can just be called directly in Twig. Also checked Github and SO for similar issues but did not find an answer. There is a video on youtube that covers custom post types, but it is within a loop of only posts.

This is my page-home.php

echo 'page-home.php';

$context = Timber::get_context();
$context['page'] = new Timber\Post();

$templates = array('page.twig');
if (is_front_page()){

    $context['posts'] = Timber::get_posts('post_type=post&posts_per_page=3');
    $context['testimonials'] = Timber::get_posts('post_type=testimonials');

    // add your twig view to the front of the templates array
    array_unshift($templates, 'page-home.twig');
}

Timber::render( $templates, $context );


$image = get_field('hero_image');

echo '<pre>';
    var_dump( $image );
echo '</pre>';

page-home.php is showing 3 blog posts as expected, but returning a NULL value for the ACF field var_dump.

If I comment this line // $context['posts'] = new Timber\PostQuery($args); I get the var_dump of my image array, though it doesn't render in the Twig file.

This is the image in page-home.twig <div class="image image-overlay" style="background-image:url({{ Image(post.meta('hero_image')).src }})"></div> which returns blank.

Blog posts are being called as:

{% for post in posts %}
  {% include "blogpost-card.twig" %}
{% endfor %}

I am also unsure how to call a separate custom post type (testimonials) on the same page since the documentation does not provide that example.

I'm using the starter-theme installed through Composer. It would be great if the theme or the documentation provided an example of a page containing posts, custom posts and ACF fields since I guess this is a very common scenario. At least for those like myself who need a little extra help with the PHP side.

2
At least for one part of this problem I was making a mistake in choice of template. Since the custom field (an image) is set on Page Home, this page needs to be set as static homepage in Customizer. I am using page-home.php and page-home.twig In that case I needed array_unshift($templates, 'page-home.twig'); However the image still does not render, even though the var_dump returns data, and I still cannot get both posts and testimonials to appear.Yan White
I've finally been able to get both post types with: $data['posts'] = Timber::get_posts('post_type=post&posts_per_page=3'); $data['testimonials'] = Timber::get_posts('post_type=testimonials'); and 'for post in posts (or) testimonials'Yan White
For some reason the ACF field is not getting passed through to the Twig template. The var_dump was coming directly from the PHP. If I do {{ dump(user) }} in the Twig file I get data. But if I do {{ dump(post.hero_image) }} (or ..hero_image, or image) I get NULL. Will keep investigating and post the solution when I find it. I'm sure it will be something really obvious in hindsight..Yan White
Can you change $post = new Timberpost() to $post = new Timber\Post()? What’s the return value for your hero_image in your ACF field settings? Can you make sure it returns an ID? What do you get when you only run {{ dump(post.meta('hero_image)) }}` in Twig?Gchtr
I edited the above code from front-page.php to page-home.php with the changes made to succesfully output both blog posts and testimonials. The var_dump from the php template also now runs, but I am still not getting the Twig file to output anything other than NULL for image_hero custom fieldYan White

2 Answers

0
votes

As for the ACF variables, you simply add this to your functions.php and you should be rocking it - someone correct me if i am wrong.

  class StarterSite extends Timber\Site {
        /** Add timber support. */
        public function __construct() {
            //maybe you already have this part in your functions file
            add_action( 'after_setup_theme', array( $this, 'theme_supports' ) );
            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();
        }

        public function add_to_context( $context ) {
            //left side: define how the variable is named to grab them in the TWIG files
            //right side: grabing the ACF variable-name
            $context['site'] = $this;
            $context['menu'] = new Timber\Menu("Main Menu");
            $context['something'] = new Timber\Menu("something_acf_name");
            $context['foo'] = new Timber\Menu("bar");
            $context['my_custom_button_name'] = new Timber\Menu("acf_custom_button_name");
            // Posts with the category name "featured" for the slideshow

            //
            return $context;
        }
    }

So let us assume we are in the index.twig file (or any other one, aslong as you have defined it in the functions.php file), you can just get your variable like this:

<div>
{{ foo }}
</div>

I hope this is what you were looking for. You could also just assign the variables within the index.php file for example, then they won't be globally (on every page) available. This might be good to keep your variable-mess under control. Really depends on what you are building.

0
votes

If you have {{ Image(post.meta('hero_image')).src }} in your Twig file, then Twig will look for the post variable. In your case, you define a post variable when you loop through your posts to display them as cards.

{% for post in posts %}
    {% include "blogpost-card.twig" %}
{% endfor %}

However, you probably didn’t define a custom field called hero_image for your posts, but on the page where you display them. So, when you define your context and add the currently displayed post under page in the context, then you later need to access it through page as well, and not through post.

$context = Timber::get_context();
$context['page'] = new Timber\Post();
<div
     class="image image-overlay"
     style="background-image:url({{ Image(page.meta('hero_image')).src }})"
></div>