ACF variables in blade template

Is there a way to include partials in the controller while using flexible content field, not just single field data?

What I’m trying to do is to have the usual acf check for the flexible content field in the controller, get the corresponding partial and then display the whole thing in the view file, while each partial can show its own sub fields.

Basically I’m trying to make a simple page layout builder in the back-end and I use the flexible content field for that. There would be these pre-made page sections like a page-banner, or a basic text content with title or a gallery, etc. And I want to make all these as individual partials. Just can’t really figure out how to make the controller spit it out on the page.

Not sure if I tackled the problem from the right direction, I just started learning the new sage and blade templating in general a few hours ago. I tried to avoid doing it with my old way which is having the acf if/while checks then including the specific partial in the page template file.

Any examples and help are greatly appreciated.

I am also doing the same thing. I have gotten to the point where I can display different content per ACF shelf but it does not utilize the controller.

i did have a solution where i could use multiple ACF controllers on any page; however, when i wanted to reuse a flexible content shelf on the same page, it would return the value of the first content row.

Example:
Home Page : Flexible Content : Row 1 - Content, Row 2 - Image, Row 3 - Content. The values of the variables from the content controller - Row 1 and Row 3 - are the same on the front end, but on the back end they are different.

I ended up putting together something based on nathobson’s tips in the controller, but let the partial handling in the view file. That wasn’t my original goal but I thought that much logic is okay(or necessary) since it is the same how it is in the default pre-made files.

controller:

public function getLayouts()
  	{

      $layouts = get_field('layout');
      $data = [];
      if($layouts):
        foreach($layouts as $layout):

          // common layout attribute settings
          $this_layout = (object)[
            'background_color' => $layout['settings']['background_color'],
            'background_image' => $layout['settings']['background_image'],
            'custom_class' => $layout['settings']['custom_class']
          ];
          // specific attributes based on layout type
          if($layout['acf_fc_layout'] == 'large_carousel'):
            $this_layout->type = 'large_carousel';
            $this_layout->slides = $layout['carousel_slides'];
          elseif($layout['acf_fc_layout'] == 'text_section'):
            $this_layout->type = 'text_section';
            $this_layout->full_width = $layout['settings']['full_width'];
          endif;

          array_push($data, $this_layout);

        endforeach;
        return $data;
      endif;
  	}

View:

@foreach($get_layouts as $layout)
      @if($layout -> type == 'large_carousel')
        @include('partials.page-section-carousel')
      @elseif ($layout -> type == 'text_section')
        @include('partials.page-section-text')
      @endif
    @endforeach

Inside a partial a you can get the values you set up for the object with $layout -> somestuffyouneed.

It isn’t much more efficient than the regular acf while loop but at least the flexible content data is available in the controller now. Not sure if it helps in your case but maybe you can get some ideas and improve my mess.

edit: Oh and I used this for debug purposes in the loop to check how ACF made the structure:

  echo '<pre>';
  print_r($layout);
  echo '</pre>';
	      die;

How are you reusing the same template on the same page?

it’s there in the code examples really. In the controller I build an array of layout objects from the acf input and in the view it goes through the array and displays the corresponding layout template. It doesn’t matter how many times you put in the same template in the back end because they become different objects in the controller.

There are some stuff there that is specific to my case but the main part is the $this_layout which is current object that will be put into the $data array.

maybe this way it’s clearer:

controller:

public function getLayouts()
{
	//acf flexible content field
	$layouts = get_field('layout');
	//this will hold all the layouts
	$data = [];
	//go through each layouts that got put in there
	if($layouts):
		foreach($layouts as $layout):

			//$this_layout is the current one
			$this_layout = (object)[
				//the layout object's title value will be the 'title' named acf sub field of the flexible content layout
				$this_layout->title = $layout['title'];
			];

			// if you want to add specific fields based on flexible content layout type, you can check it this way
			if($layout['acf_fc_layout'] == 'text_section'):
				//the layout object's type value is going to be 'text section'
				$this_layout->type = 'text_section';
			endif;

			//put the current object into the $data array
			array_push($data, $this_layout);

		endforeach;
		//return the $data array with all the flexible content objects in it
		return $data;
	endif;
}

