I am new to web development.I am using laravel for my app where i used blade templates for creating pages.I have a main blade in which my header and footer exist and i am using it as wrapper.I want all of other pages to be open in that without reloading that base template and when i open the page it extends the main wrapper with new view correctly but when i update that page's content with ajax content of that page doubles the footer that may be because #includes() that creates a new page within existing one but i want to fix that double content and footer.Please help!Here is the code of pages that i used to load within the main wrapper
#extends('wrappertemplate')
#section('content')
<div class="body-content">`
And the content is here
</div>
#stop
I would advise that unless it's a very simple use case/playground exercise, that you don't do it this way, and instead define a proper API using Laravel, then use a front end framework like React, Angular, Ember etc etc. to interact with this API and handle DOM manipulation/creation. Seems v bizarre to re-render the entire page using HTML loaded of Ajax. There are plenty of tutorials on using Laravel and Various Front End Frameworks
However, for what you asked, you need to first create a page that extends wrappertemplate which you have. This should load without any content in the body
Then create a blade file which has the html that you want - it shouldn't extend anything. Then you just have a route and controller method which returns the contents of this file.
Then all you have to do is get your HTML over ajax and append it to the body.
This is just a sample controller:
class PageController extends Controller
{
// This is your method which renders the page that is essentially a wrapper
public function home()
{
return view('pages.home');
}
// This is your route which returns a partial, i.e. the content which gets refreshed
public function content()
{
$html = view('partials.home-content')->with(['name'=>'ExoticChimp'])->render();
return response->json(['html' => $html]);
}
}
Then your views:
<!--pages.home-->
#extends('wrappertemplate')
#section('content')
<div class="body-content">`
And the content is here
</div>
#stop
<!--partials.home-content-->
<h1>Hello {{$name}}</h1>
Then you'd just append the html parameter in the response to your body-content using basic jquery or js. I'm not going to write the JS as well, just google making AJAX requests using jQuery and there are a ton of articles on this stuff. I must stress though that you should look into using Laravel + a front end framework.
Tutorial: http://culttt.com/2015/04/06/getting-started-with-laravel-and-ember/
You should read up on the Laravel documentation for controllers.
http://laravel.com/docs/5.1/controllers
Related
I am working on Laravel for the first time
i have to make a Front End Menu Dynamic in Header and Footer [ list of categories will come from database ]. which controller I have to use for this.?
any common controller available in this framework to send data to header and footer.
When I receive the data in HomeController index Action its available for the home page only.
class HomeController {
public function index()
{
$categories = Category::get();
return view('home', compact('categories'));
}
}
Thanks.
This is a perfect case for 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.
You may attach a view composer to multiple views at once by passing an array of views as the first argument to the composer method:
View::composer(['partials.header', 'partials.footer'], function ($view) {
$view->with('categories', [1, 2, 3]); // bind data to view
});
Now you could simply retrieve $categories within your view (blade template).
Tip: Common practice is to create a new service provider called ComposerServiceProvider and place the abovementioned composer logic in the boot() method.
I assume you are using the Header and Footer in a master layout file. In this case you need to send all header/footer info every request. Which would be silly so instead use View Composers:
Define them in your appServiceProvider in the boot() method
view()->composer('home', function($view) {
$view->with('categories', App\Category::all());
});
In my example i made 'home' the name of the view, since it is in your example. But i would make a master file called layout and include a header and footer partial. If you want categories inside your header you could make a view()->composer('layout.header') with only header data.
which controller I have to use for this.?
Any
any common controller available in this framework to send data to header and footer
No.
You control what is returned from the Controller to be the response. You can design layouts and break them up into sections and have views that extend them. If you setup a layout that has the header and footer and your views extend from it, you can use a View Composer to pass data to that layout when it is rendered so you don't have to do this every time you need to return a view yourself.
Laravel Docs 5.5 - Front End - Blade
Laravel Docs 5.5 - Views - View Composers
In case of this u can use components
https://laravel.com/docs/8.x/blade#components
php artisan make:component Header
View/Component.Header.php
public function render()
{
$category = [Waht you want];
return view('views.header', ['category'=>$category]);
}
Then include Header.php to your blade like this
views/front.blade.php
<html>
<body>
<x-header/> <!-- like this -->
#yield('content')
#include('footer')
<body>
First, I want to say that it's the first time for me working
with a PHP Framework and MVC and I have not found all the answers to my problems yet. I'm using Laravel 5.3 at the moment.
Problem:
I have a website where a User can login and a few pages (I'm using Laravel Auth) and on a lot of pages I have a sidebar which is every time the same. Then I have on every page some content which is different (about, articles, ...). I heard that the most important thing is that you should never write code twice and there is the problem. On this sidebar there is a "service" which show content to the user but to show this I have an algorithm which needs the user data from the authenticated user and the Auth function is not available in Laravel 5.3 ServiceProvider or BaseController and was never meant to be.
My question now is how can I do that cleanly?
Some codes to understand it better:
Routes:
Route::get('/community/ranking', 'Pages\RankingController#getView');
Route::get('/community/advertising', 'Pages\AdvertisingController#getView');
Route::get('/logout', 'PagesController#doLogout');
Route::get('/home', 'Pages\HomeController#getView');
Then I have for every page an own controller which serves the content for this page (except of the sidebar - no solution yet).
HomeController:
<?php
namespace App\Http\Controllers\Pages;
use App\Http\Controllers\BaseController;
use Redis;
use App\Http\Requests;
use Request;
use Shoutbox;
use User;
class HomeController extends BaseController
{
function getView()
{
$shoutboxData = $this->getShoutboxData();
return view('pages.home', compact('shoutboxData'));
}
private function getShoutboxData()
{
$shoutbox = Shoutbox::orderBy('time', 'DESC')->skip(0)->take(15)->get();
if(count($shoutbox) > 0)
{
foreach($shoutbox as $entry)
{
$getUser = User::where('id', '=', $entry->user_id)->first();
$entry['username'] = $getUser->username;
$entry['look'] = $getUser->look;
$shoutboxData[] = $entry;
}
}
else
{
$shoutboxData = null;
}
return $shoutboxData;
}
public function systemMessage()
{
$redis = Redis::connection();
$redis->publish('chat.message', json_encode([
'msg' => 'System message',
'nickname' => 'System',
'system' => true,
]));
}
}
Now I serve the view in each, own controller and the content of this page (for example shoutbox, news) is also in that controller. (Not very clean in my opinion but didnt find any better way. Something I can improve here?).
I can serve the sidebar content on every Controller but this is not what I want. How can I do that? Am I using MVC right?
Thanks in advance!
Because you're using the Laravel Blade template system you can split your view logic out into separate blade files.
Your sidebar is common to every page so put this in your layout file (resources/views/layouts/app.blade.php) put the logic before
<div class="container" id="app">
#yield('content')
</div>
Now in your blade files for each individual page just extend the layout template you just created:
#extends('layouts.app')
#section('content')
<h1>page content goes here</h1>
#endsection
Now everyone of your blade files which extend the layouts.app will have the sidebar logic in them.
EDIT: With the extra information provided.... do as I said above but also create a view composer, you can find the full documentation here: https://laravel.com/docs/5.3/views#view-composers
Create a view composer for your main layout (or sidebar layout if you're going to be extending layouts instead) and pass your data within the view composer, the documentation gives good examples so just modify that for your own sidebar.
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
I'm using laravel with controllers layout. But there are some parts of my app where I don't want to use a layout (for example, when returning data to the payment gateway request, for wich I send XML data). I just want to pass data to my view and render it alone, with no need for a layout.
How can I do that? I've been trying some approaches but none worked for this. I can successfuly change what layout to render, but I can't set to render the view without a layout.
Thanks!
Edit: Let me explain it better
My default layout is set in Base_Controller. Then all my controllers extends it but in one of them I need no layout, as I told above. Maybe I need to unset the default layout or something like that, I'm not sure.
You can simply return something from your controller action to bypass the layout.
function get_xml($id) {
$user = User::find($id);
return View::make('user.xml', $user);
}
On your controller functions, you can simply return a string, which will be thrown back to the browser as-is. Alternatively, you can craft a Laravel\Response object, which will allow you to fine-tune your site's output a lot more than just returning a string.
The Response class has a few tricks up its sleeve that are not mentioned on the docs: default return, JSON, forced download.
You're more interested in the first one, which will allow you to correctly set the content-type of the response to application/xml. In addition to this, you can still use views for XML! Generate the view as you would with View::make, but instead of directly returning it, store it in a variable. To render it, call render() on it - it will return the output.
A simple way....
suppose there is a main layout
<body>
#yield('content')
</body>
This content will be where the view will be inserted.
Now,
if you want to use layout, Make the view page like this:
#layout('main')
#section('content')
blah blah your content
#endsection
If you don't want to use layout, omit the codes above.
In controller, the code will be same for both the files.
return View::make('index');
Attempting to learn CI and going through the docs to get a better understanding. Without getting a separate library, I could make a template by including a list of views like so:
$this->load->view('header');
$this->load->view('navigation');
$this->load->view('sidenav_open');
$this->load->view('blocks/userinfo');
$this->load->view('blocks/stats');
$this->load->view('sidenav_close');
$this->load->view('content',$data);
$this->load->view('footer');
This makes sense but would I actually have that on each of my controllers (pages)? Not sure if there is a way to include this in the initial controller (welcome) and then in the others somehow reference it? Or perhaps there is something I am missing completely
You can load views from within a view file. for example, consider a generic page template called page_template.php:
<html>
<body>
<div id = "header">
<?php $this->load->view('header');?>
<?php $this->load->veiw('navigation');?>
</div>
<div id = "sidenav">
<?php $this->load->view('sidenav');?>
</div>
<div id = "content">
<?php echo $content;?>
</div>
<div id = "footer">
<?php $this->load->view('footer');?>
</body>
</html>
Load your more dynamic areas by making use of codeigniter's abiltiy to return a view as a variable in your controller:
$template['content'] = $this->load->view('content',$data,TRUE);
$this->load->view('page_template',$template);
By passing TRUE to the load function, CI will return the data from the view rather than output to the screen.
Your sidenav section could be it's own view file, sidenav.php, where you have your 'blocks' hard-coded or loaded similar to the above example.
I've done it both ways, including every stinking bit of views in each controller method, and by using a page template that loads sub-views and dynamic areas, and by far, the second method makes me happier.
Loading views from within views can lead to confusion.
Extending the Controller class hides much of the complexity that comes from that approach, but still utilises the idea of generating common views (footer, header, navigation bars, etc) by rendering them once on every page load.
Specifically, consult the CI User Guide and wiki for references to MY_Controller - you extend this by creating a MY_Controller.php file in the ./libraries directory.
In there you can call view fragments, also utilising the third-parameter=true feature of the load->view() call. You load these into $this->data - for example loading the footer into $this->data['footer']. In your various controllers, continue adding view data to $this->data. In your views - I typically use a template that does little other than skeleton HTML and some basic CSS, and then echos the entire header, footer, nav and main content lumps as variables taken from $this->data
Added bonus - if you're new to CI, you'll likely soon be looking for how to do other things that a MY_Controller will make easy for you :)
I've got a wiki page on simplifying the generation and display of view partials, as you're trying to do here, using MY_Controller at:
https://github.com/EllisLab/CodeIgniter/wiki/Header-and-Footer-and-Menu-on-every-page---jedd