Setting up a controller for ACF fields

sage9

#21

Thank you again @alwaysblank

I’d even looked in the debugger to check the namespace but I think I’m panicking too much to think properly at the moment. My understanding is very tentative but I’m getting there. Your help has been invaluable.

Just got to figure out the ACF bit now …


ACF variables in blade template
#22

I think I’ve solved this issue:


#23

Has anyone tried setting up a flexible field group? I am trying to have a controller get access to a get_sub_fields.

<?php

namespace App;

use Sober\Controller\Controller;

class FrontPage extends Controller
{
  public function content() {
    return(object) [
      'full_width_header_option' => get_sub_field('full_width_header_option'),
      'full_width_header' => get_sub_field('full_width_header')
    ];
  }
}

My view:

<h1>{{ $content->full_width_header }}</h1>

Returns - false

The field does have a value on the backend of WP. Makes me think that I am not accessing the correct part of the WP loop for Flexible Fields.


#24

I did reply to your other post on this but this is more helpful as you have provided some code to look over. The problem here is that you are not looping over any data; there is no context for get_sub_field; how would it know which field to call it against or which row to display?

I like to follow the principal that all logic takes place in the controller and not the view and so I also try to only pass the data I’m actually to need for the view and in its final format.

Controller

public function content() {

    $data = [];

    $flexible_content = get_field('flexible_content_field');

    foreach($flexible_content as $content) {

        $this_content = (object) [
            'full_width_header_option' => $content['full_width_header_option'],
            'full_width_header' => $content['full_width_header']
        ];

        array_push($data, $this_content);
    }

    return $data;

}

This is actually more like a repeater, as with a flexible content field you’ll likely want to different logic based on the particular layout but the concept would remain similar.

You would then loop through the resulting object in your view.


#25

Thanks for the quick reply. I have noticed that you contribute a lot to the forms and am very appreciative.

I am trying to have a controller for each flexible layout.

Example: I have views/flexible-fields/content.blade.php. I want a unique controller that manages all the custom fields for content.blade.php in app/controllers/content.php.

Here is the controller:
app/controllers/content.php

<?php

namespace FlexibleFields\Content\Controllers;

use Sober\Controller\Controller;

class Content extends Controller
{
  public function content() {

  $data = [];

  $flexible_content = get_field('flexible_fields');

  foreach($flexible_content as $content) {

      $this_content = (object) [
          'container' => $content['container'],
          'full_width_header_option' => $content['full_width_header_option'],
          'full_width_subheader_option' => $content['full_width_subheader_option'],
          'full_width_content_option' => $content['full_width_content_option'],
          'full_width_header_element' => $content['full_width_header_element'],
          'full_width_header' => $content['full_width_header'],
          'full_width_subheader' => $content['full_width_subheader'],
          'full_width_content' => $content['full_width_content']
      ];

      array_push($data, $this_content);
  }

  return $data[0];

  }
}

Here is the view
views/flexible-fields/content.blade.php

@if ($content->container)
  <div class="container">
@endif
@if ($content->full_width_header_option)
    <{{ $content->full_width_header_element }}> 
        {{ $content->full_width_header }}
    </{{ $content->full_width_header_element }}>
@endif
@if ($content->full_width_subheader_option)
    {{ $content->full_width_subheader }}
@endif
@if ($content->full_width_content_option)
    {{ $content->full_width_content }}
@endif
@if ($content->container)
    </div">
@endif

How come I cannot access the object from app/controllers/content.php on the view? When I place the logic from app/controllers/content.php to app/controllers/front-page.php the blade then can access it?

Thanks.


#26

You seem to be making the assumption that Controllers are linked to Blades—i.e. that content from Controller.php will be automatically piped to controller.blade.php. This is not the case. Controllers are linked to the WordPress Template Hierarchy—i.e. content from the Controller in Page.php will appear at locations where WordPress would load the Single Page template. There is no way (that I’m aware of) to target individual Blades from Controllers.

The way both Controller and Sage’s own routing do this is by hooking into the values that pass through the body_class filter, and loading the appropriate content. You can determine what controller should be used for your page by looking at the value of the class attribute on your page’s <body>. For instance, take a look at this page:
image
If I wanted to target this with a controller, I could use a Controller called Single or LocationTemplateDefault, because of these classes:
image
Controller names need to conform to PSR-4 naming standards, which is why it’s LocationTemplateDefault, not location-template-default.

