Add posts with timber twig into an include - wordpress

On a single page, I need to add an include, on the bottom of the page, that add 3 projects.
I have a content type called projects I made with ACF.
single-project.twig
I have a "single-project.twig" page that display the content of a post (which is also a project). At the bottom of this page, I need to add a block like this:
{% block related %}
{% include 'inc-related.twig' %}
{% endblock %}
inc-related.twig
Into "inc-related.twig", I have this:
{% for post in related_posts %}
{% if post.thumbnail %}
<a href="{{post.link}}" class="l-basicgrid-work work">
<article>
<figure>
<img data-src="{{post.get_thumbnail.src('medium_large')|resize(800, 533)}}" alt="{{post.title}}" class="lazy">
</figure>
<figcaption>
<h2>{{ post.title }}</h2>
</figcaption>
</article>
</a>
{% endif %}
{% endfor %}
related.php
I also create a "related.php" page, that integrate the following rendering:
$context = Timber::get_context();
$context['related_posts'] = Timber::get_posts('post_type=project&posts_per_page=3');
Timber::render('inc-related.twig', $context);
Questions
I have 2 questions:
The project are not displaying into the single page. What I have done
wrong?
Can I select 3 project except the one who is displayed on the
single page?
Thank you

you have include twig template but not send data to him. Your related.php is not include automatically. You should write $context['related_posts'] = Timber::get_posts('post_type=project&posts_per_page=3'); in your single-project.twig. And do not use post name in inc-related.twig. May be conflict with current post object.
To single-project.php add $context['related_posts'] = Timber::get_posts('post_type=project&posts_per_page=3');

This is what I did.
single-project.php
I have created a single-project.php page. It contains the following script:
$context = Timber::get_context();
$args = array(
// Get post type project
'post_type' => 'project',
// Get 3 posts
'posts_per_page' => 3,
// Order random
'orderby' => 'rand',
);
$context['related_posts'] = Timber::get_posts( $args );
Timber::render('single-project.twig', $context);
single-project.twig
On my single-project.twig, I have the code that get the result of the php page. Actually, that code is included into an "inc-related.twig" page. And it works!
{% for post in related_posts %}
{% if post.thumbnail %}
<a href="{{post.link}}" class="l-basicgrid-work work">
<article>
<figure>
<img data-src="{{post.get_thumbnail.src('medium_large')|resize(800, 533)}}" alt="{{post.title}}" class="lazy">
</figure>
<figcaption>
<h2>{{ post.title }}</h2>
</figcaption>
</article>
</a>
{% endif %}
{% endfor %}
But on the same page (single-project.twig), I also have data that display content from Advanced Custom Field.
{% if post.project_images %}
{% for item in post.get_field('project_images') %}
<figure class="{{item.project_media_css}}">
<img data-src="{{TimberImage(item.project_media).src}}" alt="{{item.alt_media}}" class="lazy">
</figure>
{% endfor %}
{% endif %}
The problem now is that the ACF field don't return anything.
How should I modify single-project.php to get content from "related_project" and ACF field?

The ACF context is passed to the single page template via Timber $context, using the get_posts function.
single-project.php
$context['related_posts'] = Timber::get_posts('post_type=project&posts_per_page=3');
Twig sends along the active context by default, so this template is fine as-is.
{% block related %}
{% include 'inc-related.twig' %}
{% endblock %}
Finally, the posts in $context['related_posts'] can be looped over. However, within the for loop, refer to each post by anything other than post, such as rel_post. This avoids conflict with the regular post object.
{% for rel_post in related_posts %}
{% if rel_post.thumbnail %}
...
{% endif %}
{% endfor %}

Related

Issue with Post Object Timber/Twig WordPress

I have an ACF field, It's a Repeater, and inside the Repeater is a Post Object.
Controller
/* Template Name: Strategic Partners */
use Timber\Timber;
use Timber\PostQuery;
use Flynt\Utils\Options;
use const Flynt\Archives\POST_TYPES;
$context = Timber::get_context();
$context['slider'] = get_field('slider');
$context['featured'] = get_field('featured');
if (isset($_GET['contentOnly'])) {
$context['contentOnly'] = true;
}
Timber::render('templates/StrategicPartners/index.twig', $context);
Here's the snippet from the View
{% for partner in Post(featured) %}
{{ partner.link }}
{% endfor %}
I'm var_dumping the context, and it's getting the Timber Post... but {{ partner.title }} does not grab the Post Title, it's blank.
{{ partner.link }} comes out with the direct link.
Output
http://***/strategic-partners/
http://***/strategic-partners/
What am I doing wrong here? I'm using {{ Post() }}} within a seperate repeater, within for foreach itself and that works on another page, but it does not work here either, so I tried Post() included in the foreach and it still is not working.
No one answered this for me. I answered it myself.
There isn't much documentation on this within the formal Timber documentation so I hope this helps somebody.
Do not call Post with your foreach
Do this for a Post Object within a Repeater (ACF)
{% for item in seq %}
{{ Post(item.post_object_name).field }}
{% endfor %}
seq is your ACF Field
post_object_name is the Post Object within the field.
field is the field within the Post Object type.
Hope this helps someone.
For more Context:
Controller
<?php
/* Template Name: Strategic Partners */
use Timber\Timber;
use Timber\PostQuery;
use Flynt\Utils\Options;
use const Flynt\Archives\POST_TYPES;
$context = Timber::get_context();
$context['slider'] = get_field('slider');
$context['featured_sps'] = get_field('featured_strategic_partners');
$context['rebate'] = get_field('rebate_information');
if (isset($_GET['contentOnly'])) {
$context['contentOnly'] = true;
}
Timber::render('templates/StrategicPartners/index.twig', $context);
Twig View
{% for partner in featured_sps %}
{{ Post(partner.featured).title }}
{% endfor %}
Images are more complex
{% for partner in featured_sps %}
<div class="slide">
<a href="{{ Post(partner.featured).link }}">
<img src="{{ Image(Post(partner.featured).logo).src }}" alt="{{ Post(partner.featured.title) }} Logo">
</a>
</div>
{% endfor %}

How to get image metadata from ACF gallery images?

I wanted to display image metadata of images from a gallery added with Advanced Custom Fields, is that possible?
So far, I've tried this (and a few other things too which didn't work either):
front-page.php
<?php
/**
The front page template file
*/
$context = Timber::get_context();
$post = Timber::query_post();
$context['post'] = $post;
Timber::render( 'home.twig', $context );
home.twig
{% extends "base.twig" %}
{% block content %}
{% for image in post.get_field('gallery') %}
{{ post.wp_get_attachment_metadata(TimberImage(image).id) [image_metadata][aperture] }}
{% endfor %}
{% endblock content %}
Thanks for your answer, I hope you can help me! :)
the meta data that you want should be available when converting to a TimberImage object so....
{% for image in TimberImage(post.get_field('gallery')) %}
{{ image|print_r }}
{% endfor %}
The print_r filter will output all the values on the object. That said, if you specifically want the array that WP normally the "fix" for your code would likely be...
{% for image in post.get_field('gallery') %}
{{ function('wp_get_attachment_metadata', TimberImage(image).id). image_meta.aperture }}
{% endfor %}
I say "likely" because the above is untested — give it a shot and let me know!

Timber use different template for custom post type

I am completely new to PHP, Wordpress and Timber. I have a custom post type called Projects, it uses the posts archive template and I am going crazy to create a specific Projects archive template so I can have a different layout for it.
This is what my index.twig looks like
{% extends "layouts/base.twig" %}
{% block content %}
<div class="uk-child-width-1-3#m" uk-grid uk-scrollspy="cls: uk-animation-fade; target: > div > .uk-card; delay: 500; repeat: false">
{% for post in posts %}
{% include "tease-post.twig" %}
{% endfor %}
</div>
{% endblock %}
and this is the tease-post.twig
{% block content %}
<div>
<div class="uk-card uk-card-default">
<div class="uk-card-media-top">
<img src="{{post.thumbnail.src('full')}}" alt="">
</div>
<div class="uk-card-body">
<h3 class="uk-card-title">{{post.title}}</h3>
<p>{{post.get_preview(25,false,false,true)}}</p>
</div>
<div class="uk-card-footer">
Read more
</div>
</div>
</div>
{% endblock %}
Any idea how it works? Can't find any related documentation..
There are a few diff't methods depending on what you're looking to achieve. It would seem the simplest is...
{% extends "layouts/base.twig" %}
{% block content %}
<div class="uk-child-width-1-3#m" uk-grid uk-scrollspy="cls: uk-animation-fade; target: > div > .uk-card; delay: 500; repeat: false">
{% for post in posts %}
{% include "tease-'~ post.type ~'.twig" %}
{% endfor %}
</div>
{% endblock %}
You could then create a file called tease-project.twig (assuming that `project is the name of your custom post type's slug) that might look something like this...
{# tease-project.twig #}
<h2>My cool project is... {{ post.title }}</h2>
If you're looking to do something special with a CPT's specific archive page...
Check your archive.php file, if you're using the starter theme it should load a file called archive-projects.twig (assuming that projects is the name of the custom post type).
The logic is fully customizable so you can load any .twig files you want depending on the circumstance

Custom Fields Not Displaing on Category or Archive Page

I have set up an Advanced Custom Field item to display a featured image, description etc at the top of each Category & Archive of a custom post type.
The Custom Post Type & Taxonomy are
$event_args = array(
'has_archive' => 'news-events',
'exclude_from_search' => false,
'publicly_queryable' => true,
'rewrite' => $event_rewrite,
'capability_type' => 'post',
);
register_post_type( 'events', $event_args );
register_taxonomy( 'event_category', array( 'events' ), $events_args );
In archive-events.php I have
$context['pagination'] = Timber::get_pagination();
$context['title'] = 'Archive Tours';
$context['posts'] = Timber::get_posts();
$content['events'] = Timber::get_terms('event_category');
Timber::render($templates, $context);
In the Twig file
<div class="col-sm-12 col-md-12">
<article class="post post-container">
<div class="entry-header">
<div class="post-thumb thumb">
{% if events.featured_event_image %}
<img src="{{TimberImage(events.featured_event_image).src}}" alt="{{ events.featured_event_title }}"
class="img-responsive" />
{% else %}
{# TODO: replace this with something we serve. #}
<img src="http://placehold.it/500x340" alt="Default Thumbnail" class="img-responsive">
{% endif %}
</div>
</div>
<div class="sa_blog_content">
<div class="sa_blog_center">
<h4 class="sa_blog_title"><a target="_self" title="{{ events.featured_event_title }}" href="#">{{
events.featured_event_title }}</a></h4>
<div class="meta">
<span><time datetime="{{post.post_date|date('F j, Y')}}">{{post.post_date|date('F j, Y')}}</time></span>
<span>359 Views</span>
</div>
</div>
{{ events.featured_event_summary }}
<div class="tagcloud">
{% for term in post.terms('featured_event_tags') %}
<span>{{post.term.name}}</span>
{% endfor %}
</div>
</div>
</article>
</div>
Yet none of my Custome Fields are available in the Archive or Category pages. Can anyone suggest a solution to this problem. Thanks in advance...
When you use Timber::get_terms(), you’ll get an array in return.
Instead of checking for the existence of a custom field with {% if events.featured_event_image %} you probably have to loop over the elements in events:
{% for event in events %}
{% if event.featured_event_image %}
{# your code #}
{% endif %}
{% endfor %}
Or you can directly access the first element of the array with
{% if event[0].featured_event_image %}
In the same way, {{ events.featured_event_summary }} will not show up, because the field featured_event_summary can’t be found on the array, but probably exists in each of the elements of the array.
When you use {% for term in post.terms('featured_event_tags') %}, then you ask to get all terms of a featured_event_tags taxonomy assigned to that post. From your code excerpts I can see that you only register event_category as a taxonomy. In you screenshots I can see that featured_event_tags is the name of a custom field set on the taxonomy event_category.
To get the terms for a post, you then should do:
{% for term in post.terms('event_category') %}
Inside this for loop, you seem to trying to get the link and name for that term, but you access it from post with {{ post.term.link }}. Probably, it should be
{% for term in post.terms('event_category') %}
{{ term.link }}
{{ post.term }} won’t work, because term() is not a method of Timber’s Post class. There’s only the terms() method, which will get you all terms assigned to a post.
These could all be reasons why nothing will show up in your code. Remember that you can also do {{ dump( variable ) }} to check the contents of a variable in Twig.
If you still get stuck, then update your question with more code and I can update this answer.

Symfony2 - Excluding current post on show page

I have a show page and on the bottom the page I have a 'Related' articles section that show 4 related articles that the user can click on.
The problem is, I want to exclude the current article that is being shown from the 'Related' articles section on the bottom of the page so it doesn't appear twice.
Is there a conditional I can use in Twig to hide the current article I am showing in the 'Related' section so it doesn't appear twice (once for the show and again on the bottom of the page as a Related article) on the bottom of the page?
Example of show page
Show page - Article 1
blah...
...blah
blah...
Related: (4 articles on the bottom of page)
Article 1, Article 2, Article 3, Article 4 (I want to hide Article 1 in this section as it's being shown already)
Related partial I am using:
<h2>Related</h2>
<aside id="" class="">
<div class='featuredfour cf'>
{% for article in articles %}
{% if not article.id == showedArticleId %}
<div class="featuredfourpost">
<a href="{{ path('acme_demo_article_show', { slug: article.slug }) }}">
<img width="150" height="150" src="{{ asset(['images/', article.image]|join) }}" class="" alt="" />
<h3 class="title">{{ article.title }}</h3>
</a>
</div>
{% endif %}
{% endfor %}
</div>
</aside>
Show page
{% extends "AcmeDemoBundle::layout.html.twig" %}
{% set showedArticleId = article.id %}
{% block body %}
[...]
<div class="entry-content">
{% autoescape false %}
<p>{{ include(template_from_string(article.body|raw|nl2br)) }}</p>
{% endautoescape %}
</div>
[...]
{# Related Articles section #}
{{ include('AcmeDemoBundle:Partial:_featured.html.twig', { articles: articles }) }}
{% endblock %}
Doctrine for relatedPosts
public function getRelatedArticles($limit)
{
return $this
->createQueryBuilder('article')
->setMaxResults($limit)
->orderBy('article.createdAt', 'DESC')
->getQuery()
->execute();
}
You can try this for your Doctrine query:
public function getRelatedArticles($exceptArticle, $limit)
{
return $this
->createQueryBuilder('article')
->where('article != :exceptArticle')
->setMaxResults($limit)
->orderBy('article.createdAt', 'DESC')
->setParameter('exceptArticle', $exceptArticle);
->getQuery()
->execute();
}
You just give the article to except from the query.
Inside your twig, on the part where you're showing the article, add (somewhere, without code is difficult to say exactly where)
[...]
{% set showedArticleId = article.id %}
[...]
Then use it for check and skip already showned one
[...]
{% for article in articles %}
{% if article.id != showedArticleId %}
[...]
{% endif %}
{% endfor %}
[...]
Of course I'm making some guessing on your article entity fileds: I'm pretty sure that id will be there

Resources