Laravel Blade - Advantage of @slot/@component vs @include?

As stated, there's no functional difference I was incorrect - see benjaminhull's answer for details on variable scoping and passing blade syntax code. The following still holds for basic usage, though.

If a slot could contain HTML, then using a component will give a cleaner syntax in your blade files.

@component('test')
   <strong>This text has html</strong>
@endcomponent

versus

@include('test', ['slot' => '<strong>This text has HTML</strong>'])

Equally, if a component has no slots, then an include may be preferred:

@include('test')

versus

@component('test')
@endcomponent

I think I've tracked down another crucial difference. For instance, from the documentation for 5.4:

Blade's @include directive allows you to include a Blade view from within another view. All variables that are available to the parent view will be made available to the included view:

As far as I can tell, components have a different scope from a containing view and so the variables available to the parent view are not available within the component. You need to pass a variable to a component like this:

@component('alert', ['foo' => 'bar'])
@endcomponent

This discussion is related to this problem: Use variables inside the Markdown Mailables


There are two key differences.

1. Variable scope

As described in @DavidHyogo's answer, a component only sees variables explicitly passed to it. So you have to give it all variables like so...

@component('my-component', ['foo' => 'bar', 'etc' => 'etc'])

Whereas an include will adopt all variables from the global/current scope by default - unless you define an explicit set of variables to pass it, which then becomes local scope again.

{{-- This include will see all variables from the global/current scope --}}
@include('my-component')

{{-- This include will only see the variables explicitly passed in --}}
@include('my-component', ['foo' => 'bar', 'etc' => 'etc']) 

2. Component's {{ $slot }} vs include's {{ $var }}

When using a {{ $slot }} in a component, you can give it blade syntax code e.g...

{{-- alert.blade.php --}}
<div class="alert">{{ $slot }}</div>

@component('alert')
    <div>Hello {{ $name }} @include('welcome-message')</div>
@endcomponent

Note how the slot will receive html AND blade syntax code and just deal with it.

This is not possible with includes because you can only pass variables into includes...

{{-- alert.blade.php --}}
<div class="alert">{{ $slot }}</div>

@include('alert', ['slot' => "I CAN'T PASS IN BLADE SYNTAX HERE!"])

It could be done in a more hacky way by grabbing a fresh view() helper and passing it some variables to compile the output we want to pass into the slot, but this is what components are for.