How to pass a subview to a master view in Laravel? - php

I have a master view and depending on the URL and controller, it will load in another subview to a variable called $content, that's the idea.
Currently I am trying with:
return view("master")->with(["content" => view("pages.group")]);
So for example, if the URL is https://example.com/group/1 I am trying to get the subview included on my master template. Currently, it just gets escaped for XSS but I feel like this isn't the right way to do this?

I assume you are trying to display the sub-view content in the follwing way:
{{ $content }}
Change your syntax from {{ }} (Escaped output) to {!! !!} (Non escaped output).
{!! $content !!}

In the end after #lagbox mentioned it, using Laravel sections enabled me to use a master view and extend it when needed. https://laravel.com/docs/6.x/blade#extending-a-layout

Related

Laravel blade "{{ command }}" not working correctly

I have this weird problem with my Laravel 5.5 version... I created the auth views using
php artisan make:auth
This command created the views controllers and everything I need to lets get stared to work. But I'm having this visualization problem
As you can see on the register view I have this problem.
The real thing is that "{{ any_command }}" is printing the code that its supose to generate instead of interprating like part of the code. But if I use {!! any_command !!} instead it seems to work propertly. What can happend to my laravel is screwed up. It has nothing to be with the artisan auth method, because I tried to create a new form (using laravel collective form helper) and get the same result.
{{ }} will escape all data before printing. So, if you write any HTML tag inside, it will be escaped and printed as is. Just like your example.
{!! !!} will print unescaped data. This will print the tags correctly, but you have to take care where you use it, because someone could inject unwanted data there.
So, in your case, you should use {!! !!}.
Please, refer to this question: What is the difference between {{ }} and {!! !!} in laravel blade files?

Laravel Blade - Advantage of #slot/#component vs #include?

Laravel 5.4 Blade introduced the concept of components & slots - but I can't see what they add over the traditional #include. As I understand, with component/slots, you do:
In template component-tpl.blade.php:
<div class='container'>
<h1>{{$slot1}}</h1>
<h2>{{$slot2}}</h2>
</div>
Using slots in page template, you do:
#component('component-tpl')
#slot('slot1')
The content of Slot 1
#endslot
#slot('slot2')
The content of Slot 2
#endslot
#endcomponent
What functionality does that provide over the older:
#include('component-tpl',['slot1'=>'The content of Slot 1',
'slot2'=>"The content of Slot 2"])
using the exact same 'component-tpl.blade.php' Blade template?
What am I missing? Thanks for any insights.
Chris
As stated, there's no functional difference I was incorrect - see benjaminhull's answer for details on variable scoping and passing blade syntax code. The following still holds for basic usage, though.
If a slot could contain HTML, then using a component will give a cleaner syntax in your blade files.
#component('test')
<strong>This text has html</strong>
#endcomponent
versus
#include('test', ['slot' => '<strong>This text has HTML</strong>'])
Equally, if a component has no slots, then an include may be preferred:
#include('test')
versus
#component('test')
#endcomponent
There are two key differences.
1. Variable scope
As described in #DavidHyogo's answer, a component only sees variables explicitly passed to it. So you have to give it all variables like so...
#component('my-component', ['foo' => 'bar', 'etc' => 'etc'])
Whereas an include will adopt all variables from the global/current scope by default - unless you define an explicit set of variables to pass it, which then becomes local scope again.
{{-- This include will see all variables from the global/current scope --}}
#include('my-component')
{{-- This include will only see the variables explicitly passed in --}}
#include('my-component', ['foo' => 'bar', 'etc' => 'etc'])
2. Component's {{ $slot }} vs include's {{ $var }}
When using a {{ $slot }} in a component, you can give it blade syntax code e.g...
{{-- alert.blade.php --}}
<div class="alert">{{ $slot }}</div>
#component('alert')
<div>Hello {{ $name }} #include('welcome-message')</div>
#endcomponent
Note how the slot will receive html AND blade syntax code and just deal with it.
This is not possible with includes because you can only pass variables into includes...
{{-- alert.blade.php --}}
<div class="alert">{{ $slot }}</div>
#include('alert', ['slot' => "I CAN'T PASS IN BLADE SYNTAX HERE!"])
It could be done in a more hacky way by grabbing a fresh view() helper and passing it some variables to compile the output we want to pass into the slot, but this is what components are for.
I think I've tracked down another crucial difference. For instance, from the documentation for 5.4:
Blade's #include directive allows you to include a Blade view from within another view. All variables that are available to the parent view will be made available to the included view:
As far as I can tell, components have a different scope from a containing view and so the variables available to the parent view are not available within the component. You need to pass a variable to a component like this:
#component('alert', ['foo' => 'bar'])
#endcomponent
This discussion is related to this problem:
Use variables inside the Markdown Mailables
As the documentation says:
Components and slots provide similar benefits to sections and
layouts; however, some may find the mental model of components and
slots easier to understand.
For me most important thing is component needs a class. So when I need just a simplest reusable part of html (blade) there is no need to create blade file + php file, just simple #include with subview is enough ;)

