I have a Blade template that I would like to use from multiple Controllers, as although the DB table is different, everything else is the same.
For example, I have the following line in the template:
<li>View All Manufacturers</li>
I would like to make this dynamic, so I can improve so that it is:
<li>View All {{ name }}</li>
But how do I also apply this to the first part?
You have to extend the blade for this.
create a custom directive for this.
in your AppServiceProvider
public function boot()
{
Blade::directive('myDirective', function ($expression) {
return "<li>View All ". ucfirst($expression)."</li>";
}
And now in your view you can use
#myDirective('manufacturer')
it will return your desired input.
Related
I've been trying to define a variable globally into my project (laravel 7). I need this variable be available in all views but i am getting following error:
$count is undefined
Make the variable optional in the blade template. Replace {{ $count }} with {{ $count ?? '' }}
First step i created a new service provider TestSeriviceProvider
Second step I added following line to congif\app.php
App\Providers\TestServiceProvider::class,
Then i wrote following codes into boot method of TestServiceProvider
public function boot()
{
View::composer('*', function ($view) {
$view->with('count', 333);
});
}
Which part have i made mistake?
This can be done in the boot() method of the AppServiceProvider.
Just add view()->share('count', 333); and your $count is accessible on any blade page. If you have many shared data implemented, yes you can make a separate ServiceProvider for this. But keep in mind that your shared data may be overwritten in controllers.
Depending on the reason why you want to do this, you can look into a combination of middleware and the session() helper or combine shared variables in an array.
initially, I created the static navigation bar but now I want to improve navigation bar as Dynamically.
in there im try function inside the Controller but it was not success because that view manage only one route.i need to that view in every pages of my web.
SideMenuController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\admins;
use DB;
class SideMenuController extends Controller {
public function index(){
$details = DB::SELECT("SELECT Name FROM admins");
return view('layout', compact('details'));
}
}
web.php:
Route::get('/user/test','SideMenuController#index');
test.blade.php :
Order
#foreach($details as $value)
{{ $value->Name }}
#endforeach
Error Exception
(3/3) ErrorException Undefined variable: details (View:
C:\xampp\htdocs\ERP\ERP_LAR\resources\views\test.blade.php) (View:
C:\xampp\htdocs\ERP\ERP_LAR\resources\views\test.blade.php)
For first take a look at the blade engine that is in Laravel.
The idea is that you will create a value in an controller and past this to the view. Here you will extract the value and place the right value to the right place. With blade you can even make a separate navigation.php and yield them in every view you need it.
There are many ways to solve the problem.
You can make a separate php file in your project like "navbar.php" and include it in by <?php include('navbar.php'); ?>
you can also use classes but it is harder.
I have a database table called random_img. Inside are 10 rows for 10 images.
I will be pulling the images from public/images/random
I want to use the database so I can set the loop to Random take(1). I want to use in my hero images. (New image on every page refresh)
Where would I put my database query so I can use it Globally? Or how can I use my RandomImgsController so it is being used globally?
I created a route file, so I can use it as an include where needed.
Route:
Route::post('/layouts/inc/random-img','RandomImgsController#randomimg')->name('random-img');
Include:
#include('layouts.inc.random-img')
Inside Include:
#foreach ($randomimg as $rand)
<span class="hero-image">
<img src="/images/random/{{$rand->file_name}}" class="img--max--hero blur-img">
</span>
#endforeach
RandomImgsController: (Where should this go so I can use globally)
public function randomimg()
{
$randomimg = DB::table('randomimg')->orderBy(DB::raw('RAND()'))->get();
return view('random-img',compact('randomimg'));
}}
This is what I want to achieve on every page of my website:
#php
$randomimg = DB::table('randomimg')->orderBy(DB::raw('RAND()'))->get()->take(1);
#endphp
#foreach ($randomimg as $rand)
<span class="hero-image">
<img src="/images/random/{{$rand->file_name}}" class="img--max--hero blur-img">
</span>
#endforeach
What would be a cleaner way to do this?
Update:
I can access the images DB in all views now, but I have an issue.
In my App\Http\ViewComposer\ImageComposer.php file I have this:
public function compose(View $view)
{
$view->with('foo', Image::inRandomOrder()->get()->take(1));
}
In any view I can use {{$foo}} to get a random row from my images table, but the data comes in a string like this:
[{"id":10,"alt":"Image Alt Tag","title":"Image Title","file_name":"10.jpg"}]
When I try to only grab individual columns like this {{$foo->file_name}}
I get the error:
Property [file_name] does not exist on this collection instance.
How can I grab individual columns like this: {{$foo->alt}} , {{$foo->title}} and {{$foo->file_name}} then cleanly output them in my view? Example, I need {{$foo->file_name}} to render like this: 5.jpg.
Update 2:
I figured it out. Have to use #foreach since I'm using the get() method.
#foreach($foo as $f)
{{$f->file_name}}
#endforeach
Would still like to know if there is a way to do it without the get() method. This will work though.
First of all you can't #include a route in a blade template. What you would actually do is send an AJAX request from your blade template to the route you created to retrieve the random images. However...
It sounds like a controller is the wrong place for the logic in this situation.
Assuming you have an associated Eloquent model for your table, a simple option could be to define a method on your RandomImage model (could probably just be called Image).
This way, you can just use your Image model to generate and pass a random image to any view you would like. Then there is also no need to query for every image on each page reload. You would only ever be querying for one image per request.
Imagine if the code in your view could look like this:
<span class="hero-image">
<img
src="{{ $image->url() }}"
class="img--max--hero blur-img" />
</span>
And maybe this belongs in a home page for example, which is what it sounds like you're trying to do. So maybe you have a route like this:
Route::get('/', function () {
$image = App\Image::random();
return view('home', compact('image');
});
You could achieve this using a Query Scope on your Image model:
public function scopeRandom($query)
{
return $query->inRandomOrder()->first();
}
Edit
If you want this to be used across many, or even all views in your website you can use a View Composer: https://laravel.com/docs/5.6/views#view-composers
Your compose method would look like this:
public function compose(View $view)
{
$view->with('image', Image::random());
}
And the View Composer would be registered either in your AppServiceProvider or in a new provider such as ComposerServiceProvider. Inside of the boot method you need:
public function boot()
{
// Using class based composers...
View::composer(
'*', 'App\Http\ViewComposers\ImageComposer'
);
}
Where the * says that you want this composer to be applied to all views.
Here is my situation. I have a layout.blade.php which most of my pages use. Within this file, I have some partial pieces that I include, like #include('partials.header'). I am trying to use a controller to send data to my header.blade.php file, but I'm confused as to exactly how this will work since it is included in every view that extends layout.blade.php.
What I am trying to do is retrieve a record in my database of any Game that has a date of today's date, if it exists, and display the details using blade within the header.
How can I make this work?
I think to define those Game as globally shared is way to go.
In your AppServiceProvider boot method
public function boot()
{
view()->composer('partials.header', function ($view) {
view()->share('todayGames', \App\Game::whereDay('created_at', date('d')->get());
});
// or event view()->composer('*', Closure) to share $todayGames accross whole blade
}
Render your blade as usual, partial.header blade
#foreach ($todayGames as $game)
// dostuffs
#endforeach
In Laravel you can create a service class method that acts like a controller and use #inject directive to access this in your partial view. This means you do not need to create global variables in boot(), or pass variables into every controller, or pass through the base view layout.blade.php.
resources/views/header.blade.php:
#inject('gamesToday', 'App\Services\GamesTodayService')
#foreach ($gamesToday->getTodayGames() as $game)
// display game details
#endforeach
While it's different value you retrieved belong of the game chosen, you can do something like that:
Controller
$data = Game::select('id', 'name', 'published_date')->first();
return view('game')->with(compact('data'));
layout.blade.php
<html><head></head><body>
{{ $date }}
</body></html>
game.blade.php
#extend('layout')
#section('date', $data->date)
#section('content')
#endsection
The better solution would be this
Under your app folder make a class named yourClassNameFacade. Your class would look like this.
class yourClassNameFacade extends Facade
{
protected static function getFacadeAccessor()
{
return 'keyNameYouDecide';
}
}
Then go to the file app/Providers/AppServiceProvider.php and add to the register function
public function register()
{
$this->app->bind('keyNameYouDecide', function (){
//below your logic, in my case a call to the eloquent database model to retrieve all items.
//but you can return whatever you want and its available in your whole application.
return \App\MyEloquentClassName::all();
});
}
Then in your view or any other place you want it in your application you do this to reference it.
view is the following code:
{{ resolve('keyNameYouDecide') }}
if you want to check what is in it do this:
{{ ddd(resolve('keyNameYouDecide')) }}
anywhere else in your code you can just do:
resolve('keyNameYouDecide'))
I have setup a general layout for all my views - all fine.
Now, I would like to get some information from database to put in the header, which is part of the layout.
At the moment, the only way I can find out is something like:
// OneControler.php
static public function hello()
{
$data['hey'] = 'heeey';
return View::make('layouts.partial.nav', $data);
}
And from inside the layout:
// master.blade.php
...
{{ OneController::hello() }}
...
This works fine but... I think there must be another way? I don't think loading a controller from inside the view/layout is the best way to do this?
You can use View Composers to help you with this:
View::composer(array('your.first.view','your.second.view'), function($view)
{
$view->with('count', User::count());
});
Then in your view your.first.view or your.second.view, or even your layout you can just:
{{ $count }}
In the array of views, you put the name of the view:
View::composer(array('layouts.partial.nav') ...
or you can just set it to all views:
View::composer(array('*') ...
If you want to define a variable for all views you can also use share:
View::share('name', 'Steve');
In your view or layout:
{{ $name }}