# Multiple layouts in Sage 9?

**URL:** https://discourse.roots.io/t/multiple-layouts-in-sage-9/10117
**Category:** sage
**Tags:** blade, sage9
**Created:** 2017-08-02T12:28:42Z
**Posts:** 20

## Post 1 by @krishaamer — 2017-08-02T12:28:42Z

Hey everyone! I’ve building a couple of new projects using Trellis/Roots/Sage 9 and need to have different layouts for different parts of the site.

In general I probably need to make copies of app.blade.php and have some logic to switch between them?The documentation is still a bit sketchy and I think the example code for Sage 8 doesn’t apply here as we’re using blade now. Anyone who has this working and can offer some advice?

Thanks!  
Kris

---

## Post 2 by @strarsis — 2017-08-02T16:19:24Z

It is possible to select a template per page in WordPress, maybe this is the right approach?

---

## Post 3 by @nathobson — 2017-08-02T17:00:33Z

As @strarsis mentioned, you would leave app.blade.php and create your own new templates (views). Take a look in `recourses/views` and you should see `template-custom.blade.php` which you can copy and use as an example to work over. You can then select that template for a given page.

---

## Post 4 by @alwaysblank — 2017-08-02T17:36:20Z

I think you’re kind of looking at it backwards? `app.blade.php` is just extended by other templates. I.e. if you look at `views/index.blade.php` you’ll see:

```
@extends('layouts.app') // <-- this part here

@section('content')
  @include('partials.page-header')
...
```

If you want to use a different layout, all you need to do is create that layout in `views/layouts` and then `@extend` it in the template you want to use.

So, let’s say you had a post type called “Book” and you wanted Books to use a special layout. You might do something like this:

```
// views/layouts/book.blade.php
<!doctype html>
<html @php(language_attributes())>
  @include('partials.head')
  <body @php(body_class())>
    @php(do_action('get_header'))
    <div class="wrap container" role="document">
      <main class="main">
          @yield('content')
      </main>
    </div>
    @php(do_action('get_footer'))
    @php(wp_footer())
  </body>
</html>
```

```
//views/single-book.blade.php
@extends('layouts.book') // <-- the important part!

@section('content')
  @while(have_posts()) @php(the_post())
    {!! $book_content !!}
  @endwhile
@endsection
```

WordPress will use the template heirarchy to load `views/single-book.blade.php` when you’re viewing a single Book, and then Blade will use the `@extends` directive to load `views/layouts/book.blade.php` as the layout. There’s no need for any additional logic.

---

## Post 5 by @strarsis — 2017-08-02T19:32:52Z

@alwaysblank:  
So `single-book.blade.php` is a template for a single post?  
And `book.blade.php` is a template for the archive page?

---

## Post 6 by @alwaysblank — 2017-08-02T19:43:52Z

`views/single-book.blade.php` is the template WordPress will load for a single Book-type post, yes. But `views/layouts/book.blade.php` is a layout template, just like `views/layouts/app.blade.php` – _not_ a Book-type archive template. Unless another template `@extends` it, as demonstrated above, it won’t appear anywhere.

My example above wasn’t intended to be comprehensive, just to illustrate how Sage uses the Blades in `views/layouts`. If you wanted to create an archive for Books using what I have above, you’d need to create `views/archive-book.php` and put `@extends('layouts.book')` at the top of it.

You don’t actually _have_ to use layouts for anything, though: They’re just a convenient way to wrap your templates with stuff that’s the same across your theme. There’s nothing to prevent you from making `views/single-book.blade.php` look like this, completely avoiding loading a layout:

```
// views/single-book.blade.php
<!doctype html>
<html @php(language_attributes())>
  @include('partials.head')
  <body @php(body_class())>
    @php(do_action('get_header'))
    <div class="wrap container" role="document">
      <main class="main">
          {!! $book_content !!}
      </main>
    </div>
    @php(do_action('get_footer'))
    @php(wp_footer())
  </body>
</html>
```

---

## Post 7 by @krishaamer — 2017-08-02T21:26:57Z

Thanks for the explanation! Roots/Sage looks so different I forgot the old WordPress logic still works!

---

## Post 8 by @Gordon_Smith — 2018-03-12T21:35:16Z

First time using Sage 9 - equally confused. Where does template-custom.blade.php come in on the custom template side? I’ve duplicated it, named my new template template-plain.blade.php \> changed the @includes to pull a couple different files. For some reason, what I’ve done works locally, but when uploaded to the beloved wpengine, the pages show up completely blank. I’ve dumped wpengine’s cache and can’t for the life of me figure out why both template-custom.blade.php and template-plain.blade.php won’t show any content on the remote server. Sorry for the revival, this post was helpful, but I think I’m still fuzzy on the understanding.

---

## Post 9 by @alwaysblank — 2018-03-12T21:50:38Z

