I have seen a few similar questions to mine, with the common answer being to use a view composer. I have a HomeController that shows articles from a database by passing query data to an associated view, which works see this image link
As you can see there is a nav bar, which is generated by the master layout, layout.master.
For each title in the navigation I am trying to show each article for that section via a for loop which generates the links.
My code is this.
public function index()
{
$loans_articles = Article::byDepartment('Loans')->get();
$digital_articles = Article::byDepartment('Digital')->get();
$consulting_articles = Article::byDepartment('Consulting')->get();
return view('welcome',
[
'loans_articles' => $loans_articles,
'digital_articles' => $digital_articles,
'consulting_articles' => $consulting_articles,
]);
}
As you can see I'm returning this data to the welcome blade.
In my nav bar I tried
#if(count($loans_articles) > 0)
#foreach($loans_articles as $ls)
<!--for each loop which grabs the articles with department Loans-->
<li>{{ $ls->title }}</li>
#endforeach
#endif
But as soon as you navigate away from the home page the nav bar doesn't know what $loans_article is.
Is there a clean way to pass this data to the master blade navigation without sending the same data to every subview?
The way I tend to achieve this is by making a variable available to every view in this way:
All of your controller should extend a base controller, which is usually located in app/Http/Controllers/Controller.php. Inside this controller you can put some code that will be used by all extending controllers.
In this base controller you can make a variable available to all views, like this...
class Controller extends BaseController
{
public function __construct()
{
// Load your objects
$loans_articles = Article::byDepartment('Loans')->get();
// Make it available to all views by sharing it
view()->share('loans_articles', $loans_articles);
}
}
All of your controllers must extend this controller for this to work.
If any of your controllers have their own constructors, you must also make sure to call parent::__construct() to ensure the above code is run. If your controllers don't have their own constructors, you can omit calling parent::__construct().
public class HomeController extends Controller
{
public function __construct()
{
parent::__construct();
// Your constructor code here..
}
}
This way you should be able to use $loans_articles in all of your views.
You must use View Composer to achieve what you are trying to do :
https://laravel.com/docs/5.2/views
if you would like to share data with all of your blade templates, a simple way is trough
appServiceProvider.php and boot method.
you can find this file in app/Providers/AppServideProvider.php and do the changes like bellow:
namespace App\Providers;
use Illuminate\Support\Facades\View;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
View::share('key', 'value');
}
}
after that you can access to the value in all blade files using {{ $key }}
note: do not forget to use Illuminate\Support\Facades\View in top of the class
<?php $contact = DB:table('tbl_contact')->get(); ?>
Use this code in master.blade.php in top section
And
Use such as
<a href='{{ $contact[0]->fbLink ? $contact[0]->fbLink : " " }}'>
Related
I've code in my controller which returns some $data, and I want to refer that in all my blades, I can make routes for each page, but I don't like this way. I thought should be better if I refer this $data on layout.blade which include navbar, and etc..., but is it a possible to make route without url? cause I don't want to appear my layout.blade, So my question is, what is a best way to get $data on each blade?
You may perhaps want a view composer. A view composer is an extension of a blade via php that runs before the blade.
In app service provider you set the view you want to view composer class.
use Illuminate\Support\Facades\View;
use App\Http\ViewComposers\LayoutComposer;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
View::composer('layout', LayoutComposer::class);
}
}
Then write your logic in the class.
use Illuminate\View\View;
class LayoutComposer
{
public function compose(View $view)
{
$data = Model::where('id',###)->first();
return $view->with(['data' => $data]);
}
}
https://laravel.com/docs/7.x/views#view-composers
I am new to laravel and need help. After login user, on the dashboard page I have partial sidebar blade template that shows the user's balance data that load from database. This must be loaded for every dashboard pages.
I can not imagine how to create a controller for this user' balance since every pages have their own routes and controller.
public function getBalance()
{
$userbalance = \App\UsersBalance::where('userid', '=', Auth::user()->id)->first();
$balance = $userbalance->balance;
return view(......);
}
Kenny's answer is good if you want to share the data with all pages. However, if you only want to share with user dashboard pages and not the entire website, you probably want to use view composers.
https://laravel.com/docs/5.8/views#view-composers
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
class AppServiceProvider extends ServiceProvider
{
// ...
public function boot()
{
// limit returning the balance to only your dashboard layout
view()->composer([
'layouts.dashboard'
], function($view) {
$userbalance = \App\UsersBalance::where('userid', '=', Auth::user()->id)->first();
view()->share('balance', $userbalance->balance);
});
}
}
This will pass the $balance variable to all pages that extend layouts.dashboard. You can change this layout name as necessary, or even add additional layouts since the view composer accepts an array.
You could share data with all your views. From the docs:
Sharing Data With All Views
Occasionally, you may need to share a piece of data with all views
that are rendered by your application. You may do so using the view
facade's share method. Typically, you should place calls to share
within a service provider's boot method. You are free to add them to
the AppServiceProvider or generate a separate service provider to
house them (...)
So, you could make your query there and then pass it to every view:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
class AppServiceProvider extends ServiceProvider
{
// ...
public function boot()
{
$loggedInUser = auth()->user();
View::share('loggedInUser', $loggedInUser);
}
}
So even tough your controller doesn't return this value:
# MyController.php
public funcion myFunction()
{
return view('my_view');
}
You could access the properties defined globally:
# my_view.blade.php
<span>{{ $loggedInUser->name }}</span>
Using Laravel 5.6, I'm trying to get the number of received links a logged-in user may have in my application.
public function getReceivedLinksCount() {
return $count = App\Link::where([
['recipient_id', Auth::id()],
['sender_id', '!=', Auth::id()]
])->count();
}
So far, so good. Question is not about that piece of code, but where I can use it. I'd like to display this counter on the navigation bar of the website (Facebook's style) which is in my header.blade.php which is included in every page.
I'd like to do it with a clean code, of course. It seems like I need to use View Composers but I'm not sure it's the right way to do it, and not sure on how the code is supposed to look.
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
view()->composer('layouts.header', function ($view) {
$view->with('variable_name', \App\Path-To-Your-Model::something());
});
}
You can share a value across all views by using View::share(), see docs
For example
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$linksCount = Link::getReceivedLinksCount();
View::share('linksCount', $linksCount);
}
...
}
This works well if you want to set the value everywhere. Personally, I would set the value in the constructor of a 'BaseController' that gets extended by other controllers. This makes the code more discoverable because most people would expect view values to be set in a controller. And it's also a bit more flexible if you plan on having a section of your app that doesn't require that value to be computed.
I am trying to create an application where i have a user activity log. I dont want to write a special function in all the pages. I just want to metnion it once and run on all the pages or controller where ever i go. Which keep showing on the header.blade.php. And i want to keep using that log all time.
I have a function with like this.
public function headerLogs()
{
$latestActivities = Activity::with('user')->latest()->limit(10)->get();
return view('layouts.header')->with('logs', $latestActivities);
}
How can i do that?
Laravel has built-in functionality for that: View Composers. They are what you use if you want some data to be in every view that is loaded (of course you specify which views exactly)
So from the docs we would create a service provider for our view composer:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ActivitiesComposerServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* #return void
*/
public function boot()
{
// Using Closure based composers...
view()->composer('layout.header.activity', function ($view) {
$latestActivities = Activity::with('user')->latest()->limit(10)->get();
$view->with('logs', $latestActivities);
});
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
//
}
}
And then you register your ActivitiesComposerServiceProvider service provider by simply adding it to the providers array in config/app.php.
So now you can simply #include('layout.header.activity') and the logs will show with no extra line of code in your controller or view
In your base controller:
view()->composer('layouts.header', function($view){
//your code for header logs which gives $logActivites.
$view->with('logs', $logActivites);
}
So, whenever your view layouts.header will be created, this $logActivites will be available.
Everyone had a situation when one variable had to be accessible in every view (blade) file. One possible solution – letting the service provider load our global view information. For Example, type this in your service provider.
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// Using view composer for specific view
view()->composer('welcome',function($view) {
$view->with('latestActivities', Activity::with('user')->latest()->limit(10)->get());
});
}
}
Then you can access the latestActivities variable from all you view files
Model: Comment.php
class Comment extends Eloquent {
protected $table = 'comments';
public $timestamps = true;
}
Controller: PageController.php
class PageController extends BaseController {
$top_comments = Comment::take(3)->get();
return View::make('page', array('top_comments' => $top_comments));
}
View: page.blade.php
#foreach ($top_comments as $comment)
user #{{ $comment->user_id }}:<br />
{{ $comment->comment}}
#endforeach
This works perfect with the page.blade.php view which I can define as a route (/page). However, I can't seem to figure out how to achieve this globally.
Example: I want to be able to use the #foreach containing $top_comments in my master.blade.php file. Right now if I was to use the above, it works great on /page but not on /, /about, /tos
You can use View::share('top_comments', Comment::take(3)->get()); to make it available everywhere. Of course, you'll have to place it some place where it gets loaded no matter what page you load if you want it in every possible view. (One such place would be in the __construct() method of your BaseController, but I doubt that could be considered a best practice. Not sure where I'd put it myself.)
Another way would be to leverage view composers, like this:
View::composer('master', function($view)
{
$view->with('top_comments', Comment::take(3)->get());
});
This works if you meant that you want it in your master.blade.php no matter from where it is loaded, because it's bound to that view. If you choose this option, I recommend for instance creating a file composers.php and including that in app/start/global.php.
That said, I assume your controller sample above left something out, because it looks like it's missing a method declaration.