Best Practice / Resources for Blade

I noticed that Laravel Blade has been added to Sage 9. It seems like it’s going to be pretty great but I’m wondering if anyone has any tips or resources for using Blade with WordPress. I’ve hit the Laravel docs and also have a Laracasts subscription.

I mean, I get the concepts, but I’d love to see some real world examples as they pertain to WordPress. I was checking out WP Blade to get some ideas but, again, I’m just not sure what best practice is.

I tried creating a directive for custom queries but ultimately I felt like I was still cluttering the top of my page templates (views?) with a bunch of logic, just using a different syntax.

Anyway, I realize my post is a little scattered. Short of it is I’m pretty excited to get into Blade templates and would love to hear any thoughts, tips, or ideas for using Blade with WordPress. The more logic I can get out of my template files the happier I’ll be. It’s one of my biggest gripes when building with WordPress.

:smile:

8 Likes

As much as I know from learning Laravel in the last weeks this one can be good for starting out - https://laracasts.com/series/laravel-5-fundamentals/episodes/5

But as you said we may need some pointers or good docs for that with examples for best practices :slight_smile:

2 Likes

So what you may have noticed with many of the other templating engine integrations, they are much more than just allowing new templates. Timber for instance comes as almost a framework, with controllers and a new router.

The thinking process for integrating Blade into Sage was really to make it as light and drop-in as possible. We made sure to have the template hierarchy work the same, and we’ve squashed some bugs related to third party plugin templates.

We haven’t even really included many Blade directives. I’ve seen directives for WP_Query as well as ACF, and those can be helpful, but again not something that necessarily needs to be in a starter theme.

It should be relatively simple, but open ended to add in a controller like system. My thought was it could be similar to controller’s in other frameworks, however instead of returning a view with data passed to it, you can just filter the view data: https://github.com/roots/sage/blob/6ca3b3faa7e3ec29d01016fdc7bd656ff0e8a64e/src/filters.php#L50

With all that in mind, we will be writing a blog post pretty soon to cover Blade, let us know what you’d like to know about it.

5 Likes

@smutek, I’ve been thinking the same thing since I saw it added.

I’m a big fan of Tuts+, and I saw they have a course that covers blade essentials, layouts, and partials. Only problem is that it’s specifically for Laravel. I’ll probably watch it through.

I watched one on youtube, and I just found a scotch.io article on it. They usually have some good content.

@kalenjohnson, one specific question I’ve been wondering is, “couldn’t I do all of this stuff with React?”. What would be the pros/cons of Blade vs. React?

Let’s keep this thread on topic — Blade resources and best practices, not why we’re using PHP instead of JS :slight_smile:

4 Likes

Awesome! I think I’m mainly looking for how best to do things like… everything! :slight_smile:

Mostly best practices, I think. For example, I was looking at WP Blade and was thinking it looked good but then saw this comment on the Blade PR referring to those directives as “Bad”, so I wonder - what is bad about them?

@darjanpanic and @masoninthesis, thanks for the links. I have a Laracasts subscription and will be giving it more attention, and will check out the Tuts+ and other links as well.

2 Likes

Fair enough @ben! It was an out there question. I just like to learn as few frameworks as possible, and given that I’ve already invested time into learning React, I guess I’m actually just questioning if Blade is going to stick around long enough to make it worth learning.

Obviously blade and React serve different needs (single pg apps vs. templating) So instead of React vs. Blade- @kalenjohnson, I guess I’m asking:

What are some specific, basic examples of how it can make PHP dev easier?

Why is blade useful to learn?

Is it’s implementation pretty long term?

And, what are the basics someone should know to be able to implement it?

Thanks guys! I’m genuinely stoked to get up and running w/ Sage9

1 Like

I was playing around a little tonight and was able to return data to my page template. I’d love some feedback on this if anyone has time.

Okay, so I have 2 pages, titled “post-1” and post-2", and both pages are using a custom page template. In this case I’m using the default custom page template that ships with Sage, and I’ve made a partial called content-page-custom.blade.php

I also have a file I’ve added to /src/ called controllers.php, in which I have the follwing -

namespace App;

function post1()
{
    $data = [
        'title' => 'List',
        'names' => [
            'Frank',
            'Bob',
            'Mary'
        ]
    ];

    return $data;
}

add_filter( 'sage/template/post-1/data', 'App\\post1' );

function post2()
{
    $data = [
        'title' => 'List 2',
        'names' => [
            'Bill',
            'Sally',
            'Becky'
        ]
    ];

    return $data;
}

add_filter( 'sage/template/post-2/data', 'App\\post2' );

function both()
{
    $data = ['both' => 'Both'];
    // Undefined, gets overwritten
    return $data;
}

add_filter( 'sage/template/page-template-template-custom-blade/data', 'App\\both' );

Then, on my partial I have -

<h2>{{ $title or 'Not Defined' }}</h2>

<ul>
  @foreach($names as $name)
    <li>{{$name}}</li>
  @endforeach
</ul>

<h2>{{ $both or 'Not defined' }}</h2>

The lists output as expected, with post-1 getting the correct data back for the post-1 filter, and post 2 getting the correct data back as well.

The both() function should return identical data to both pages, and is hooked into page-template-template-custom-blade, but gets overwritten because it fires earlier and $data it’s in the same scope as the lists.

So… questions… :slight_smile:

Am I on the right track here?
What’s the best way to avoid having my variables overwritten, like in my both() example?
It seems that whatever I save in the $data variable has to be saved in key value pairs, right?

Any feedback would be most appreciated, I feel like I’m pretty close to understanding this.

3 Likes