view file

@extends('layouts.custom')

@section('content')
  @while(have_posts()) @php the_post() @endphp

		//get_layouts function from the controller and run through each
    @foreach($get_layouts as $layout)
			//if the object's type value is 'text_section' then do this
      @if ($layout -> type == 'text_section')

        <section class="page-section standard-text-section">
					<div class="container">
						<div class="text-wrapper">
              //display one of the sub field values we set up in the controller this way
							<h1>{{$layout -> title}}</h1>
              <p>{{$layout -> type}}</p>
						</div>
					</div>
				</section>

      @endif
    @endforeach

  @endwhile
@endsection

Hi Jacoby, love your work here. Thanks for all your help.

Just wondering how this ACF module works using get_option('page_for_posts')

As an example I’m trying to get a custom field on a blog page, but when I @debug using protected $acf = ['field1']; returns no data.

1 Like

The new version releasing soon will have support for acf option page. You would just just use $acf = true; in App.php

2 Likes

Appreciate it mate… Don’t mean to pester but any idea when the new version may released?

In the meantime should I just forgo using the ACF module and use the original method?

1 Like

I’ll tag it this afternoon.

First of all, thanks for this post as we’re able to use this to have clean templates!

If one were trying to return the default WP thumbnail cropped image size from an ACF image field in a repeater field, what’s the best way to do that? Also, how to correctly grab the alt tag for the image?

Controller:

public function models()
{
    return array_map(function($model) {
        return [
            'title' => $model['model_type_name'] ?? null,
            'content' => $model['short_description'] ?? null,
            'image' => $model['image'],
            'aluminum' => $model['aluminum_colors'] ?? null,
            'poly' => $model['poly_roof_colors'] ?? null,
            'heat' => $model['heat_poly_roof_colors'] ?? null,
            'wind' => $model['wind_pressure'] ?? null,
            'snow' => $model['snow_load'] ?? null,
        ];
    }, get_field('model_series') ?? []);
}

Loop:

@foreach($models as $model)

<div @include('partials.content-single-our_models_list', $model) </div>

@endforeach

</div>

File:

<h3>{ $title }}</h3>

<img src="{{ $image }}" alt="{{ $image ['alt'] }}">

Lastly, how would you go about returning the values of a set of checkboxes if they’re checked?

@if($aluminum['slc'])
    @php echo "sun silver"; @endphp
@else
    @php echo "n/a"; @endphp
@endif

shaimoom I was running into the same exact issue. Instead of {{ the_permalink() }} and {{ the_title() }}, try {!! the_permalink($post) !!} and {!! get_the_title($post) !!} so long as you’re using the blade syntax.

Otherwise, follow this pattern for vanilla php: <?php echo get_the_title($post); ?>.

These both worked for me.

I’m new to blade and come from Sage 8, so there’s probably a cleaner way to handle this setting up a controller. If you know how, please let me know.

I have one question. Let’s say we want to create a variable based on acf fields to show in the blade files. Just to keep the logic out of the blade template.
I would still have to use the get_field within the methods, or is there a way to access the acf variables created with $acf = true within the controller?

Out of simplicity, In your example imagine that instead of overriding the text_field variable, you want to take the acf variable and append some text to it. How would you do it?

Thanks!

I have a custom post type: Portfolios.
This post type has a handful of ACF fields in a group:

<?php

namespace App\Controllers;

use Sober\Controller\Controller;

class SinglePortfolio extends Controller
{
    public function portfolio()
    {
        $field = get_field('portfolio');
        return (object) [
            'slider'     => $field['slider'] ?? null,
            'name'        => $field['name'] ?? null,
            'location'     => $field['location'] ?? null,
            'description'     => $field['description'] ?? null,
            'awards'     => $field['awards'] ?? null,
            'photos'     => $field['photos'] ?? null,
        ];
    }
}

The home page has an ACF relationship field to allow me to choose 3 portfolio items to displayed in a loop on the home page:

<?php

