Roots Discourse

ACF, Custom Taxonomy and Controllers

I have a custom post type: “property” and a custom taxonomy within: “property-type” and I’ve added some ACF fields to be displayed on the categories in the taxonomy such as inputs and images and so on.

I have a loop on the home page:

@php 
            $terms = get_terms(
                array(
                    'taxonomy'   => 'property-type',
                    'hide_empty' => false,
                )
            );
            @endphp
            @if ( ! empty( $terms ) && is_array( $terms ) )
                @foreach ( $terms as $term )

                <div>
                    <div class="uk-card uk-card-default">
                        <div class="uk-card-media-top">
                            <img src="@asset('images/bobbarker.jpg')" alt="">
                        </div>
                        <div class="uk-card-body uk-padding-small">
                            <h3 class="uk-card-title">{{ $property_section->title }}</h3>
                            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.</p>
                            <a href="{!! get_term_link( $term ) !!}" class="btn btn-primary">{!! $term->name !!}</a>
                        </div>
                    </div>
                </div>
                @endforeach
            @endif

These fields are in an ACF group so I’ve put this in my controller:

public function propertySection() {
    $field = the_field('property_section');
    return (object) [
        'title'     => $field['title'] ?? null,
        'content'     => $field['content'] ?? null,
        'cta_text'     => $field['cta_text'] ?? null,
        'cta_page'     => $field['cta_page'] ?? null,
        'image'     => $field['image'] ?? null,
    ];
}

I’m having a difficult time trying to pull this data from the taxonomy. Any help would be appreciated.

@joshb

Hi, maybe need to try adding term->term_id when outputting fields in a foreach loop

I am able to retrieve the default data but I’m trying to retrieve the ACF data.

It’s unclear to me what this is meant to do. AFAIK the_field expects an ID or ID-ish string as the second argument, but you’re passing it something that looks like a slug. IIRC if you’re trying to get a particular ACF field from a particular taxonomy term, you need to pass the term ID concatenated with term, i.e. term_123. See documentation: https://www.advancedcustomfields.com/resources/the_field/

Whoops, yeah that was some trial/error attempts. I didn’t intend to copy that here. I’ll keep working at different methods or may just skip out using a controller on this one.

I’m not trying to target any specific terms within the taxonomy… just targeting the ACF fields for the taxonomy itself.

I’m not clear what you mean by this. AFAIK you can’t store ACF data on a taxonomy because it doesn’t exist as an object ACF can access, you can only store data on specific terms.

Yes, the fields are being applied to each term in the taxonomy. I’m trying to pull the data in a loop on the home page from each term in the taxonomy. Sorry for not being more clear.

<a href="{!! get_term_link( $term ) !!}" class="btn btn-primary">{!! $term->name !!}</a>

FWIW, I’m able to access the default term fields, like the one above and display this information on the front end, just not the ACF field data.

Is property_section the ACF group on a term that you’re trying to get? If so they you have to pass the term ID of whatever term you’re trying to get data from. ACF functions (i.e. the_field fall back to the current page if a specific ID isn’t passed), and here the “current page” is going to be your home page.

I’m not clear on why you’re running so much logic in your blade either. It looks like maybe you’re thinking that the context of the blade loop will cause $property_section to yield something different on each iteration? That’s not the case. Once variables are passed to a blade, they are whatever value they were when they came out of the Controller. Because you’re calling the_field in your controller, it has only the Controller’s context to go on, which means it’s trying to find property_section on your front page.

Your controller should probably look more like this:

public function termLoop()
{
  $terms = get_terms(['taxonomy'   => 'property-type', 'hide_empty' => false,]);
  if (is_array($terms) && count($terms) > 0) {
    return array_map(function($term) {
      $section = get_field('property_section', "term_{$term->id}");
      return [
        'name' => $term->name,
        'url' => get_term_link($term),
        'title' => $section['title'] ?? false,
        'cta_text' => $section['cta_text'] ?? false,
        // Whatever other fields you want to get
      ];
    }, $terms);
  }

  return false;
}

Then in your blade you can do something like

@if($term_loop)
  @foreach($term_loop as $term)
     <div>
       {{ $term['name'] }}
       // Whatever else you want to do here
     </div>
  @endforeach
@endif

Thanks @alwaysblank for the explanation. I’ll give it a try but at first try it’s giving me a syntax error: syntax error, unexpected ‘=>’ (T_DOUBLE_ARROW)

I forgot to wrap the returned values in an array. Keep in mind the above is an untested guess on my part, you will need to debug it.

