Tag: ACF

  • The core team (i.e. Matt) doesn’t want WordPress to be a general purpose CMS

    For various reasons, I’ve kind of taken a step back from heavy client project development in WordPress over the past few months.

    Today I’m back at it, trying to really actively work on something new for the first time since before the big kerfuffle started, and the time away has given me new perspective on what WordPress really is, and what the core team (let’s be honest, Matt) wants it to be.

    I’ve frequently argued that WordPress owes its broad success to the malleability its plugin architecture provides. The platform is not, inherently, a general-purpose Content Management System (CMS), but thanks to plugins like Advanced Custom Fields, it can be turned into one.

    The funny thing is, the platform clearly was moving in the general CMS direction for much of its early life. The availability of custom fields (not ACF specifically, but the more rudimentary open-ended key/value pair system created by the wp_postmeta table), not to mention custom post types and taxonomies, and the extensible template system, really pointed things in the direction of a system much broader than simply “blogging.”

    But Matt really just wants WordPress to be about blogging. Because that’s how he uses it. And he only sees what he wants to see.

    All of that natural growth in the direction of general-purpose CMS use was effectively pruned by the shift to all things Gutenberg: the Block Editor, and now the Site Editor (formerly Full Site Editing).

    I won’t deny that — now that they’re reasonably mature — the elements of Gutenberg are powerful and (somewhat) intuitive tools for building an engaging blog without having to write code.

    But for many of us who helped get WordPress to where it is, that’s not what we want, or need. These tools are not only irrelevant to our work, they make the work we need to do much more difficult.

    Specifically I’m talking about template design. In their pure intended form, Block Themes can’t have any PHP code in page templates. Which severely limits their functionality. Even if you end up creating a theme — like I have — that’s somewhat of a hybrid of the old and new ways, you’ll find it absolutely maddening how your PHP code may no longer have access to such obvious and basic variables as the post ID.

    Meanwhile, core functionality for things like custom fields has been all but killed. It seems like, at the very least, there should be a way in the Block Editor to reference a custom field value. Nope.

    Even Advanced Custom Fields’ efforts to extend Block Editor support require a bunch of convoluted hoops. Assuming that creating your own ACF Blocks is overkill, in some cases you can reference ACF values using the [acf] shortcode, but that only works for certain types of fields and, as I’m learning right now, it only seems to work in the Block Editor itself, not in templates.

    I’m not saying Advanced Custom Fields is the entire reason for Matt’s extreme actions against ACF owner WP Engine, or for his subsequent deranged steps, seemingly intent on tearing apart the WordPress community itself. But it’s hard to deny that Matt hates ACF for what it represents: a WordPress he can’t control, and one that doesn’t look like what he thinks it should be.

    Unfortunately, that’s the only kind of WordPress I care about.

    Well… that’s enough for now. Time to go and unravel my theme so I can make this new site I’m building actually do what my clients need it to do. Why did I choose WordPress again? I seem to be asking myself that question more and more frequently.


    Update: The morning after I wrote this, I stumbled upon this forgotten bit of code in my theme:

    function r3423_acf_disable_shortcode() {
        acf_update_setting('enable_shortcode', false);
    }
    add_action('acf/init', 'r3423_acf_disable_shortcode');

    So, uh… yeah, that part was my fault. But I was just following ACF’s instructions since I generally don’t ever use the shortcode.

  • WordPress development in the Gutenberg era: Threading the needle of Block Theme development

    As described in several of my recent posts here, I have been working for the past month or so on building my first “all-in” Block Theme for WordPress.

    After nearly 4 years of adamantly resisting “Gutenberg” and the new Block Editor revolution — not because I disliked the block concept, but because I disagreed philosophically with the core team’s approach (to what constitutes a block, which types of blocks are important, and which technologies are used to manage the UI of the editing screen) — I am finally accepting that if I am to continue making a living primarily as a WordPress developer, I need to give up on my Classic Editor, Advanced Custom Fields “Flexible Content” approach, and embrace that the Block Editor is now The Way.

    One of numerous challenges I’ve faced in this process (on top of the learning curve of a completely unfamiliar method of constructing themes, the dearth of adequate and up-to-date documentation, and the core team’s willingness to allow very unfinished versions of functionality to roll out in public WordPress releases) is figuring out the best way to approach some of the more complex design structures I am used to dealing with via ACF’s Flexible Content fields.

    My biggest hurdle is recognizing that what I think of as a “block” is not what the WordPress core team thinks of as a “block”

    Here I will admit this is a shortcoming of my own approach. I have been “opinionated” in my development approach (well, about everything, really), and created large-scale and complex “blocks” that, in Gutenberg/Block Editor terms, would really be “groups” or “block patterns,” not blocks. Gutenberg blocks are more granular.

    Gutenberg blocks are also static, in that they generally do not interact with database content, or if they do, it is in very limited “bloggy” ways that don’t align with my use of WordPress as a general-purpose CMS.

    So I’ve found myself falling back on ACF. I like its server-side approach. I’m more accustomed to dealing with PHP and MySQL. I use JavaScript (mainly jQuery) a fair bit for front-end interactive elements, but I don’t build complex functionality in JavaScript and I avoid AJAX if I can help it.

    You can see I’m destined for a strained relationship with the Block Editor.

    A concrete example: “Tiles”

    One of the most idiosyncratic elements of my old ACF approach is the block I call “Tiles.” It’s a way of creating a set of small blurbs to link to other pages/posts. There are numerous options for appearance: number of tiles per row, relationship between the image and text in a tile, etc. And there are also numerous options for the content source: a specific page or post (with the title, featured image and excerpt automatically pulled in), a dynamic feed from the blog or a specific category (likewise with the info pulled in automatically, except this one auto-updates when there’s a new post), or a completely custom-built tile, where you manually select the image and enter the text and link.

    Here are screenshots of the ACF-based editing tools for my Tiles block.

    I tried recreating this entire setup as a new ACF-based Block field group. It worked, to be sure, but the complex ACF editing layout really did not feel right in the new Block Editor interface, either in the sidebar (eek) or in the main content area. It felt like a cop-out.

    Then I considered creating a block pattern. I knew this would lack some of the benefits of my ACF-based Tiles block, but one in particular: the option to dynamically pull in the details of another page/post, rather than manually entering the text. But as a starting point, I decided to recreate the “custom” tile type.

    That, also, worked. But it was finicky and didn’t apply well in a lot of different places. So I realized that instead of creating a Tiles block pattern, I needed to create a Tile block pattern. Just one tile. Instead of a monolithic block that was really a group, users would insert each individual tile into whatever larger structure they want (e.g. columns).

    The end result was a block pattern that looked like this (screenshot instead of live code because, well, you really don’t want to use this):

    I was really proud of myself for using the new “lock” feature to force the elements to stay in a particular order, but to allow the user to remove elements they don’t need, such as the image, lead-in text, or CTA button.

    Still… I didn’t like it. And it didn’t allow for dynamic sources.

    Along the way I also finally came to grasp another fundamental limitation of the Block Editor and Block Patterns. Since all of the parameters of the blocks are stored as HTML comments right in the post content, you (the theme developer) can’t update the design of a block pattern once it’s inserted into a page/post. The Block Editor isn’t dynamically inserting content into a template when the page is rendered. It’s making a one-off copy of the template and storing it right along with the content at the point when the content is inserted into the page/post.

    This seems, to me, to be a fundamental flaw in the entire Gutenberg/Block Editor approach. It’s bad enough that if I were building it myself, I’d have stopped right there and taken a completely different direction. Maybe there’s a long-term plan to address this limitation, but for now it appears to be here to stay. Which led me back to ACF.

    Threading the needle

    And that was when I had my insight into the true nature of the problem. It was the fact that what I think of as a “block” is larger-scale than what the Block Editor treats as a block.

    So I went back to my Tiles ACF field group, stripped out the repeater functionality and created a Tile ACF field group. Now you’re building one tile at a time, it has all of the previous benefits of ACF’s dynamic integration of content with template functionality, it seems to correctly fit the definition of a “block” in the WordPress sense, and you can still have a flexible presentation of multiple tiles in a group… just using Block Editor “groups” to achieve that.

    I still have more to learn and questions to answer (followed by more questions to ask and then answer), but I feel like this was a major step forward in finding a way to merge the benefits of ACF with the… inevitability, I guess, of the Block Editor.

  • Using The SEO Framework with Advanced Custom Fields

    I’m going to go out on a limb and guess that I am not the only WordPress developer who in recent days (in the wake of their obnoxious Black Friday dashboard ad) has switched allegiance from Yoast to another SEO plugin, and that many of those who find themselves in a similar boat (to mix metaphors) have switched to The SEO Framework.

    I’ve only been using it for a couple of days, but I already love it. It does all of the things I actually used Yoast for, without any of the other stuff I did not use it for. I mean honestly, maybe readability scores and “cornerstone content” do provide an SEO boost, but I barely understand how to use these tools, so good luck explaining them to my clients in a meaningful way. I suppose they’re more of a tool for full-time SEO consultants who need to pad out their billable hours. (Sorry not sorry. My opinion on the business of SEO hasn’t changed all that much since 2011.)

    It wasn’t until the Black Friday ad that I really admitted to myself how much I don’t like Yoast. It does a lot of important things, and does them very well. But it’s obnoxious as hell about it. Pushing features you don’t really want or need into every page of the WordPress admin, and plastering its own over-designed admin screens with tons of garish ads promoting its “premium” features.

    Yuck.

    The SEO Framework encapsulates all of the key features I liked about Yoast into a single configuration screen, which kindly adheres to the standard WordPress admin UI design language instead of infusing its own brand style into every button and metabox border. It’s refreshingly boring to look at. And it just has the stuff I actually use, like title and description, OpenGraph tags, sitemap XML, the basic elements of SEO that unequivocally matter and can be a pain to build and maintain on your own.

    But enough about all of its great features. There’s one key thing it lacks: support for Advanced Custom Fields. My standard “modular design” theme relies almost entirely on ACF’s Flexible Content fields to work its page layout magic, and with all of the page content stored in custom fields instead of post_content, there’s nothing for The SEO Framework to latch onto to auto-generate meta descriptions.

    Fortunately, the developer has built in some hooks to allow you to customize the meta description output.

    Here’s a barebones starting point:

    function my_seo_framework_description($description, $args) {
      if (empty($description)) {
        $description = ''; // Add your own logic here!
      }
      return $description;
    }
    add_filter('the_seo_framework_custom_field_description', 'my_seo_framework_description', 10, 2);
    add_filter('the_seo_framework_generated_description', 'my_seo_framework_description', 10, 2);
    add_filter('the_seo_framework_fetched_description_excerpt', 'my_seo_framework_description', 10, 2);

    As the developer notes, it’s very important for SEO not to just output the same static description text on every page. You need to have a function of your own that will read your ACF field content and generate something meaningful here.

    Fortunately in my case, I had already done that, for generating custom excerpts from ACF content, so I was able to just stick a call to that function into the // Add your own logic here! line. You’ll need to customize your function to suit your specific content structure, but here’s the post that I used as a starting point for my function.

    Have fun!

  • WordPress Dev Tip: The Events Calendar 4.6.4 breaks Advanced Custom Fields Select2 fields… here’s a fix

    Suddenly, Advanced Custom Fields that use Select2 (any custom select dropdown, such as on Post Object fields) were broken. Testing plugins one-by-one narrowed it down to The Events Calendar. Apparently version 4.6.4 is loading Select2 and overriding ACF's own loading of Select2, breaking custom fields that use it.

    I found a simple fix in the WordPress Support Forums. Then I encapsulated that fix in a barebones plugin you can download here.

  • Make Advanced Custom Fields smarter about handling date fields

    I love Advanced Custom Fields almost as much as I love WordPress itself. But that’s not to say it doesn’t have its problems. Most are obscure, and minor… and incredibly aggravating once you stumble upon them.

    Here’s one such case. Date Picker fields are great, but no one seems to be able to agree on how to store dates in a database… other than insisting on avoiding Unix timestamps, the obvious choice.

    ACF stores its dates, for some reason, in YYYYMMDD format (or, as we’d express it in PHP Land, Ymd). No delimiters at all. If you’re not going to use Unix timestamps, why not at least use the MySQL convention of Y-m-d H:i:s? But I digress.

    I’m presently working on a project that merges some functionality of ACF and Gravity Forms, along with some custom code, to create a jobs board. It’s super-slick how Gravity Forms can create posts from a form submission, and even set them to pending review so a site editor can come in and review them before publishing.

    But… dates. Jobs boards have a lot of dates. And while Gravity Forms offers a wealth of options for date string format, Ymd isn’t one of them. So it ends up storing the date value in the database in a format ACF doesn’t like. Because ACF is very picky. It wants that format, and no other. If the value in the field is not in Ymd format, the value displayed on the admin editing screen is just… blank. And then when you save, whatever was previously saved in that field is erased.

    It doesn’t have to be this way. And thanks to the following bit of code, it won’t be. Now bear in mind, this is only altering what ACF renders on the editing screen. Once you’ve saved again from that point, the date will be stored in ACF’s preferred format, but up until then, it will be in whatever other format it was in when it landed in the database.

    If you’re writing your front end code proactively, that won’t matter. Because you’re already assuming data inconsistency and using strtotime() to standardize any dates you’re working with in your templates, right? Of course you are.

    OK, then. So the real goal here is just to get ACF to display the correct, saved date when you go in to edit the post, so it doesn’t then wipe out the date when you hit Save Changes.

    In your functions.php file, or wherever you think is best (a plugin would be nice), do this:

    function acf_smart_dates($field) {
      if ($field['value']) {
        $field['value'] = date('Ymd',strtotime($field['value']));
      }
      return $field;
    }
    add_filter('acf/prepare_field/type=date_picker','acf_smart_dates');

    That’ll do.