How to echo / embed laravel view output in layout as variable

I want to use view helper like {{ render_part("user_profile"); }} in laravel layout, and render_profile will return and html,
Right now it prints as plain string and not rendering as HTML, Also I need some good guide to understand laravel blade/view compilation architecture so that i can write custom classes overriding core methods.
I've upvoted Gerard Reches answer. But if you want to render views from your controller and display the HTML in your views:
By default, Blade {{ }} statements are automatically sent through PHP's htmlentities function to prevent XSS attacks. If you do not want your data to be escaped, you may use the following syntax:
{!! $myHTML !!}
Hope this helps.

How to correct Laravel's Blade variable section scoping when yielding inside a loop?

When I include a blade template that extends a base blade, any variables within the section of the included blade show only the variables of the first iteration.
Reading around it seems the render order here is important, and views are rendered before variables, or vice versa.
Note
I have read this SO question/answer: Laravel Blade #yield variable scope
The below snippet is greatly reduced in complexity, so the example could be restructured to exclude sections/extends. However my real case can't be
Example
// index.blade.php
//
#foreach($jobs as $job)
{{ $job->id }} // <-- Correct output, 1,2,3,..N
#include('job-detail', ['id' => $job->id])
#endforeach
Then in the job detail blade
// job-detail.blade.php
//
#extends('job-base')
A: {{ $id }} // <-- Correct output, 1,2,3,..N
#section('content')
B: {{ $id }} // <-- Incorrect output, 1,1,1,..1 (or whatever the first index is)
#endsection // have also tried #stop
Then in the job base blade
// job-base.blade.php
//
#yield('content') // Have also tried #section('content') + #show
After wading through the source code, namely BladeCompiler and View/Factory I noticed the following snippet:
protected function compileOverwrite($expression)
{
return '<?php $__env->stopSection(true); ?>';
}
In the background Laravel appears to store rendered content (by including the file, and extract current variables in a ob_style fashion) in a keyed array, with the view name being the key.
When stopSection is not passed a boolean true, it creates a new key, and the view gets the data from the original key.
Long story short, it's now undocumented (for 5.1+) but can be found in the docs for 5.0:
https://laravel.com/docs/5.0/templates
However it doesn't really explain the "why". This page seems to explain it a little better:
http://laravel-recipes.com/recipes/244/stopping-injecting-content-into-a-section-and-overwriting

Laravel Blade - pass variable via an #include or #yield

I need to pass a variable to an included Blade file. I have attempted this two-ways; however, neither have been successful.
Pass a variable, title, to the included file:
#section('left')
#include('modal', ['title' => 'Hello'])
#stop
Use #yield and set the section:
#section('left')
#include('modal')
#section('title')
Hello
#stop
#stop
I am using Laravel 4.2. I am unaware if what I am trying to do is possible, but I imagine it is.
According to the documentation, the include-way should be the way to do it:
Including Sub-Views
#include('view.name')
You may also pass an array of data to the included view:
#include('view.name', array('some'=>'data'))
My hunch is that $title is conflicting with another variable in your nested templates. Just for troubleshooting, try temporarily calling it something else.
pass an array of data to the included view
#include('view.name', array('some'=>'data'))
then use this on view/name folder
{{ $some }}

Categories