Ok, so the following is working to return the default taxonomy term fields in the loop:

public function termLoop() {
    $terms = get_terms(['taxonomy' => 'property-type', 'hide_empty' => false,]);
    if (is_array($terms) && count($terms) > 0) {
        return array_map(function($term) {
            $section = get_field('property_section');
            return [
                'name' => $term->name,
                'url' => get_term_link($term),
                'title' => $section['title'] ?? false,
                'cta_text' => $section['cta_text'] ?? false,
                    // Whatever other fields you want to get
            ];
        }, $terms);
    }
    return $terms;
}

            @if($term_loop)
                @foreach($term_loop as $term)
                   <div>
                     <a href="{{ $term['url'] }}">{!! $term['name'] !!}</a>
                     <p>{{ $term['title'] }}</p>
                   </div>
                @endforeach
            @endif

Trying to echo out {{ $term['title'] }} returns nothing.

Sorry, made another edit. I forgot to pass the term ID.

No need to apologize, I appreciate you trying to help out! Unfortunately that’s not resolving the issue either… hmm. Damn.

In case anyone stumbles here and looking for the solution, the following works:

$section = get_field('property_section', $term);

public function termLoop()
{
  $terms = get_terms(['taxonomy'   => 'property-type', 'hide_empty' => false,]);
  if (is_array($terms) && count($terms) > 0) {
    return array_map(function($term) {
      $section = get_field('property_section', $term);
      return [
        'name' => $term->name,
        'url' => get_term_link($term),
        'title' => $section['title'] ?? false,
        'cta_text' => $section['cta_text'] ?? false,
        // Whatever other fields you want to get
      ];
    }, $terms);
  }

  return false;
}

Thanks to @alwaysblank for help to lead me in the right direction.

Now onto more problems. I’m unable to pull in the image from the termLoop function but it works fine with the aboutSection function. Both are setup as image arrays in ACF but for the termLoop function I receive the following error:

Notice: Trying to get property 'image' of non-object

public function aboutSection() {
    $field = get_field('about_section');
    return (object) [
        'title'     => $field['title'] ?? null,
        'content'     => $field['content'] ?? null,
        'cta_text'     => $field['cta_text'] ?? null,
        'cta_page'     => $field['cta_page'] ?? null,
        'image'     => $field['image'] ?? null,
    ];
}
public function termLoop() {
    $terms = get_terms(['taxonomy' => 'property-type', 'hide_empty' => false,]);
    if (is_array($terms) && count($terms) > 0) {
        return array_map(function($term) {
            $section = get_field('property_section', $term);
            return [
                'name' => $term->name,
                'description' => $term->description,
                'url' => get_term_link($term), 
                'image' => $section['image'] ?? false,
                'title' => $section['title'] ?? false,
                'excerpt' => $section['excerpt'] ?? false, 
                'cta_page' => $section['cta_page'] ?? false,
                'cta_text' => $section['cta_text'] ?? false,
            ];
        }, $terms);
    }
    return $terms;
}

The aboutSection:
<img src="{{ $about_section->image['url'] }}" alt="{{ $about_section->image['alt'] }}">
Returns the image no problem.

The termLoop section:
<img src="{{ $term->image['url'] }}" alt="{{ $term->image['alt'] }}">

Your error is telling you exactly what the problem is:

This says that you asked for the property image on something you thought was an object, but when the script was run, that thing wasn’t actually an object, hence no properties can be accessed on it.

That means that your error is being thrown by code that looks like this: ???->image. There are two places you do this:

<img src="{{ $about_section->image['url'] }}" alt="{{ $about_section->image['alt'] }}">
<img src="{{ $term->image['url'] }}" alt="{{ $term->image['alt'] }}">

We can see in your controller where $term and $about_section come from, so lets look at the values they return:

// aboutSection()
return (object) [ ...

// termLoop()
return [ ...

termLoop() is returning an array of arrays, not the array of objects you would need in order to be able to do $term->image.

This is pretty basic debugging and troubleshooting, and the issue here has nothing to do with Sage or Controller. I answered this question because I’m procrastinating about something else, but you could have found this on your own. We’re all happy to help folks understand and work through issues with the Roots stack, but this thread is starting to feel like you’re using me to troubleshoot and write your code for you. If type issues like this are cause you problems, you might want to try using a full IDE: I use PHPStorm, and this is exactly the type of problem that its static analysis tools will be able to identify and correct for you.

Sorry for being off topic and thank you for your help!!