Laravel 4 - Extending the layout using blade templating - laravel

I have just setup my Laravel 4.2 application and am following some online tutorials about authentication.
The tutorials are telling me to add
protected $layout = "layouts.main";
and then when calling a view, call it like so
$this->layout->content = View::make('users.register');
But, if im following the Laravel website in creating my templates, it tells me to add
#extends('layouts.main')
At the beginning of my users/register view
Do i need to bother about the 2 bits of code i added at the beginning if im using that #extends call?
Im really confused.
Cheers

No, docs don't say you should do that.
You either do define controller layout (a), or return the view which extends layout (b)
A: Controller layout
/**
* The layout that should be used for responses.
*/
protected $layout = 'layouts.master';
/**
* Show the user profile.
*/
public function showProfile()
{
$this->layout->content = View::make('user.profile');
}
B: View extending layout view
// app/views/layout/master.blade.php
<html>
<head>
<title></title>
</head>
<body>
<header>
#yield('header')
</header>
<section>
#yield('content')
</section>
<footer>
#yield('footer')
</footer>
</body>
</html>
// app/views/profile.blade.php
#extends('layout/master')
#section('header')
Header content here
#stop
#section('content')
Master content here
#if (Auth::user()->isAdmin)
#include('admin-panel')
#endif
#stop
#section('footer')
Footer content here
#stop
// Controller
/**
* Show the user profile.
*/
public function showProfile()
{
return View::make('profile');
}

Related

How to create a new page layout in Laravel/Livewire

This is a complete new application using Laravel 9 and Livewire
By default you have two layouts, guest and app. I want to create a new layout for all my admin things.
So, first I create a component
php artisan make:component AdminLayout
This creates \app\View\Components\AdminLayout.php, it read as:
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class AdminLayout extends Component {
public function render() { return view('layouts.admin'); }
}
As any of the other two AdminLayout.php or GuestLayout.php
So now I write app\resources\views\layouts\admin.blade.php which is a stantandard HTML with the {{ $slot }} blade directive, something as...
<html>
<head>
...
<title>Admin Page</title>
...
#livewireStyles
#vite([...])
</head>
<body>
<main class="...">
{{ $slot }}
</main>
#livewireScripts
</body>
</html>
Then I create the admin routes... The Index class is in \app\Livewire\Admin\Index.php and it is correctly imported
Route::get('', Index::class)->name('home');
The Index.php reads as
class Index extends Component {
public function render() { return view('livewire.admin.index'); }
}
The \app\resources\views\livewire\admin\index.blade.php reads:
<x-admin-layout>
Hello
</x-admin-layout>
So everything seems to be right... now I have two problems that I can't spot/solve. When I load the http:://server.test/admin it should load this page. 1) It doesn't change the title in the page for Admin Page, 2) It always loads the #livewire('navigation-menu'), and looks like the followin picture:
If I add things above the {{ $slot }} or below, they are rendered. If I add another #livewire('navigation-menu') it is rendered. But I'm not able to take it out, even when I'm not telling to display it.
Any idea?
I just noticed that if I add a comment in the guest layout or the admin layout, it simply ignores it. If I add a comment in the app layout it somehow "propagates" to both the guest and admin layout. Is this the expected behaivour?

What is the proper way of setting the page meta title in laravel

In many examples and documents I generally see that the page title is set via someController->main.blade.php->somePage.blade.php. Something like:
SomeController.php
public function someAction()
{
$title = 'Some Title';
return view('somePage', ['title'=>$title]);
}
main.blade.php
<head>
<title> #section('title') | Page #show </title>
...
somePage.blade.php
#section ('title')
{{$title}} #parent
#endsection
Wouldn't it be mode convenient to set it directly/only over the controller and blade layout file? I mean something like:
SomeController.php
public function someAction()
{
$title = 'Some Title';
return view('somePage', ['title'=>$title]);
}
main.blade.php
<head>
<title>{{ $title }}</title>
...
Wouldn't it be better to use it in that way?
I prefer not to assign the title from the controller - it's content and should be in the template from my point of view. I like to have a section in the template like
//layout file
<title> FancyApp - #yield('title')</title>
// Template
#section('title', 'Page Title')

Laravel 4 pages

