简体   繁体   中英

Include a view with a variable inside another view (Laravel's 5.6 - Blade)

I'm working on a one-page website that has it's navigation below the "Home" section. In this website my client has the option to hide or show any section of the page, I have accomplished that by adding a simple if statement to check if the page should be visible or not:

The view I am loading assembles all the sections on the one-page website:

@extends('layouts.master')

@section('content')

@include ('homeSection')

@include ('layouts.navigation')

@if ($section1)
@include ('section1')
@endif

@if ($section2)
@include ('section2')
@endif

...

@endsection

The only section that doesn't have a show/hide option (it will always show) is the home section, all of the other sections can be hidden by my client (through the database).

All of that is working perfectly, it's showing the pages that should be visible and hiding the sections that should be hidden.

The problem I'm having is how to make the navigation for it to show the pages that are actually hidden without having to execute the if statements on every for loop.

My solution was to make a @yield('navigation') and at the bottom of the page add a @section('navigation') which would @include the 'navigation' view once the $pages variable gets populated. like this:

@php ( $sections = array($home) )

@extends('layouts.master')

@section('content')

@include ('home')

@yield ('navigation')

@if ($section1)
@include ('section1')
@php ( array_push($sections, $section1) )
@endif

@if ($section2)
@include ('section2')
@php ( array_push($sections, $section2) )
@endif

...

@endsection

By this time the $sections variable will be populated with all the visible pages:

@section ('navigation')
@include ('layouts.navigation')
@endsection

Offcourse, I use the $sections variable to make the navigation bar with a @foreach statement, the only problem is it doesn't seem to be working. I tried moving the @section('navigation') but it only works when it goes before the @yield('navigation'), that's when the $sections variable only has the homeSection.

I know I can do this directly inside my navigation view, but I would have to use more logic inside it by re running all the if statements. Maybe I am just doing something wrong inside this view?

You generally want your view to be as dumb as possible, leaving logic up to the controller and allowing the view to only concern itself with rendering whatever it is given. This separation of concerns allows for much more maintainable code, and helps you avoid problems like the one you're facing now.

An implementation of what you're trying to achieve, that separates concerns, would be something like:

  1. Your controller constructs a list of sections that should be included
  2. Your controller passes that list of sections to your view
  3. Your view renders the navigation containing that list of sections
  4. Your view renders the sections

As a simple example of how you might implement this, here's a controller that constructs an array of sections, then decides which should be removed (that's where you can do your test for "is this disabled by the admin in the database") and finally provides that list of sections to the view.

public function index()
{
    $sections = [
        'section1' => 'First Section',
        'section2' => 'Second Section',
        'section3' => 'Third Section',
        'section4' => 'Fourth Section',
    ];

    foreach ($sections as $id => $name) {
        // determine if section should be included or not
        // `shouldBeIncluded` is whatever your truth test is
        if (! shouldBeIncluded($id)) {
            unset($sections[$id]);
        }
    }

    return view('index', ['sections' => $sections]);
}

Then anywhere in your view that is concerned with the sections (ie navigation, or the body) you can make use of that $sections array and you don't need to worry about determining if the section should be there or not, because the controller has already done that.

For example, to include all of the appropriate sections you can do away with the numerous if statements and have a single loop:

@foreach ($sections as $view => $name)
    @include($view)
@endforeach

And for navigation you'd do something like:

<ul>
    @foreach ($sections as $view => $name)
        <li><a href="#{{ $view }}">{{ $name }}</a></li>
    @endforeach
</ul>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM