Custom Fields Not Displaing on Category or Archive Page - timber

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.

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 %}

Nested forms in symfony empty after form submit

I have a question related to nested forms in symfony.
I have this form
{{ form_start(form, {'attr': {'class': 'needs-validation'}} ) }}
....
<div id="slot-fields-list" data-prototype="
{% filter escape %}
{% include 'slot/form/prototype.html.twig' with {'form': form.slot.vars.prototype} %}
{% endfilter %}"
data-widget-tags="{{ '<span></span>'|e }}">
</div>
{{ form_end(form) }}
.......................................
->add('slot', CollectionType::class, [
'entry_type' => SlotType::class,
'entry_options' => ['label' => false],
'label' => false,
'allow_add' => true,
'allow_delete' => true,
'error_bubbling' => false
])
Work fine, I have data in data-prototype after render template. When I submit the form and if the form has erreurs this nested form is added after submit button and data-prototype is empty. Any ideas ? Thx in advance
The documentation for CollectionType is actually quite good, but perhaps some particular details need reiteration.
First the documentation tells you, how to render the collection items (your slots probably):
<ul class="tags">
{# iterate over each existing tag and render its only field: name #}
{% for tag in form.tags %}
<li>{{ form_row(tag.name) }}</li>
{% endfor %}
</ul>
This is what's missing in your case. Just to avoid confusion, their <ul class="tags"> is your <div id="slot-fields-list" ...>. You have to go through the form.slot with
{% for slot in form.slot %}
{{ form_row(slot) }} <!--- or render your sub-form properly -->
{% endfor %}
now. Symfony is very reluctant to omit form elements. So when you place a {{ form_end(form) }} it will render the rest of the form elements, which have not been rendered before, to your form, before closing the <form>. (the same behaviour can be achieved by {{ form_rest(form) }}, if you ever need it)
That is the reason, why your subforms will appear after your submit button and completely out of place - because they weren't rendered anywhere before.
However, this does not yet explain the missing data-prototype, but perhaps there is a simple explanation as well ...
you possibly already know about the form themes, where you could add your own slot_widget, slot_row, slot_label and have symfony do all that weird include-stuff for you.

Add posts with timber twig into an include

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 %}

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

How to add an image to each choice of a choice list in a Symfony2 form?

I'm using Symfony 2 form to create an expanded choice list using radio buttons for selecting whether to post a blog as an anonymous user or not anonymous (showing username).
The form field type definition in the BlogType.php file looks like the following (I'm passing the choices with their values from the controller, but it should be irrelevant to my question):
$builder->add('is_anonymous', 'choice', array(
'choices' => $options['is_anonymous'],
'required' => true,
'multiple' => false,
'expanded' => true,
));
I tried to apply the "How to customize an Individual field" section from the Symfony2 Cookbook by doing the following in my template twig file:
<div class="post_as">
{{ form_label(form.is_anonymous, 'Post as:') }}
{{ form_errors(form.is_anonymous) }}
{% form_theme form _self %}
{% block _factor_is_anonymous_0_label %}
<img src="/images/anonymous-32.png"/>
{{ block ('form_label') }}
{% endblock %}
{% block _factor_is_anonymous_1_label %}
<img src="/images/user-32.png"/>
{{ block ('form_label') }}
{% endblock %}
{{ form_widget(form.is_anonymous) }}
</div>
However, the above results in both images showing before the choice list in addition to each showing next to its corresponding radio button, as seen in the resulting html:
<div class="post_as">
<label class="required">Post as:</label>
<img src="/images/anonymous-32.png"/>
<img src="/images/user-32.png"/>
<div id="factor_is_anonymous">
<input type="radio" id="factor_is_anonymous_0" name="factor[is_anonymous]" required="required" value="true" />
<img src="/images/anonymous-32.png"/>
<label for="factor_is_anonymous_0" class="required">Anonymous Collaborator</label>
<input type="radio" id="factor_is_anonymous_1" name="factor[is_anonymous]" required="required" value="false" />
<img src="/images/user-32.png"/>
<label for="factor_is_anonymous_1" class="required">User Name</label>
</div>
</div>
How can I get rid of the images from showing twice? I think this has to do with the images showing in the rendering of the overall choice "row" as well as in the rendering of each of the 2 choices. I tried various combinations for displaying the overall label and not, but I haven't been able to solve the issue... Could anyone help? thanks...
You need to move the definitions for your form blocks outside of any other block. Ie, move these lines outside any other block, best would be at the beginning or end of file
{% block _factor_is_anonymous_0_label %}
<img src="/images/anonymous-32.png"/>
{{ block ('form_label') }}
{% endblock %}
{% block _factor_is_anonymous_1_label %}
<img src="/images/user-32.png"/>
{{ block ('form_label') }}
{% endblock %}

Resources