I have a question. How could I create subpages (something like this: character.php?name=Xar) but I want it in Laravel. Do I have to create routes? Also to mention, when I create a route like this:
Route::get('account/test', 'HomeController#test');
and the view is in folder under views/aac/test, and the function is like:
public function test()
{
return View::make('aac.test');
}
it won't load the CSS. it's just an HTML page.
back to the problem again, how could I create sites like that? I'm also using Blade templating engine.
// app/routes.php
Route::get('characters', 'CharactersController#all');
Route::get('characters/{name}', 'CharactersController#detail');
// app/controllers/CharactersController.php
class CharactersController extends BaseController
{
public function all()
{
// show all characters
}
public function detail($name)
{
// find character by name & show detail for example
return View::make('acc.test');
}
}
// app/views/acc/test.blade.php
// HTML::style('css/style.css') loads CSS file located at public/css/style.css
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
{{ HTML::style('css/style.css') }}
</head>
<body>
</body>
</html>
Search function
Place search form somewhere in your view file
<form action="{{ URL::action('CharactersController#search') }}" method="get">
<input type="text" name="search-term">
<input type="submit" value="Search">
</form>
As specified, search form is submited to CharactersController and its search method.
Controller's method
public function search()
{
$name = Inpute::get('search-term');
$searchResult = Character::where('name', '=', $name)->get();
....
}
Register new route
Route::get('characters/search', 'CharactersController#search');

Attempting to access View from blade template causes blank body in Laravel4

I have a project which is using laravel4 and its blade view engine. Occasionally I have had the need to call controller methods via a view file to output dynamic data; incidentally this time its a call to a method that generates javascript code for the page. Regardless of whether this is the best way to go about things is a moot point atm as I am simply upgrading from L3 to L4.
My View is similar to:
#extends('en/frontend/layouts/default')
{{-- Page title --}}
#section('title')
Page Title
#parent
#stop
{{-- Page content --}}
#section('pageContent')
...
#stop
{{-- Scripts --}}
#section('scripts')
<?php echo CaseStudy::script(); ?>
#stop
I have set up CaseStudy to load via the laravel facades and the class at current is simply:
class CaseStudy
{
public function display()
{
}
/**
* Returns the javascript needed to produce the case study
* interactivity
*
* #return \Illuminate\View\View|void
*/
public function script()
{
$language = \Config::get('app.locale');
$scriptElementView = $language . '.frontend.elements.casestudy_script';
if ( ! \View::exists($scriptElementView))
{
$scriptElementView = "Training::" . $scriptElementView;
}
return \View::make($scriptElementView, array());
}
}
It would appear that echoing the response of CaseStudy::script is what is causing the blank body; however with no further error message I do not know what is going on. I assume that this is because my static CaseStudy's instance of View is conflicting with the instance being used by the blade engine. How would I go about having CaseStudy::script() returning a string form of the rendered view?
Thank you.
In your view
{{-- Scripts --}}
#section('scripts')
{{ CaseStudy::script() }}
#stop
In your library
class CaseStudy
{
public function script()
{
$string = "your script here";
return $string;
}
}
Note - CaseStudy should really be a "library" or "helper" or something. Not a controller - that does not really conform to MVC approach.

Laravel 4 content yielded before layout

I am using a fresh build today of Laravel 4.
I have a dashboardController
class DashboardController extends BaseController {
protected $layout = 'layouts.dashboard';
public function index()
{
$this->layout->content = View::make('dashboard.default');
}
}
I have a simple route
Route::get('/', 'DashboardController#index');
I have a blade layout in views/layouts/dashboard.blade.php
For the sake of saving everyone from all of the actual HTML ill use a mock up.
<html>
<head>
<title></title>
</head>
<body>
#yield('content')
</body>
</html>
I have a default blade file in views/dashboard/ that has the following (edited for simplicity)
#section('content')
<p>This is not rocket science</p>
#stop
For some reason the content gets generated before the layout.
I am using a different approach to set the layouts globally to routes using a custom filter. Put the following filter into the app/filters.php
Route::filter('theme', function($route, $request, $response, $layout='layouts.default')
{
// Redirects have no content and errors should handle their own layout.
if ($response->getStatusCode() > 300) return;
//get original view object
$view = $response->getOriginalContent();
//we will render the view nested to the layout
$content = View::make($layout)->nest('_content',$view->getName(), $view->getData())->render();
$response->setContent($content);
});
and now instead of setting layout property in the controller class, you can group the routes and apply the filter as shown below.
Route::group(array('after' => 'theme:layouts.dashboard'), function()
{
Route::get('/admin', 'DashboardController#getIndex');
Route::get('/admin/dashboard', function(){ return View::make('dashboard.default'); });
});
When creating the views, make sure to use the #section('sectionName') in all the sub views and use #yield('sectionName') in the layout views.
I find it easier to do my layout like this for example. I would create my master blade file like so
<html>
<body>
#yield('content');
</body>
</html
And in the blade files that I want to use the master at the top i would put
#extends('master')
then content like so
#section('content')
// content
#stop
Hope this helps.
When you use controller layouts, i.e. $this->layout->..., then you get access to data as variables, not sections. So to access content in your layout you should use...
<html>
<head>
<title></title>
</head>
<body>
<?php echo $content; ?>
</body>
</html>
And in your partial, you would not use #section or #stop...
<p>This is not rocket science</p>

Resources