2

I am trying to implement themes in a site so that certain pages have a different look and feel (and features) than other pages.

I have master.blade.php which contains the full HTML structure and has @section and @yield to get the content:

<html>
<body>

    @section('master-template')
    <?php
        view()->share('masterTemplate', 'general');
        $masterTemplate = "general"; 
    ?>
    @stop

    <header>
        @section('nav-1')
            @include('layout.navs.house-links')
        @show

        @section('nav-2')
            @include ('layout.navs.contact-links')
        @show

        @section('nav-3')
            @include('layout.navs.product-links')
        @show

        @section('nav-4')

        @show
    </header>
    @yield('content')
</body>
</html>

I then have ford.blade.php which extends master, and overwrites some things:

@extends('templates.master')

@section('master-template')
    <?php
        view()->share('masterTemplate', 'ford');
        $masterTemplate = "ford"; 
    ?>
@overwrite

@section('nav-1')
    @include('layout.navs.house-links')
@overwrite

@section('nav-2')
    @include ('layout.navs.contact-links')
@overwrite

@section('nav-3')
    @include('layout.navs.product-links')
@overwrite

Then a regular page on the website will extend master.blade, and anything that requires the Ford navigation bar and colour scheme will extend the ford.blade template.

I then bound a view composer to layout.navs.product-links which gets the $masterTemplate variable from the view data and checks if it is one of our themes (like "ford"). If it is a regular page, it will bind vehicle ranges for all manufacturers to the view, and if it is a ford page, it will only bind the ford ranges to the page. The pseudo-code of the view composer is below:

public function compose(View $view)
{
    // Get the view data
    $viewData = $view->getData();

    // Check for $masterTemplate view variable
    if (isset($viewData['masterTemplate'])) {
        $template = $viewData['masterTemplate'];

        if ($template == "ford") {
            $ranges = $this->getRangesForManufacturer($template);
        }else {
            $ranges = $this->getRangesForAllManufacturers();
        }

        $view->with('ranges', $ranges);
    }
}

The problem is, because ford.blade extends master.blade, BOTH views get rendered behind the scenes. So the above view composer logic is useless because it runs twice on the "ford" page, once for master.blade and then again for ford.blade.

I proved this by checking the queries that are running using Laravel DebugBar.

  1. How can I bind a variable $masterTemplate for use in all views (and partials) to check logic inside a view whether it is a "ford" or "general" page? I did it with @section and @overwrite in ford.blade but this seems to not work everywhere.

  2. How can I use a view composer to bind data to a partial view that is @included by ford.blade and master.blade, because ford.blade extends master.blade and so the view composer gets executed twice.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Daniel Twigg
  • 749
  • 4
  • 22

1 Answers1

1

At first glance, @overwrite might do what you told it to (except for @stop being enough, see how to extend a layout).

As a workaround: How about a redesign where you have a meta-master-template which contains the general stuff and is extended by both the ford and the master (i.e. general) template, depending on which part you need? (You could then rename master to general and meta-master to master)

That would skip your problem, because only one would be defined in each instance.

serv-inc
  • 35,772
  • 9
  • 166
  • 188
  • 1
    Thanks, making a new "general" template and letting the general and ford template extend master solved my issues. The number of database queries reduced dramatically on the page, so thank you! – Daniel Twigg Oct 26 '15 at 15:32
  • Good to hear that it helped. – serv-inc Oct 26 '15 at 17:13