namespace App\Controllers;

use Sober\Controller\Controller;

class FrontPage extends Controller
{

    public function featured() {
    global $post;
    $data = [];
    $featured = get_field('featured_portfolios');
        foreach ($featured as $f) {
            $this_post = (object) array(
                'thumbnail' => get_the_post_thumbnail($f, 'hero', array('class' => 'lozad')),
                'permalink' => get_the_permalink($f),
                'title' => get_the_title($f),
            );
            array_push($data, $this_post);
        }
        return $data;
    }
}

The regular post data from WP (thumb, permalink, title) all pull that data to the home page loop just fine:

@foreach ($featured as $f)
    <div class="relative w-full md:w-1/2">
        <div class="p-4">
            <a href="{{ $f->permalink }}" title="{{ $f->title }}">       
                <div class="absolute top-0 right-0 bottom-0 left-1/2 bg-secondary opacity-20 z-50 m-4 p-4">
                    <div class="absolute bottom-0 right-0 text-right text-white pr-8 pb-8">
                        <p class="m-0">{{ $f->title }}</p>
                    </div>
                </div>     
                {!! $f->thumbnail !!}
            </a>
        </div>
    </div>
@endforeach   

I’m having trouble attempting to pass the ACF data to the loop. I’m trying to pass the ACF location field. I’m not having any luck with anything I try and can’t find any examples that others have used to make this work.

I apologize in advance for the bump here but I’m still curious if anyone has any suggestions on my last post and getting fields from a post thru a relationship to appear in the loop on the home page.

Much appreciated!

What’s preventing you from doing this?

<?php

namespace App\Controllers;

use Sober\Controller\Controller;

class FrontPage extends Controller
{

    public function featured() {
    global $post;
    $data = [];
    $featured = get_field('featured_portfolios');
        foreach ($featured as $f) {
            $post_data = [
                'thumbnail' => get_the_post_thumbnail($f, 'hero', array('class' => 'lozad')),
                'permalink' => get_the_permalink($f),
                'title' => get_the_title($f),
            ];

            $field = get_field('portfolio', $f);
            $portfolio_data = [
                'slider'     => $field['slider'] ?? null,
                'name'        => $field['name'] ?? null,
                'location'     => $field['location'] ?? null,
                'description'     => $field['description'] ?? null,
                'awards'     => $field['awards'] ?? null,
                'photos'     => $field['photos'] ?? null,
            ];
            array_push($data, (object) array_merge($post_data, $portfolio_data));
        }
        return $data;
    }
}

I’m sure I understand your use case. Maybe if you showed some of the things you’ve tried it would help us understand what the problem is?

1 Like

Honestly, lack of knowledge… where can I study up on this? Thanks for the help, I understand more now. I’m sure others will come around and find this information useful as well.

The only interesting things I did there were pass the post object id to get_field() and use array_merge() to combine the two arrays. I don’t know where exactly I’d go to study up on them except the ACF and PHP docs? I would recommend at least reading through all of PHP’s many, many array functions: https://www.php.net/manual/en/ref.array.php. Just about everything in PHP is basically an array (which is not great, but…that’s life) so knowing how to manipulate them with language-level functions is very helpful. My personal favs are array_map, array_reduce, array_filter, array_merge, and array_column.

get_field() is generally my only point of contact w/ ACF’s data structure: I know it has a bunch of other functions but to me they just confuse things. get_field() gives you a value or an array, and they you can process it however you want. I do see a lot of people apparently unaware that you can pass an ID as the second parameter to tell it to get the field from a specific post object. I usually try and make it a habit to always call get_field() with that second parameter, so I can easily know where it’s getting the value from when I look at my code, without having to do a bunch of thinking about the current global context.

1 Like

That’s amazing. Thanks for sharing your favs and that info! It is super helpful.

Hey man, I know this is a super old thread, but it’s worth a shot. I"m using this code, it works great. But i’d like to output the number each item in the loop is associated with. Normally I’d use $count = 0 and then $count++; and then echo $count in the loop but I can’t figure out where to place this for it to work.

Cheers!