Laravel Blade pass array data to multiple extends - php

I've searched for this on internet alot, but wasnt able to find answers. I'm using Laravel 5 and I've little issue with blade templating as in my project I need sometime to do multiple extends and I need to pass all data from one layout to all master layouts "extends"
Nested page example :
#extends('layouts.full', ['var' => 'key'])
#section('page')
page content here
#stop
layouts/full.blade.php example
#extends('app', ['need to pass same data here too'])
#section('content')
#yield('page')
#stop
and app.blade.php is just main html stuff
And I wanted to ask is there possibility to pass same vars without setting global variable like?
#extends('layouts.full', $data = [])

I think this might help you :
https://laravel.com/docs/5.2/blade#service-injection

to pass multiple variables, use an array:
#extends('layouts.full', [ 'data' => ['var' => 'key'] ])
as for multiple extensions, maybe just use include statements in layouts.full :
#include('header')
#section('content')
#yield('page')
#stop
#include('footer')

Related

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 }}

Laravel blade template specific code

Currently we are using the Laravel framework on several projects, but one issue we keep running into which i don't like is the following issue:
Lets say you have a Homepage and a Content page
HomepageController has all Homepage specific php code
ContentpageController has all Content specific php code
we have an app.blade.php that does
#yield('page')
HomepageController calls the view homepage.blade.php containing
#extends('app')
#section('page')
Some HTML part
#include('parts.top_5')
#endsection
ContentController calls the view content.blade.php containing
#extends('app')
#section('page')
Some different HTML part
#include('parts.top_5')
#endsection
Here you can see both pages include parts.top_5, the top 5 needs some specific variables to output the top5. Now the issue is we are currently copying the code for the top5 variables in both controllers or in grouped middleware but is there a better solution to generate some blade specific variables when the part is included? So a bit like running a controller function on loading the blade template?
I have been searching the internet but can't seem to find anyone with the same question. Hopefully someone can help me on this mindbreaking issue!
You can add this binding to AppServiceProvider
(or any custom ServiceProvider You want)
like this:
public function boot()
{
$view->composer('parts.top_5', function($view) {
$view->with('any_data' => 'You want');
})
}
This way any time Laravel will compose parts.top_5 view this closure method will be triggerd.
And in documentations it's here:
http://laravel.com/docs/5.0/views#view-composers

Laravel blade section

I just get to know that we can write section with this:
#section('sectionname','data')
What is the difference between the above method with the below method?
#section('sectionname')
'data'
#stop
Is it a proper way to write with the first method? Although, during my testing, it does not need #stop for the first method. But is it the best practice that we need to put it?
Thank you.
For writing small string in the sections you can use
#section('sectionname','data')
and to write multiple lines of html you will use
#section('sectionname')
'data'
#stop

Laravel 4 Blade #include variable

