Retrieving categories on every page - laravel

I have a main.blade.php which contains my layout. As part of this layout, I need to show the categories from the database.
I would like to avoid doing the Eloquent call in every single controller.
How can I retrieve all categories to show on main.blade.php regardless of the controller?

You can do it in the base controller or the view layout you have.
In the view it would be:
#foreach(Category::all() as $category
and for a base controller, it would be something like:
$this->layout->categories = Category::all();
Hope this helps!
http://laravel.com/docs/templates

It would be great to call single action in template right? :)
You can check this package (check out layout facade section). Hope it helps.

Related

Laravel view into another view

Just started learning Laravel not long ago and I've got a question about views.
I have a 2 view files (blade).
The one which shows the categories from database.
The other one is showing the results of as search in products.
I'd like to use them in the same view, in the first section would be the searcher area and the area below is where I would like to list the categories.
I tried a couple of things to make it work, but I'm not sure which is the right approach:
I made a function in a controller where I listed the categories and handled the search and sent that to the view, but i didn't like this approach because I'm handling two different logic in one function.
I tried to yield or #include the view file into the main view. I got an error, because the database query didn't happen that case. I think yield and include only available with static data.
So, I'm don't know how to handle that issue properly.
Can someone suggest me a solution for this problem?
Thanks the help in advance!
There can be several way.
You can try to fetch category data inside blade file.
So, for example, in category.blade, you can fetch category list from database.
Then it would be independent to other views file and controllers.
And you can include category.blade.php for example.
The second way, is to fetch category data via ajax.
In this case, you can not insert script in all pages of using category.
So, in this case, you can use template structure.
For example.
In template.blade.php
<!DOCTYPE html>
<html class="no-js css-menubar" lang="en">
#stack('style')
#include('admin.layouts.head')
#include('admin.layouts.header')
#include('admin.layouts.page')
#include('admin.layouts.footer')
#stack('script')
</html>
In page.blade.php
<div class="page">
#yield('page-content')
</div>
In individual page,
#extends('admin.layouts.template' ,['menu'=>'coach'])
#section('insert-css')
your custom css content here
#endsection
#section('page-content')
Your page content here
#endsection
You must get $categories just once and pass $categories to all views (or views that need to category or just pass it to categories.blade.php).
for this goal, I suggest that create a partial blade called categories.blade.php and show all cateogories in it and include it wherever necessary, but before before that go to app/Provider/AppServiceProvider.php and in boot() method get categories and share it in categories blade that you created it, like below :
public function boot() {
// pass to first param, address categories blade
View()->composer('categories', function ($view){
// set a name for variable that get it in categories view
$view->with(['categories'=>$categories]);
});
}
If you would like to know more about subscriptions, visit this link or Laravel docs

How can I use 2 models in a single view?

I'm currently working on a homepage where I am showing the 'latest hauls' and 'latest finds' they are both separate models ofcourse.
Currently I am only showing the 5 latest hauls since I use the HaulController#getWelcome Controller so I can access $haul->title etc.
How would I be able to also access $finds->title?
Thanks for the help!
You can share a model to a view by using it inside controller function -
View::share('subadmin', App\Models\SubAdmin::class);
You can call the model in your view like
{{ \App\Model::function() }}
So you can have {{ App\Model::orderBy('created_at', 'desc')->limit(5)->get() }}
You have a couple of options.
Option 1: A combined model and one view.
To do this create a new ViewModel and have LatestHauls and LatestFinds as properties on this model. You could set these properties in the controller.
On your view simply navigate down the viewmodel to the appropriate properties.
Option 2: Extend the above solution to use partial views. Create a partial view for each model. On the parent view call each partial view. This might be considered a better solution but option 1 will get you started.

How to make a laravel 5 view composer

