Roots Discourse

How to add new comments walker to Sage


#1

I want to make several markup changes to wp_list_comments() that requires me to include a new walker.

Here are the steps I’m using:

  1. Create new comments.php file in /theme/app folder
  2. Add namespace App; to the top of this new comments file, followed by a named function sage_comments() containing new code for the comments section to replace the existing comments function reference
  3. Add newly created file to Sage required files array in functions.php
  4. Edit /resources/views/partials/comments.blade.php line containing wp_list_comments() to include within the array 'walker' => 'sage_comments()'.

After completing this, I get the following error on any post containing a comment section
Fatal error: Uncaught Symfony\Component\Debug\Exception\FatalThrowableError: Class 'sage_comments' not found in [path/to/app/uploads/cache/cachefile.php on line 15.

What am I missing or doing wrong?


#2

Hey @asuh - I think you’re facing two problems:

  1. Class vs function: You need to pass wp_list_comments a Walker class object, not just a function. So, your app/comments.php will need to contain something like this: https://gist.github.com/georgiecel/9445357.
  2. Namespaces: you’ll need to reference your class (or function as you currently have it) within the App namespace.

Your final wp_list_comments call will look like this (both instantiating your class and respecting the App namespace): 'walker' => new App\My_Walker()

Using the comments walker I linked to, I was able to get this working as a test. The only change I had to make to that walker was to change this:

class comment_walker extends Walker_Comment {

to:

class comment_walker extends \Walker_Comment

The \ means the root namespace, instead of the App namespace.

Let me know if you have any questions.


#3

Thank you for the detailed answer! That’s very helpful.

My follow up question is about coding structure and architecture. Sage appears to be very DRY in how it’s built. Most of the files in /app contain almost no HTML markup, outsourcing that responsibility back to /resources. I like the separation of concerns and clean look as well.

In that respect, would it make sense for me to create a new blade file in the /resources/views/partials directory and reference that file from the newly created /app/comments.php file?


#4

@asuh I personally would include the markup needed for the comments themselves (the equivalent of what wp_list_comments is currently printing with the default walker) in your walker class in app/comments.php. At least for menu walkers (and I’m assuming it’s similar for comment walkers) the markup is so tightly coupled to the logic of the walker that it would probably do more harm than good to try to separate them.

That still adheres to the DRY principle, because the markup generated by the walker is still only defined in one place–the walker–and not repeated elsewhere.

If you look at some of the menu walkers for Sage that have been posted in Discourse (e.g., @MWDelaney’s Bootstrap 4 nav walker linked to in this post) you will see that’s the approach they take. The template into which the menu / comments are inserted via wp_nav_menu or wp_list_comments is a Blade template in the normal template location, but the markup for the menu items/comments themselves is in the walker class.


#5

I want to follow up since I’ve had no success.

My Walker class replacement

I followed your advice using \Walker_Comment and left out the name space b/c of this.

Current unsuccessful setup:

  1. Create new comments.php file in /theme/app folder
  2. Add newly created file to Sage required files array in functions.php (Is this even necessary?)
  3. Edit /resources/views/partials/comments.blade.php line containing wp_list_comments() to include last within the array 'walker' => new comments_reloaded()

Your final wp_list_comments call will look like this (both instantiating your class and respecting the App namespace): 'walker' => new App\My_Walker()

This causes the same error I originally reported.

So while it looks like it should be working, I do not see any of the updates inside of comments.php when I load the comment system.

I also tried @MWDelaney’s method of using /app/controllers/app.php and, while no errors were returned, it did not use the updated /app/comments.php file.


#6

@asuh I think the only thing you’re missing is putting namespace App; right at the top of your walker file.

I got it working using your code with these steps:

  1. Copy your gist into app/comments.php and modify the top of the file as follows:

    <?php
    
    namespace App;
    
    class comments_reloaded extends \Walker_Comment {
    
  2. Add ‘comments’ to required files array in functions.php (yes, this is necessary):

    /**
     * Sage required files
     *
     * The mapped array determines the code library included in your theme.
     * Add or remove files to the array as needed. Supports child theme overrides.
     */
    array_map(function ($file) use ($sage_error) {
        $file = "../app/{$file}.php";
        if (!locate_template($file, true, true)) {
            $sage_error(sprintf(__('Error locating <code>%s</code> for inclusion.', 'sage'), $file), 'File not found');
        }
    }, ['helpers', 'setup', 'filters', 'admin', 'comments']);
    
  3. Specify the new walker within the options for wp_list_comments in comments.blade.php:

    {!! wp_list_comments(['style' => 'ol', 'short_ping' => true, 'walker' => new App\comments_reloaded()]) !!}
    

#7

Yeah, this was one of so many different combinations that I tried and it doesn’t work for me. I don’t see any of the changes or additions I made in app/comments.php for any of the comments.

I assume that if this was working correctly, once complete step 3 and save, it should refresh the localhost page and I’d see differences in all the comments for what I added. If this is not correct, then I must not understand something.

How do I troubleshoot this to find out why it’s not working right?


#8

Hey @asuh - yep, you’re correct, once you complete those steps and refresh the page you should see different output. Here’s what I get:

Before

After

I think we have all the right steps–if it’s still not working on your end, I’m not sure what to try next besides the usual tactics when there’s no trail to follow: make sure there’s no error output on the page or in your logs, double check everything, and maybe dump out any function output or variables involved to take a closer look at the values and see if that gives you a lead.

On my end I don’t think there’s anything more I can do without access to your actual theme. :frowning:


#9

@asuh - another thing you could try is create a fresh, clean copy of Sage 9 and follow the steps I listed. If that works, it tells us there’s something different about how you implemented it in your current theme or that some other change in your theme is breaking it somehow.


#10

@mmirus I got it working! The issue wasn’t my implementation, it was a plugin which is implementing its own custom Walker. This is preventing me from using a custom one myself.

Lesson learned: check my plugins to make sure that’s not an issue.

Thanks for your feedback!