You may be running into an issue specific to WPEngine. There’s some discussion and possible solutions here: [Sage 9 on WPEngine](https://discourse.roots.io/t/sage-9-on-wpengine/9090/24?u=alwaysblank)

---

## Post 10 by @Gordon_Smith — 2018-03-12T22:20:17Z

The solution is perfect and works - to echo resolving this issue when trying to use a custom page template and host your Sage 9 theme on WP Engine:

in sage \> config \> view.php

change: `'compiled' => wp_upload_dir()['basedir'].'/cache',`  
to: `'compiled' => '/tmp/sage-cache',`

And re-upload your view.php file.

Thank you @alwaysblank - you’ve saved me much pain and suffering.

Edit: clarification on the issue.

---

## Post 11 by @AmirFarid — 2018-06-30T12:45:27Z

Hello,

Looked around but didn’t see a post specific to my question and this seems to be the most relevant one.

So what I am trying to achieve is to have full-width templates for all my pages apart from the blog page and any subsequent blog posts.

Looking at the templates I see that **app.blade.php** is being used for all pages/posts and it has

`<div class="wrap container" role="document">`

I want to replace that for ALL pages too:

`<div class="container-fluid" role="document">`

BUT then keep it the same i.e. `<div class="wrap container" role="document">` for the blog page and any subsequent blog post pages.

Now I did create a template by duplicating app.blade.php to template-fullwidth.blade.php to be used for all pages that require full-width containers which I can then select in WordPress for pages that I create that require full width but I somehow feel that this isn’t the best or mostly importantly DRY method of achieving what I would like if I only want to remove that small amount of code.

Once thats done i would be implementing this for the actual blog page itself:

> [@Custom Page Template for blog posts](https://discourse.roots.io/t/custom-page-template-for-blog-posts/10137/2):
>
> This loop is adapted from one I used recently. You should be able to just drop it into whatever template you’re using to display your blog posts and it’ll work. It may need a little tweaking based on your needs. \<?php global $wp\_the\_query; while (have\_posts() && $wp\_the\_query-\>current\_post \< 0): the\_post(); ?\> \<div class="featured-post"\> \<?php the\_title(); // ...and whatever else you want to do ?\> \</div\> \<?php endwhile; ?\> \<div class="two-columns"\> \<?php while (have\_posts() && $wp…

which looks spot on for what I need to show my initial blog page.

SO is there an easy way to replace `<div class="wrap container" role="document">` to `<div class="container-fluid" role="document">` for ALL pages except the blog page and posts? which will in turn only require me to make a cutom template for the blog page which the above link describes…

please keep in mind that I am new to blade/sage 9 and have only previously used the old roots theme and I have read up on blade and watched screencasts etc but cannot seem to figure this out.

Hope all that makes sense… trying not to repeat my self in code and keep everything as clean as possible…

---

## Post 12 by @MWDelaney — 2018-06-30T13:00:14Z

You could most easily achieve this with Sass:

```
.wrap {
  @extend .container;

  .blog &,
  .post-single & {
    @extend .container-fluid;
  }
}
```

(Or something like that. That’s untested.)

Or with Controller by adding a variable of classes that you fill conditionally:

```
<div class="wrap {!! $containerclass !!}" role="document">
```

---

## Post 13 by @AmirFarid — 2018-06-30T13:25:29Z

@MWDelaney thank you for your quick reply.

Seems like the controller method would be simpler? as I am trying to keep the css as lean as possible.

however can you please elaborate?

> [@MWDelaney](#):
>
> Or with Controller by adding a variable of classes that you fill conditionally:
> 
> ```
> <div class="wrap {!! $containerclass !!}" role="document">
> ```

newbie @ both sage9/blade/controllers and no idea on how to implement that. I read up on: [GitHub - soberwp/controller: Composer package to enable a controller when using Blade with Sage 9](https://github.com/soberwp/controller#overview) and info on this post here:

[https://discourse.roots.io/t/how-to-create-a-controller-file-for-a-custom-template-page-in-sage-9/11833/4](https://discourse.roots.io/t/how-to-create-a-controller-file-for-a-custom-template-page-in-sage-9/11833/4)

I tried but all i get is broken pages :worried:

---

## Post 15 by @SRawhloe — 2018-06-30T14:43:42Z

Honestly, I’d just set the container class full width by default and fixed width for blog/single pages in css. Much simpler than setting up these named specific classes all the time. And one could argue these bootstrap class names go against the concept of separating style and content.

---

## Post 16 by @MWDelaney — 2018-06-30T14:52:21Z

In `app/controllers/app.php` add the following function to the class:

```
public function containerclasses() {
        return “container-fluid”;
    }
```

In `app/controllers` create `blog.php` and make its contents:

```
<?php

namespace App;
use Sober\Controller\Controller;

class Blog extends Controller
{
    public function containerclasses() {
        return “container”;
    }
}
```

That should get you started!

EDIT: note, I wrote this from memory on my phone and didn’t test it.

---

## Post 17 by @MWDelaney — 2018-06-30T14:52:47Z

This isn’t a helpful response to the question that was asked.

---

## Post 18 by @AmirFarid — 2018-06-30T16:18:23Z

Thanks guys.

i briefly caught the deleted post that @SRawhloe posted…

@MWDelaney thank you. playing with this now after going through some blade docs and watching a few other screencasts to get my head around it.

I could just easily accomplish what i want by duplicating app.blade.php and creating new templates **but** then i would be inundated with loads of templates. Your way looks promising and hopefully i will have luck with it :slight_smile:

---

## Post 19 by @MWDelaney — 2018-06-30T16:42:28Z

You could also just move the `container` class deeper into the templates but that’s less DRY.

---

## Post 20 by @AmirFarid — 2018-07-03T10:03:36Z

> [@MWDelaney](#):
>
> In `app/controllers/app.php` add the following function to the class:
> 
> ```
> public function containerclasses() {
> return “container-fluid”;
> }
> ```
> 
> In `app/controllers` create `blog.php` and make its contents:
> 
> ```
> <?php
> 
> namespace App;
> use Sober\Controller\Controller;
> 
> class Blog extends Controller
> {
> public function containerclasses() {
> return “container”;
> }
> }
> ```
> 
> That should get you started!
> 
> EDIT: note, I wrote this from memory on my phone and didn’t test it.

**Thanks guys** for your input. Much appreciated.

I have played around with this for a few days now and cannot get my head around it. The code works with no errors but the container class isn’t reflected as I wanted. Most definitely because I’m new to blade and probably didn’t add in additional stuff to control it all (and when I did I just got errors galore).

I just went ahead and created a full-width template instead which I now manually select in pages that require the full-width container. It’s less DRY but working!
