Skip to content

[12.x] Add @​context Blade directive #56146

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

Merged
merged 1 commit into from
Jul 7, 2025

Conversation

martinbean
Copy link
Contributor

@martinbean martinbean commented Jun 26, 2025

Adds a new @context Blade directive, that operates similar to the existing @session directive.


Context Directives

The @context directive may be used to determine if a context value exists. If the context value exists, the template contents within the @context and @endcontext directives will be evaluated. Within the @context directive’s contents, you may echo the $value variable to display the context value:

@context('foo')
    <div>{{ $value }}</div>
@endcontext

This makes it easy to check if a context value is set and if so, to obtain its value, in Blade templates. My particular use case:

@context('canonical')
    <link href="{{ $value }}" rel="canonical">
@endcontext

@martinbean martinbean changed the title [12.x] Add @​context Blade directive [12.x] Add @​context Blade directive Jun 26, 2025
@devajmeireles
Copy link
Contributor

This is good and useful. The only problem that I see with it is the fact that the context has two data: normal and hidden, so it might be better to add an argument @context('foo', hidden: true) - to determine which context you want to interact with, or add two separate directives: @context and @contextHidden

@martinbean
Copy link
Contributor Author

@devajmeireles It just delegates to the context helper, which doesn’t make a distinction between hidden and non-hidden values when retrieving them:

if (! function_exists('context')) {
/**
* Get / set the specified context value.
*
* @param array|string|null $key
* @param mixed $default
* @return ($key is string ? mixed : \Illuminate\Log\Context\Repository)
*/
function context($key = null, $default = null)
{
$context = app(ContextRepository::class);
return match (true) {
is_null($key) => $context,
is_array($key) => $context->add($key),
default => $context->get($key, $default),
};
}
}

@devajmeireles
Copy link
Contributor

@devajmeireles It just delegates to the context helper, which doesn’t make a distinction between hidden and non-hidden values when retrieving them:

if (! function_exists('context')) {
/**
* Get / set the specified context value.
*
* @param array|string|null $key
* @param mixed $default
* @return ($key is string ? mixed : \Illuminate\Log\Context\Repository)
*/
function context($key = null, $default = null)
{
$context = app(ContextRepository::class);
return match (true) {
is_null($key) => $context,
is_array($key) => $context->add($key),
default => $context->get($key, $default),
};
}
}

I see, maybe we can adapt the helper before your PR to enable interaction with hidden values.

@devajmeireles
Copy link
Contributor

@martinbean I just noticed we can interact with the hidden data even if we do not have the hidden argument as part of the helper. All we need to do is interact with the helper without specifying the key:

context()->has('foo');
context()->hasHidden('bar');

@taylorotwell taylorotwell merged commit a944904 into laravel:12.x Jul 7, 2025
62 checks passed
@martinbean martinbean deleted the feature/compiles-contexts branch July 7, 2025 14:54
AhmedAlaa4611 referenced this pull request in laravel/docs Jul 8, 2025
@WouterDeGeringel
Copy link

@martinbean Thanks for the implementation

A word of warning: I just found out that it was a breaking change for our website and I think it might be for many more.
Since JSON-LD uses the key "@context" and this is used in many blade files, I recon.

This is easily fixed by adding a "@" making it "@@context".

@rodrigopedra
Copy link
Contributor

@WouterDeGeringel thanks for the heads-up; just got hit by that.

@martinbean
Copy link
Contributor Author

@WouterDeGeringel Sorry to hear that. I’m not sure what you’d like me to do, though? The release notes do also mention the inclusion of this new directive, so did you just update the framework version without checking what was included in the update?

I imagine adding any Blade directive is going to be a breaking change for someone somewhere if they’re including code that includes an @ symbol.

That being said, there are ways to deal with this, such as using the @verbatim directive:

@verbatim
    <script type="application/ld+json">
        {
            "@context": "https://schema.org",
            // ...
        }
    </script>
@endvertbatim

But personally, when I’ve dealt with JSON-LD data before, I’ve generated the JSON using PHP and then printed it in my Blade templates using the @json directive:

<script type="application/ld+json">@json($schema)</script>

This then eliminates the possibility of content containing @ symbols being mistakenly interpreted as Blade directives.

@rodrigopedra
Copy link
Contributor

did you just update the framework version without checking what was included in the update?

I caught it locally when running Dusk tests, so no servers were harmed =)

This last release was 2 weeks in the oven, and I was eager for another PR to land.

there are ways to deal with this, such as using the @verbatim directive

That is what I ended up using.

I’ve generated the JSON using PHP and then printed it in my Blade templates using the @json directive

For dynamic JSON-LD, such as metadata for videos, I do that. But for static ones, such as organization data that never changes, I usually have it directly on the blade file.

Nonetheless, the @context directive was a great addition, and I am even already using it on a project. Thanks! =)

@WouterDeGeringel
Copy link

@martinbean Thanks for the examples...the @verbatim directive is a better solution then mine, I think.

I’m not sure what you’d like me to do, though?
It wasn't my intention to give you the feeling you should do something and I wasn't trying to complain.
I just wanted let you and others to know what I found out.

Thanks again for you work.

@applyACS
Copy link

applyACS commented Jul 9, 2025

@taylorotwell this should not have been in a minor release since it breaks your app if you use https://schema.org/ structure 😑

@dasundev
Copy link
Contributor

dasundev commented Jul 9, 2025

This also breaks our site because of the JSON-LD:

<script type="application/ld+json">
    {
      "@context": "https://schema.org",
      // ...
    }
</script>

But I think we may consider wrapping everything that uses @ with the @verbatim directive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants