-
Notifications
You must be signed in to change notification settings - Fork 11.4k
[11.x] Added "snippet" blade feature with >13x speed improvement #51268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Would this also allow passing those snippets into inner views as a variable (can see some use cases for it for myself 🤔)? also didn't see it handle invalid names if someone named it as |
Can you show an example of your use case?
Fixed that |
There are a lot of cases like blade component slots where you cannot receive data up where the slot is provided, this would allow passing the state up to the parent from the component/child view with additional state of where the parent can additionally add or render based on it. Probably bad example, but example nonetheless: // fields/input.blade.php
@php($id = Uuid::generate())
@if(isset($labelSnippet))
{!! $labelSnippet($id) !!}
@endif
<input id="{{ $id }}">
// form.blade.php
@snippet('labelSnippet', $id)
<label for="{{ $id }}">This is my <strong>rich</strong> label</label>
@endsnippet
@foreach($fields as $field)
@include('fields.input', ['name' => $field->name, 'labelSnippet' => $labelSnippet])
@endforeach |
Got it. Right now a snippet name"labelSnippet" will turned to One could make it more strict and say: each snippet name MUST be a proper php compatible variable name, like |
I wonder wether this "mechanism" could work for blade components as well, somehow. That would speed them up by a lot. Will check that out. |
I think we specifically want to make Blade components much faster. 👍 |
@taylorotwell, I get your point about speed improvements for blade components. But this PR is not aimed at that at all. The main point of this PR is to add a simple feature which makes it possible to avoid some blade components at all, for better readability. The example with the image tags is a real one. In cases like this it does not make sense to create another blade component, for readability sake. I kindly ask you to reconsider. |
@donnysim FYI: Ryan Chandler published something similar which could suit your usecase even better: https://github.com/ryangjchandler/blade-capture-directive/tree/main |
@dimitri-koenig Oh cool, definitely will play around with it, thanks! |
Svelte 5 has a neat new feature called "snippets". See https://svelte-5-preview.vercel.app/docs/snippets
Basically it allows you to extract parts of a template into a snippet, in the same file, and reuse that later in the file. That way you can avoid using another blade file, which in certain cases might be preferable.
To take those Svelte examples and translate them to blade:
This:
Becomes this:
Like function declarations, snippets can have an arbitrary number of parameters, which can have default values.
Snippet scope
Snippets can be declared anywhere inside a blade file. But since they are functions they cannot reference variables outside themselves. Maybe one day PHP will have multiline arrow functions. Nuno tried that already (php/php-src#6246).
Declared snippets are only usable in the same blade file with the exception of included bladed files using @include directive, which makes sense since you are literally including the content of another file.
Snippet declaration
Snippets can be declared with or without a specific function name, and with or without parameters:
Snippet function name declaration could also be declared as
@snippet (foo)
. The implementation can handle this case too.Snippet rendering
Taking the previous examples, snippets can be rendered like this:
Benchmarks
I've done some benchmarking, with PHP 8.3, on a Macbook Pro M2 Max, analog to this (#51141 (comment)), with the following process:
avatar.blade.php:
simple-component-test.blade.php:
snippet-test.blade.php:
Results
With opcache, cached views:

Without opcache, but cached views:

I know, the example falls a bit short, but it's still nice to see some numbers :-)
Backport to older Laravel versions
In case someone wants to use this feature on older installations, this would be the code:
AppServiceProvider.php: