Extending from diffrent layouts in laravel view - php

I have a laravel page which can be extended from admin layout or user layout.
If the user logged as admin it should extend from admin, otherwise it should extend from user.
Can I make this control with a simple if inside of my view like:
//in my view
#if(Auth::check())
#extends('layouts.admin')
#else
#extends('layouts.outside')
If I do this control in my controller I need to make two view for user and admin and I dont want to duplicate my views like:
//in my controller
if(Auth::check())
return View::make('bot/bwin_admin');
else
return View::make('bot/bwin_user');//the view is duplicated :(
So how can I use different parent layout for a view without duplicating that view in laravel?

You can control the layout in your controller.
First add the default layout to your controller:
public $layout = 'layouts.outside';
Then do this in your action:
if(Auth::check()){
$this->layout = View::make('layouts.admin');
}
$this->layout->content = View::make('bot/bwin');
Also, you can then remove the #extends() from your view. It is not needed anymore since the controller defines the layout.

Related

How to pass variables master layout blade in Laravel 8

I'm using Laravel 8, but don't seem to know which controller controls the layout master blade file. I have been able to pass variables to the sub-view (Profile page) file successfully but don't know how to achieve that with the layout view master blade.
I am trying to pass variables from a controller called ProfileController in app\Http\Controllers to the master blade layout. In the profile controller, I have a code that retrieves user profile data from the database.
$profileInfo = Profile::with('address')->where('id', '=', '1')->get();
return view('admin_pages.profile', compact('profileInfo'));
In the profiles table, I have names and image fields first_name, last_name, photo which I can access with a foreach loop from the data $profileInfo passed to the sub-view using
#foreach($profileInfo as $data)
{{ $data->first_name}}
#endforeach
and so on.
My master blade file is located at resources\views\layout\admin.blade.php. I want to be able to display the names and photo from the admin.blade.php so the logged in user can see their profile image when logged in even when they don't visit their profile page (sub-view) which is located at resources\views\admin_pages\profile.blade.php, extending the master blade (admin.blade.php).
Please kindly help out.
Solution 1:
You can pass variable from the blade file via the #extends as second argument function.
Controller:
public function index(){
$title='Sir/Madam';
return view('home',compact('title'));
}
Home.blade.php
<?php
#extends('layouts.admin', ['title' => $title])
Layout.master.blade.php
dd($title)
you will see results.
I suggest you to learn about Laravel Component.
You can make the profile in admin layout with dynamic data, reusable without pass variable in every controller and route.
Create an Admin component with artisan:
php artisan make:component Profile
It will create a Profile.php as component controller and profile.blade.php
Open Profile.php and add this code:
public function render()
{
return view('components.profile', [
'profile' => Profile::with('address')->where('id', '=', '1')->first();
]);
}
Open profile.blade.php
<div>
{{$profile->first_name}}
</div>
Now, render the Profile component on your template admin.
Replace
#foreach($profileInfo as $data)
{{ $data->first_name}}
#endforeach
with
<x-profile/>
You can learn more by reading blade documentation in this link

Adding information to a Layout without having to call it on every controller

I have a layout that is used when you are logged in. menu.blade.php.
Then I use it in blade files #extends('admin.layouts.menu')
I want to show some information in the layout, let's say the number of messages near the "message" link in the menu. I could easily do this by adding:
$message_count = Message::where("user_id", Auth::user()->id)->count();
and adding: <div>{{$message_count}}</div> to menu.blade.php
to every single controller and view where the layout is used, but this is clearly not a clean way to do it.
Is there a way to pass information to the view in a single step instead of having to do it in every single controller?
Use view composers.
View composers are callbacks or class methods that are called when a view is rendered. If you have data that you want to be bound to a view each time that view is rendered, a view composer can help you organize that logic into a single location
Register the view composer within a service provider:
public function boot()
{
View::composer('menu', function ($view) {
$view->with('messagesCount', auth()->user()->messages->count())
});
}
Then each time when the menu view will be rendered, it will have $messagesCount variable with counted messages for an authenticated user.

How to access session in blade before request

I have an admin template which I builded with blade templates,including one another.The user request is extending the main blade and returning only the content.
However in the template I have stuff like - user messages(count),theme options etc.
These things must be saved in the user session.Cookies are not an option.
The question is how to do it in the best possible option.
I'm thinking of gettind the request in middleware and accessing the session there.After that I must pass the data to the blade templates (not the final extending one).
Whats your opinion ?! Thanks!
If I understand correctly, you have a main layout blade template that is later extended by the user view returned by the controller.
No additional code like you described is needed. Both user and layout templates are processed after controller action is executed and both have access to user session via session() helper and user object via Auth::user().
So the following sample code should work for you :
// SomeController
public function someAction() {
return return response()->view('user');
}
// main.blade.php
#if (Auth::check())
Show this text only to authenticated users
#endif
Value of session parameter is {{ session('parameter_name') }}
// user.blade.php
#extends('main')

How to use a layout statically in Laravel?

As an admin I can create pages (don't think I have to paste my adminpagescontroller here, because you understand the logic). What I'm getting stuck on, is selecting, but especially using the layout that will be used for the page.
i.e. I have three layouts:
page with left sidebar
page with right sidebar
page with full-width (no sidebars)
And i.e. I want to create a salespage or so, which uses the layouts "page with full-width". How can I call this in my view?
Now all my views begin with #extends('layouts.path.file') <--- I need that to be filled in by the database, if you know what I mean.
One way of doing it is to use a view composer to define the current layout to be used. View composers set variables that can be used by all your views ('*') or just some ('users.profile', 'admin.profile'), so this is an example of using a user specific layout:
View::composer('*', function($view)
{
$view->with('userLayout', Auth::check() ? Auth::user()->layout : 'main');
});
And in your view you just have to:
#extends('layouts.'.$userLayout);
If you just need to select a page on your controller, you can pass a layout to it:
return View::make('myview')->with('layout', 'front.main');
And use it in your view:
#extends('layouts.'.$layout);
And if you have it on a table, you can just pass it on:
$layout = Pages::first()->layout;
return View::make('myview')->with('layout', $layout);
Or do the same in your composer
View::composer('*', function($view)
{
$layout = Pages::first()->layout;
$view->with('layout', $layout);
});
A lot of people like to set the layout in controller too, so you could in your controller do:
public function showProfile()
{
$this->layout = Pages::first()->layout;
$this->layout->content = View::make('user.profile');
}
And your views doesn't have to #extend a layout anymore, because you are already telling them which layout to use.

How do i load a method in a master blade template?

i am using laravel's blade template and i have a master template for all my pages. In the master template i have a top bar and a sidebar. I want to load something in the sidebar. But i don't know how do it in a simpler way. Now i am calling that method (which i want in to display in my sidebar) in every controller i have like this:
View::make()->with('data_to_load_in_sidebar',$data_to_load_in_sidebar)
How can i load this only once, not every time i generate a view?
This is what view composers are for, any view that is loaded will automatically have it's composer run alongside providing the view with any extra data it may require.
View::composer(array('partials.sidebar'), function($view)
{
$news = News::all();
$view->with('news', $news);
});
I typically put this in my routes.php file in both L3 and L4.
In the view views\partials\sidebar.blade.php you now always have access to the variable $news that will contain all models from the News collection.
I would share top bar & sidebar data in constructor (prefferably in some BaseController's contructor, that other controllers extends).
public function __construct()
{
// if needed, call parent's contructor method as well
parent::__construct()
$data_to_load_in_sidebar = loadDataForSidebar();
View::share('data_to_load_in_sidebar',$data_to_load_in_sidebar)
}

Categories