If your goal is to encapsulate functionality you intend to use on several controllers, you might try using traits as described in the Controller documentation. They won’t allow you to target specific Blades, but they will allow you to re-use content across Controllers.


#27

Holy cow, I totally forgot about the WP hierarchy when I was thinking about the design. More importantly I was able to create a solution.

What I did was create a app/controllers/partials/(this is where all my ACF controllers will live) and used: trait.

From there I passed the trait to my app controller using use.

Example:
app/controllers/partials/content.php

<?php
namespace App\Controllers\Partials;

use Sober\Controller\Controller;

trait Content
{
 public function content() {

 $data = [];

 $flexible_content = get_field('flexible_fields');

 foreach($flexible_content as $content) {

     $this_content = (object) [
         'container' => $content['container'],
         'full_width_header_option' => $content['full_width_header_option'],
         'full_width_subheader_option' => $content['full_width_subheader_option'],
         'full_width_content_option' => $content['full_width_content_option'],
         'full_width_image_option' => $content['full_width_image_option'],
         'full_width_header_element' => $content['full_width_header_element'],
         'full_width_subheader_element' => $content['full_width_subheader_element'],
         'full_width_header' => $content['full_width_header'],
         'full_width_subheader' => $content['full_width_subheader'],
         'full_width_content' => $content['full_width_content'],
         'full_width_image' => $content['full_width_image'],
         'full_width_image_size' => $content['full_width_image_size'],

     ];

     array_push($data, $this_content);
 }

 return $data[0];

 }
}

app/controller/app.php

<?php

namespace App;

use Sober\Controller\Controller;

class App extends Controller
{

use Controllers\Partials\Content;

public function siteName()
{
    return get_bloginfo('name');
}

public static function title()
{
    if (is_home()) {
        if ($home = get_option('page_for_posts', true)) {
            return get_the_title($home);
        }
        return __('Latest Posts', 'sage');
    }
    if (is_archive()) {
        return get_the_archive_title();
    }
    if (is_search()) {
        return sprintf(__('Search Results for %s', 'sage'), get_search_query());
    }
    if (is_404()) {
        return __('Not Found', 'sage');
    }
    return get_the_title();
}

}

This way I can access all of my flexible field groups when they are needed despite the page hierarchy. I would love any other suggestions!

Thanks.


#28

Hello :slight_smile: I really like the idea of creating a controller for acf fields but I have one problem which I can not solve. I have group field for section, the group contains section title and content (content is WYSIWYG editor field). When I want to display value from content field which is WYSIWYG editor I see HTML tags as normal string text.

Example: <p>Lorem <strong>ipsum</strong> dolor sit amet</p>

My controller function looks like this:

public function content() {
   return (object) array( 
    'section' => get_field('section'),
   );
}

And I displayed fields in php like this:
<h3>{{$content->section['title']}}</h3>
<div>{{$content->section['text']}}</div>

My question is: How to display formatted fields from WYSIWYG editor using controllers?
The only way is to manually display the field using the_field() function, but is there any possibility to create controller for that?


#29

The issue is not happening at the controller level. Tell your Blade to display that string as unescaped: https://laravel.com/docs/5.6/blade#displaying-data


#30

When will this be updated in the Sage theme? At the moment a fresh Sage install doesn’t come with ACF, and needs to be manually updated.


#31

I came across to this post and finally I think that I sorted out how can I use this https://github.com/soberwp/controller#advanced-custom-fields-module , thanks to everybody that posted here.

I am starting a new project now and I don’t want to mess up everything from the beginning, so I do a recap of the steps that I followed (I hope that this can help somebody in the future)

If I made some big mistakes or something that I should avoid to do, it would be great if you can let me know and save my life :slight_smile:

  • update composer to 2.0.0 (Setting up a controller for ACF fields)
  • change namespace App; to namespace App\Controllers; in /controllers/app.php and /controllers/front-page.php
  • rename app.php to App.php and front-page.php to FrontPage.php

are these steps correct or I should avoid to do something for the best practice?

thanks


#32

This is exactly the setup we are using and it works great.

The one thing that isn’t working is ACF options page fields. For that we need to to manually define them using get_option().