Creating Flexible Layouts in Laravel with Yields, Includes, and Slots
Published: 2024-01-18 13:15:52

---
title: Creating Flexible Layouts in Laravel with Yields, Includes, and Slots
published: true
date: 2024-01-18 09:29:46 UTC
tags: 
canonical_url: https://dcblog.dev/creating-flexible-layouts-in-laravel-with-yields-includes-and-slots
---

## Yields

In Laravel, the `@yield` directive is used in [blade templates](https://laravel.com/docs/10.x/blade) to define a section that can have code injected or "yielded" by child views.

Here's a basic explanation of how `@yield` works:

Defining a section with `@yield('name')`

In a blade file typically used for layouts (can be any \*.blade.php file), you can use the `@yield` directive to define a section where content can be injected. For example:

**layouts/app.blade.php**

```php
<html>
<head>
    <title>@yield('title') - {{ conifig('app.name') }}</title>
</head>
<body>
    <div class="container">
        @yield('content')
    </div>
</body>
</html>
```

In this example, there are two `@yield` directives: one for the 'title' section and another for the 'content' section.

In a child view that extends the parent view, you can use the `@section` directive to fill the sections defined in the parent view.

For example:

```php
@extends('layouts.app')

@section('title', 'Page Title')

@section('content')
    <p>This is the content of the page.</p>
@endsection
```

In this example, the view extends from `layouts/app.blade.php` the `blade.php` is left off the path as Laravel will know the file by its name only.

Then fill the 'title' and 'content' sections using a `@section` directive. This directive can self-close like in the title example or enclose multiple lines like in the ‘content’ example.

When you render the child view, Laravel will combine the content of the child view with the layout defined in the parent view. The `@yield` directives in the parent view will be replaced with the content provided in the child view. php  The resulting HTML will be:

```php
<html>
<head>
    <title>Page Title</title>
</head>
<body>
    <div class="container">
        <p>This is the content of the page.</p>
    </div>
</body>
</html>
```

## Includes

For more flexibility, you can break your views into smaller chunks using multiple views, for example:

```php
@include('layouts.partials.header')

<div class="wrapper">
@yield('content')
</div>

@include('layouts.partials.footer')
```

This layout view uses both `@include` and `@yield` directives. An include is used to bring in other files into the current file where the `@include` is placed.

`@include` takes 2 arguments. A file path and optionally an array. By default, anything defined in the parent page is available to the included file but it’s better to be explicit by passing in an array.

For example:

```php
@include('pages', ['items' => $arrayOfItems])
```

The above example would include a `pages.blade.php` file and pass in an array called items. Inside the view `$pages` could then be used.

`@include('layouts.partials.header')` would include a file called `header.blade.php` located in `layouts/partials`

Typically I define multiple `yields` in a header like this:

```php
<html>
<head>
	@yield('meta')
    <title>@yield('title') - {{ config('app.name') }}</title>
	@yield('css')
</head>
<body>

</body>
@yield('js')
</html>
```

This allows me to inject code into various parts of my layout.

For example in a blog I want to use meta tags for that post only and no other pages. This means I cannot hardcode the meta tags and the contents should change from post to post.

Typically I would inject meta tags in a post view like this:

```php
@section('meta')
<meta itemprop="name" content="{{ $post->title }}">
<meta itemprop="description" content="{!! strip_tags(Str::limit($post->description, 100)) !!}">
@if (!empty($post->image))
<meta itemprop="image" content="{{ url($post->image) }}">
@endif
<meta name='description' content='{!! strip_tags(Str::limit($post->description, 100)) !!}'>
<meta property="article:published_time" content="{{ $post->created_at }}" />
<meta property="article:modified_time" content="{{ $post->updated_at }}" />

<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="{{ url($post->slug) }}">
<meta property="og:title" content="{{ $post->title }}">
<meta property="og:description" content="{!! strip_tags(Str::limit($post->description, 100)) !!}">
@if (!empty($post->image))
    <meta property="og:image" content="{{ url(trim($post->image)) }}">
@endif

<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@dcblogdev">
<meta name="twitter:creator" content="@dcblogdev">
<meta property="twitter:url" content="{{ url($post->slug) }}">
<meta property="twitter:title" content="{{ $post->title }}">
<meta property="twitter:description" content="{!! strip_tags(Str::limit($post->description, 100)) !!}">
@if (!empty($post->image))
    <meta property="twitter:image" content="{{ url(trim($post->image)) }}">
@endif
<link rel="canonical" href='{{ url($post->slug) }}'>
<link rel="webmention" href='https://webmention.io/dcblog.dev/webmention'>
<link rel="pingback" href="https://webmention.io/dcblog.dev/xmlrpc" />
<link rel="pingback" href="https://webmention.io/webmention?forward={{ url($post->slug) }}" />
@endSection
```

I may also inject CSS or Javascript from a single view, this is done in the same way:

```php
@section('js')
<script>
	...
</script>
@endSection
```

## Slots

When working with components or Livewire you will come across the concept of slots.

### What is a slot?

A `$slot` variable is a special variable used to reference the content that is passed into a component. Components are a way to create reusable and encapsulated pieces of view logic.

Here's a brief explanation of how `$slot` works within Laravel components:

### Components

When you create a Blade component, you can define a slot within it using the `{{ $slot }}` syntax.

For example:

```php
<!-- resources/views/components/alert.blade.php -->
<div class="alert">
    {{ $slot }}
</div>
```

In this example, the alert component has a slot where content can be injected.

When you use the component in another view, you can pass content into the slot using the component tag.

For example:

```php
<!-- resources/views/welcome.blade.php -->
<x-alert>
    This is the content for the alert.
</x-alert>
```

In this example, the content "This is the content for the alert." is passed into the `$slot` of the alert component.

When the Blade view is rendered, Laravel will replace the `{{ $slot }}` in the component with the content provided when using the component. The resulting HTML will look like this:

```php
<div class="alert">
    This is the content for the alert.
</div>
```

The `$slot` variable essentially acts as a placeholder for the content passed to the component.

Using `$slot` allows you to create flexible and reusable components that can accept different content each time they are used. It provides a convenient way to structure and organize your Blade templates while maintaining the reusability of components.

## Using Component Layouts

Components can also be layout files, for example making a new component called `AppLayout` using Artisan:

```php
php artisan make:component AppLayout
```

Will create 2 files:

* app/View/Components/AppLayout.php
    
* resources/views/components/app-layout.blade.php
    

Replace the contents of `AppLayout.php` with:

```php
<?php

namespace App\View\Components;

use Illuminate\View\Component;
use Illuminate\View\View;

class AppLayout extends Component
{
    /**
     * Get the view / contents that represents the component.
     */
    public function render(): View
    {
        return view('layouts.app');
    }
}
```

This will load a `layouts/app.blade.php` when rendered.

To have a view use this layout inside a view use the `<x-` directive followed by the component name in the kebab case. So `AppLayout` becomes `app-layout`

```php
<x-app-layout>
    The content goes here.
</x-app-layout>
```

Now inside `app.blade.php` since this used the `AppLayout` component we don’t use `@yield` to have placeholders instead, we use `{{ $slot }}` or named slots

For example:

```php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <title>{{ $title ?? null }} - {{ config('app.name', 'Laravel') }}</title>
    </head>
    <body>
        {{ $slot }}
    </body>
</html>
```

### What are named slots?

In components, named slots provide a way to define and pass content into specific sections of a component. Unlike the default slot, which is referenced using, named slots allow you to define multiple distinct sections for injecting content. This can be particularly useful when you need to organize and structure different parts of your component.

Here's a basic explanation of how named slots work.

When creating a blade component, you can define named slots using the `@slot` directive. For example:

```php
<!-- resources/views/components/alert.blade.php -->
<div class="alert">
    <div class="header">
        @slot('header')
            {{ $header ?? '' }}
        @endslot
    </div>

    <div class="content">
        {{ $slot }}
    </div>

    <div class="footer">
        @slot('footer')
            {{ $footer ?? '' }}
        @endslot
    </div>
</div>
```

In this example, the alert component has three named slots: 'header', 'footer', and the default slot, which is simply referred to as `$slot`.

When using the component in another blade view, you can pass content into the named slots using the component tag. For example:

```php
<!-- resources/views/welcome.blade.php -->
<x-alert>
    <x-slot name="header">Alert Header</x-slot>
    This is the content for the alert.
    <x-slot name="footer">Alert Footer</x-slot>
</x-alert>
```

Here, content is provided for the 'header' and 'footer' named slots, in addition to the default slot.

When the blade view is rendered, Laravel will replace the content of the named slots in the component with the content provided when using the component. The resulting HTML will look like this:

```php
<div class="alert">
    <div class="header">Alert Header</div>
    <div class="content">This is the content for the alert.</div>
    <div class="footer">Alert Footer</div>
</div>
```

Named slots provide a way to structure and organize the content of your components more explicitly. They make it easier to manage complex components with multiple distinct sections by giving each section a meaningful name.