I was trying to do include with Laravel blade, but the problem is it can't pass the variable. Here's my example code:
file_include.blade.php
<?php
$myvar = "some text";
main.blade.php
#include('file_include')
{{$myvar}}
When I run the file, it return the error "Undefined variable: myvar". So, how can I pass the variable from the include file to the main file?
Thank you.
Why would you pass it from the include to the calling template? If you need it in the calling template, create it there, then pass it into the included template like this:
#include('view.name', array('some'=>'data'))
Above code snippet from http://laravel.com/docs/templates
Unfortunately Laravel Blade engine doesn't support what you expected!.But a little traditional way you can achieve this!
SOLUTION 1 - without Laravel Blade Engine
Step a:
from
file_include.blade.php
to
file_include.php
Step b:
main.blade.php
<?php
include('app/views/file_include.php')
?>
{{$myvar}}
SOLUTION 2 with Laravel Blade Engine
routes.php
$data = array(
'data1' => "one",
'data2' => "two",
);
View::share('data', $data);
Access $data array from Any View like this
{{ $data['data1'] }}
Output
one
Blade is a Template Engine for Laravel. So try passing the value from the controller or you may define it in the routes.php for testing purposes.
#include is used to include sub-views.
I think you must understand the variable scope in Laravel Blade template. Including a template using #include will inherit all variables from its parent view(the view where it was defined). But I guess you can't use your defined variables in your child view at the parent scope. If you want your variable be available to the parent try use View::share($variableName, $variableValue) it will be available to all views as expected.
In this scenarion $myvar would be available only on the local scope of the include call.
Why don't you send the variable directly from the controller?
I suggest you do a classic PHP require if you really want to change your variable (then it's automatically by reference)

Override section in a laravel blade template throwing undefined variable errors

I am using Laravel 4 and blade templates, and running into an issue when I try and extend a template.
In my layout I have
#yield('content')
and in my page I have
#section('content')
Welcome {{ $name }}
#stop
which works fine, I've created another page very similar to my first, and just want to change override the admin content section. The other sections in the template are fine.
so I extend my page, and do
#section('content')
Hello!
#stop
I get an undefined notice with the $name variable.
I tried
#section('content')
Hello!
#overwrite
and same deal, I get the notice error.
I checked my controller and it IS using the correct template. I am not calling #parent so I don't understand, how can I overwrite a section in a template with out notice errors?
Blade layouts work their way up the tree to the route or master view before rendering any of the children. Thus, nested views that extend others must always have their parent rendered before they are. As a result, parent views that contain sections will always be rendered prior to the child.
To overcome the problem you are experiencing it is a good idea to only ever nest pages that don't overwrite parents sections that contain variables, as the parents content will always be rendered before the child.
As the above ideal can't always be adhered to or a parents section content is still required, a good alternative method would be to use view composers. View composers give you an opportunity to declare variables for any specific view whenever they are rendered.
View::composer(array('pages.admin'), function($view)
{
$view->with('name', Auth::user()->username);
});
Another alternative would be to use a view creator. Creators are fired the moment a view is instantiated rather than rendered. This method allows you to overwrite the variable should you so wish prior to the view being rendered.
View::creator(array('pages.admin'), function($view)
{
$view->with('name', Auth::user()->username);
});
You can read up more about these methods in the documentation here. (Or here for the Laravel 5 documentation.)
I can't guarantee support for Laravel 4 but for those looking for a solution that works in Laravel 5.5 (and probably a fair bit further back – hard to check) is to define the variables you need when #extending.
E.g. in the example in the question:
#extend('my.parent.view', ['name' => ''])
This approach can be especially useful if the data needed is available to the child-view, but under a different name.
E.g. if a parent-view needed a $parent variable, but the child view only has a $child variable which has a property referencing the parent, you might do:
#extend('my.parent.view', ['parent' => $child->parent])
I am not sure if this is a bug or intentional, but it seems like Laravel renders the variables before interpreting blade instructions.
The workaround would be this:
views/layouts/testlayout.blade.php:
<html>
<body>
#yield('sidebar', 'This is the master sidebar. {{ $name }}' )
<div class="container">
#yield('content')
</div>
</body>
</html>
actual view: views/test.blade.php
#extends('layouts.testlayout')
#section('sidebar')
No variable in the child
#stop
#section('content')
This is a child content
#stop
This prevents the variable $name to get rendered if there is a section with that name in the actual view. It seems like this is the approach if the content in the layout file contains a variable
In your page try this :
#section('content')
#hasSection('content')
#yield('content')
#else
Welcome {{ $name }}
#endif
#stop
And read this post for more inspiration https://laracasts.com/discuss/channels/laravel/laravel-blade-layouts-inheritence-problem
I found an easy solution for this problem :)
Just add the # symbol before the variable/method you call in the parent view. If there is an error (notice/warning) PHP will ignore that and continue the execution.
It's not perfect, but save us to code view/composers.
Hope this help!

Categories