Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

dkulagin's avatar

Passing Title, Description, and Other Metadata to the Layout

Hello, I’m coming from the Yii 1.x world, where the layout had direct access to the current controller and all its public properties. This made it easy to set page-wide values like the title, meta description, Open Graph properties, indexing rules, and so on—these were typically defined in the controller, and the layout could use them directly during rendering.

In Laravel, I pass this data to the view, which then forwards it to the layout component. While this works, it leads to a lot of repetitive code—every view needs to pass the same set of variables to the layout.

I understand that Laravel offers more elegant or "Laravel-ish" ways of handling this kind of logic, and I’d like to learn the proper approach.

Could you please advise on the recommended way to pass common metadata (like title, description, etc.) to layouts in Laravel?

0 likes
12 replies
Snapey's avatar

its not common though is it? Presumably every page has different metadata which you have to set somewhere?

I would probably create a dto object with some sensible defaults and pass it into the view. You then only have one thing to pass and possibly forward into the layout blade.

dkulagin's avatar

@Snapey Sure, each page has its own unique metadata, and each type of controller sets it in its own way. But since the title, description, and other metadata are unambiguous within a single request, there’s a strong temptation to treat them like globals and pass them directly to the layout—bypassing the intermediate views altogether.

A DTO seems like a reasonable solution—I'm just trying to learn the Laravel way of doing things.

martinbean's avatar

@dkulagin What exactly is the problem? Pass the data from the controller, then echo them in your layout template:

public function someAction()
{
    return view('some.view')->with([
        'metaTitle' => 'Some Title',
        'metaDescription' => 'Some description.',
    ]);
}
<!-- resources/views/layout.blade.php -->
<!DOCTYPE html>
<html>
    <head>
        <title>{{ $metaTitle }}</title>
        @isset($metaDescription)
        <meta name="description" content="{{ $metaDescription }}">
        @endisset
    </head>
    <body>
        <!-- Layout body -->
    </body>
</html>
dkulagin's avatar

@martinbean The issue is that I’m currently passing a whole set of variables to the view like this:

public function index()
{
    return view('main')->with([
        'title' => 'Some title',
        'description' => 'Some description',
    ]);
}

Then, I forward them to the layout:

<x-layout :title="$title" :description="$description">
    ...
</x-layout>

Only at that point are they rendered:

<title>{{ $title }}</title>
        @isset($description)
        <meta name="description" content="{{ $description }}">
        @endisset

The problem arises when I want to introduce another "global" layout variable—for example, a custom meta tag or a flag to toggle the sidebar on a specific page. In this case, I would have to update all my views just to pass that new variable through to the layout.

In Yii, this was handled differently: I would simply add a new property to the base controller class, assign it a sensible default, and it would immediately be available in the layout—no need to pass it explicitly through every individual view.

Snapey's avatar
Snapey
Best Answer
Level 122

Using the DTO approach

// include this function in every controller and set the values as you need.

private function createMetadata() 
{
	$meta = new MetaDto(
		'description' => 'page description',
        'title' => 'page title',
		'keywords' => ' expert software',
	)

	view()->share('meta', $meta);
}

Create the dto however you like, the key part is view()->share() makes data available in the view without you having to pass it in the final return from the controller.

You can pass it into the layout like

<x-layout :meta="$meta">

// or 

<x-layout :meta>

and in layout

        <title>{{ $meta->title }}</title>
        @isset($meta->description)
        <meta name="description" content="{{ $meta->description }}">
        @endisset

Passing the object, you only need to amend the layout when you want to add something.

1 like
martinbean's avatar

@dkulagin Setting and rendering metadata might be a good use case for the context component.

You could set metadata in various places within your application, such as sensible defaults in a service provider:

public function boot(): void
{
    Context::add([
        'title' => 'Your App Name',
    ]);
}

And then override or set additional metadata in other places in your application, such as controllers:

public function someAction()
{
    Context::add([
        'title' => 'Page-Specific Title',
        'description' => 'Page-specific description.',
    ]);

    return view('some.view');
}

You can then render the context in your layout component:

<title>{{ Context::get('title') }}</title>
@if(Context::has('description'))
<meta name="description" content="{{ Context::get('description') }}">
@endif

You could also use context stacks for setting breadcrumb items if your site has those.

1 like
dkulagin's avatar

@Snapey I'll do it in a couple of days, unless more replies are added to the discussion.

Please or to participate in this conversation.