Keep in mind that filter is a standard WP filter, so just like any other filter, you need to accept the original data/variable, modify it, and return it.

function both($data) {
    $data['both'] = 'Both';

    return $data;
}

Other than that, it looks good. That is basically what I had in mind if I was going to implement some simple controllers in Sage 9

3 Likes

Got it, thank you Kalen!

Wow, this is super nice man, fantastic job!

Here’s a simple image slider with Slick. This is using ACF’s gallery field, but anything will do.

Controller -

function slider( $data ) {

    $images = get_field('images');

    if ( $images ) {
        $data['images'] = $images;
    }

    return $data;
}
add_filter( 'sage/template/home/data', 'App\\slider' );

View -

<ul class="list-unstyled slider">
  @forelse($images as $image)
    <li><img src="{{$image['url']}}" alt="{{$image['alt']}}"></li>
  @empty
    <li class="alert alert-danger">No Images</li>
  @endforelse
</ul>

I’m giddy about this, it’s like a whole new WordPress!!! :sunny: :smile: :sunny:

14 Likes

You can even split it out and put the slider in it’s own little blade file, and have something like this -

@php(the_content())

@if($images)
  @include('partials/slider')
@endif

Sorry for all the posts, but this is so damn nice!

3 Likes

Interesting stuff indeed! I might ditch Timber for this after all :slight_smile:

I was just wundering how you guys would declare global data, regardless of the body class?
Stuff like menu’s, languages, ACF options etc?

Hey, check this one out for navs –

/**
 * Navigation arguments
 *
 * @param $data
 *
 * @return mixed
 */
function navControl( $data ) {

    // Pass the walker class to a var, so it
    // doesn't instantiate here.
    $bootstrapWalker = 'wp_bootstrap_navwalker';

    // Main Nav
    $mainNavArgs = [
        'theme_location' => 'primary_navigation',
        'walker'         => new $bootstrapWalker,
        'menu_class'     => 'navbar-nav mr-auto'
    ];

    $data['mainNavArgs'] = $mainNavArgs;

    // Social Nav
    $socialNavArgs = [
        'walker'         => new $bootstrapWalker,
        'theme_location' => 'social_navigation',
        'menu_class'     => 'nav social-nav',
        'link_before'    => '<span class="sr-only">',
        'link_after'     => '</span>'
    ];

    $data['socialNavArgs'] = $socialNavArgs;


    return $data;

}

add_filter( 'sage/template/global/data', 'App\\navControl' );

The project I’m working on now has 2 navs, this changes the nav calls in my template file from this -

  <div class="collapse navbar-collapse" id="navbarSupportedContent">
    @if (has_nav_menu('primary_navigation'))
      {!! wp_nav_menu(['theme_location' => 'primary_navigation', 'walker' => new wp_bootstrap_navwalker(), 'menu_class' => 'navbar-nav mr-auto']) !!}
    @endif
  </div>

to this -

<div class="collapse navbar-collapse" id="navbarSupportedContent">
    @if (has_nav_menu('primary_navigation'))
      {!! wp_nav_menu($mainNavArgs) !!}
    @endif
</div>

:slight_smile: Much cleaner!

I just added a body class called global so I can access it everywhere.

3 Likes

Man I am struggling to understand this, but I think I get it. This keeps the ugly (and duplicative if you’re calling it twice on a page) wp_nav_menu() arguments out of the template file, making everything easier to read. Then passes that args array to the template for use in $mainNavArgs.

Sort of like globaling the args in functions.php but not horrifying.

Is that close at least?

That’s the benefit for me, with the nav. It makes the markup cleaner and helps separate concerns a little more.

This is still new to me as well, maybe the nav example is overkill, but I’m almost certain to get obsessive and go overboard a little before I find some balance. :slight_smile:

OK so I implemented your Nav directive just to get comfortable with it. It works!

It seems like this could be a really easy way to go overboard and over-design a system, though. Instead of calling a WP function, I’m calling a function that calls that function. Is that better?

For me I guess it’s going to come down to moving logic outside of template files and also readability. For example, the social nav in my project would look like this -

{!! wp_nav_menu([ 'walker' => new bootstrapWalker, 'theme_location' => 'social_navigation', 'menu_class' => 'nav social-nav', 'link_before' => '<span class="sr-only">', 'link_after' => '</span>']) !!}

So when I look at that I feel like, man that’s kind of unruly, and I can simplify that to -

{!! wp_nav_menu($socialNavArgs) !!}

Which is much more readable to me and seems a good use.

I guess it could go a step further and move the nav menu call out as well, but personally I don’t mind the function call, so long as it’s paired down to a simple, meaningful expression when used inside a template file.

With this the intent is clear - give me the social nav:

{!! wp_nav_menu($socialNavArgs) !!}

I couldn’t see myself abstracting something like the_post() out of a template file for the exact reasons you mentioned. It doesn’t really make sense and seems like adding unnecessary complexity.

Does that make sense? Personally I’m stoked to be able to get logic out of my template files, and make template files more readable.

1 Like

I’m really liking the ideas in this thread!

Is there any way to get the results of the standard WP_Query for a view into a variable? I’d rather loop through posts with standard blade syntax.

I know I can requery entirely with get_posts() but I’m wondering if there’s a way to get a similar data return for the default query on a view.

Has anyone played around with this? How deep of a rabbit hole is it to go down?

Thanks,

Would love to add Blade SVG to my next Sage websites but I might have to read and get more comfortable with Blade.

Anyone knows if this is possible to begin with?

Edit: I guess this one is really tied to Laravel so it won’t work.
There’s always https://packagist.org/packages/oscarotero/inline-svg which works really well.