When fetching an ACF field that returns WP_Post objects, convert them to Timber\Post
Problem
I'm on a project right now that fetches post reference ACF fields all over the place. These are returned as WP_Post objects (or lists thereof). This creates problems when the same template is sent the results of a Timber query in one place and ACF references in another; for instance, if a template gets a WP_Post, it has to use post.permalink, but if it gets a Timber\Post, it has to use post.link.
Solution
Timber\Post::meta() should convert any WP_Post objects it fetches into Timber\Post objects.
Alternatives
Timber\Post could implement the same interface as WP_Post alongside its own stuff, so developers don't have to care as much which kind of object they get. But I'm pretty sure some of those things have been deprecated and removed in the past. (Could be wrong.)
I think transform_value might be what you’re looking for here: https://timber.github.io/docs/v2/integrations/advanced-custom-fields/#transform-values-to-timber/php-objects.
D'oh, you're right, that's perfect. Sorry to bother!
This doesn't seem to handle it well when an ACF field that would be converted is empty:
TypeError: Timber\Factory\TermFactory::build(): Argument #1 ($term) must be of type WP_Term, WP_Error given, called in /var/www/html/vendor/timber/timber/src/Factory/TermFactory.php on line 59
The WP_Error in question is simply Empty Term. Is there a good way around this?
In TermFactory.php, the from_id method has this:
$wp_term = \get_term($id);
if (!$wp_term) {
return null;
}
return $this->build($wp_term);
Looks like maybe that !$wp_term should be !$wp_term || $wp_term instanceof \WP_Error perhaps?
EDIT Or perhaps we should check empty($id) before calling get_term()
Hi @75th ,
Are you willing to create a PR for handling that specific behavior?
In TermFactory.php, the
from_idmethod has this:$wp_term = \get_term($id); if (!$wp_term) { return null; } return $this->build($wp_term);Looks like maybe that
!$wp_termshould be!$wp_term || $wp_term instanceof \WP_Errorperhaps?EDIT Or perhaps we should check
empty($id)before callingget_term()
What I can see is that get_term only throws an error if the taxonomy does not exist. Was that your case as well @75th ?
I have the following code in my project per the documentation:
/**
* Set Timber to automatically transform ACF values from Wordpress objects to Timber Objects
*
* @return TRUE
*
*/
add_filter( 'timber/meta/transform_value', '__return_true' );
Relationship fields are still returning instances of WP_Post, though.
Gi @jameelmoses , can you show us how you are fetching those field values in your templates? This might be another issue
Sure. For example, in a block:
$context = Timber::context();
$context['fields'] = get_fields();
Ah yes, I thought so. The transformation is not actively set on get_fields since no Post object is being implemented on the blocks as well. There were some discussions a while ago to create a class for blocks as well so you could use this directly, but this is not implemented. You might be able to run specific transforms as seen here on your field values.