I'm still learning Laravel and I'm working on a small project to help me understand better. In the project, I am in need of a global array, so that I may display it or its attributes on every view rendered. sort of on a notification bar, so that each page the user visits, he/she can see the number of notifications (which have been fetched in the background and are stored in the array).
I have done some research, and realized that I have to fetch and compile the array in a view composer I think. But everywhere I go, I cant seem to understand how to make a view composer.
I need to fetch the relevant rows from the database table, and make the resulting array available to each view rendered (I'm thinking attaching it somehow to my layouts/default.blade.php file.). Please help, any and all advice is greatly appreciated:)
You can now inject services on your view
More info here: https://laracasts.com/series/whats-new-in-laravel-5-1/episodes/2
You have to use Sub-Views of laravel blade. I guess your functionality is like a sidebar or like a top bar which will be rendered at every page.
//Your Controller pass data
class YOUR_CONTROLLER extends Controller {
public function index()
{
$data = YOUR_DATA;
return view('YOUR_VIEW_FILE', get_defined_vars());
}
}
//In Your View File
#extends('LAYOUTS_FILE')
#section('YOUR_SECTION')
#include('YOUR_SUB_VIEW_FOR_NOTIFICATION')//You need not pass any data passed all data will be available to this sub view.
#endsection
In your sub view
//Do what ever you want looping logic rendering HTML etc.
//In your layout file just yield or render the section that's it
#yield('YOUR_SECTION')
More explanation can be found Including Sub-Views

Dynamic layouts in CakePHP

Sorry about the question title, but I couldn't find a more appropriate way to phrase this.
I am currently building a CakePHP powered website and I'm not quite sure how to approach the following issue. The website looks something like the follwing mockup:
.
The greyed out areas are part of the layout, because their content does not change between views. In the sidebar, I have a collection of ads who are linked to several models. I need controller logic to determine the picture associated with an ad. Also, the ad list needs to be dynamic. Where should I put the logic for building the sidebar?
I've thought about:
putting the logic into the AppController (beforeFilter / afterFilter) - the problem is I can't use the controller logic I need (the other controllers inherit from AppController, I'm not sure how to use them there).
making a component - is it okay to build components that rely on controllers?
replicating the sidebar code in all controllers that render views - this seems kind of stupid to me.
What is the Cake way for this?
Update
After some reading and experimenting, I've gotten to refactoring most of it.
I obtained the best performance by moving the logic for building my ads in the model (eliminating the component that retrieved the pictures) and not using requestAction. It's almost three times faster and the code looks much better.
I've done something similar for data-driven navigation. I put my logic in AppController::beforeRender and haven't had any problems. I'm not sure I understand your concern related to controller inheritance. I retrieve my menus via:
$menus = $this->NavMenuItem->groupByMenu();
$this->set( compact( 'menus' ) );
I then created an element that renders the menu. It's executed by the layout via:
<?php echo $this->element( 'navigation', array( 'id' => 'secondary', 'menu' => $menus['SECONDARY'] ) ) ?>
If that doesn't help, maybe you can further explain your issue with controller inheritance in a comment.
I guess the answer is requestAction in case the results are cachable:
http://book.cakephp.org/view/434/requestAction
It can be done in this way:
Create an element that will help in layout of the Ad Block
Create one or more controller that will generate the data required for rendering of the block
Use requestAction for getting the data out of the models and into the element.
Check the cake book, there is an example of an element where data from Post Model is used to display top/latest 5 posts. Your requirement, I feel, is very similar to it.
Alex,
you're getting a SQL error because the build() function has to be in the Sidebar model, not controller. Also, you don't necessarily need to use $user = array('Sidebar'); you could calling Sidebar in all of your models with this:
$Sidebar = ClassRegistry::init('Sidebar'); and then $Sidebar->find();, $Sidebar->build(); etc.
Or, if you only need to call the build() function from the Sidebar model, you could do this:
$sidebar = ClassRegistry::init('Sidebar')->build();
$this->set('sidebar', $sidebar);
Cheers.

What is the best practice for displaying multiple views in Codeigniter?

I'm trying to determine the best practice for calling multiple views from the same method in a controller.
Is it preferable in the controller to make one view call, then have that view call all the views it needs, or call all the views you need in sequence in the controller?
Example:
function index(){
//set all data variables
//then send them to the view
$this->load->view($index_view, $data);
}
or
function index(){
//set variables
//then call each view
$this->load->view($header_view, $header_data);
$this->load->view($body_view, $body_data);
$this->load->view($footer_view, $footer_data);
The Codeigniter guide shows both ways, but does not seem to advise to the best practice...is there one?
I didn't like the way of including the header/footer within the view, and I didn't like loading the footer and header each time in every single Controller function.
To fix this, I extended the Controller class with my own view display function.
<?php
// in application/libraries/MY_Controller.php
class MY_Controller extends Controller {
function _displayPage($page, $data = array()) {
$this->view->load('header', $data);
$this->view->load($page, $data);
$this->view->load('footer', $data);
}
}
?>
// in application/controllers/home.php
<?php
class Home extends MY_Controller {
function index() {
$this->_displayPage('home/index', array('title' => 'Home'));
}
}
?>
Not sure if this is CodeIgniter "best practice" but it makes sense to me.
I don't think there is a definitive answer for that. Choose one and stick with it, it's important to be consistent.
Anyway, I'd prefer the second one.
I would say that the controller should only display one view. Then it's up to the view if it wants to show a header, footer, sidebar or whatever. The controller shouldn't have to care, its job is to get data from a model and hand it to a view. Not decide if the view should have a header and a footer.
Agree with Christian Davén: its view / display logic not data or business / logic. essentially its the same as using php includes for snippets like navigation, footer etc. you're just embedding markup.
This is expected behavior. Once variables are set they become available within the controller class and its view files. Sending an array in $this->load->view() is the same as sending an array directly to $this->load->vars() before calling the view file. This simplifies things for most people using multiple views in a controller. If you are using multiple view files in a single controller and want them to each have their own set of variables exclusively, you’ll need to manually clear out the $this->load->_ci_cached_vars array between view calls.
A code comment in the Loader class describes another situation showing why this is the desired default behavior:
You can either set variables using the dedicated $this->load_vars()
function or via the second parameter of this function. We'll merge
the two types and cache them so that views that are embedded within
other views can have access to these variables.

Resources