Laravel 4: Using flexible layouts within routes - php

I have an application without controllers and read about controller layouts in laravel 4 documentation and this other article too, but I don't know where to start for implement it within routes (version 4), how can I do that?
Error received: InvalidArgumentException, View [master] not found.
app/routes.php
<?php
View::name('layouts.master', 'layout');
$layout = View::of('layout');
Route::get('users/create', array('as' => 'users.create', function() use($layout) {
//#TODO: load view using 'layouts.master',
// desirable: append 'users.create' and 'users.menu' views to sidebar and content sections.
//return View::make('users.create');
return $layout->nest('content', 'master');
}));
?>
app/views/layouts/master.blade.php
<html>
<body>
#section('sidebar')
This is the master sidebar.
#show
<div class="container">
#yield('content')
</div>
</body>
</html>
app/views/users/create.blade.php
{{ Form::open() }}
{{ Form::text('name') }}
{{ Form::submit('submit') }}
{{ Form::close() }}
app/views/users/menu.blade.php
<!-- This is appended to the master sidebar -->
<p>Create user</p>
Update: I modified example code to clarify what I want to do. Check app/routes.php and its comments

The code in your routes file is trying to nest the master layout within itself, which isn't really what you want. You're getting the error because 'master' would look for app/views/master.blade.php. That's easily fixed by changing it to 'layouts.master', but I wouldn't like to think what might happen...
The root cause of the issue you're having is the difference between "yielding" views from a Blade template, and nesting them from a route. When you nest a route, you need to echo it rather than using the #yield tag.
// File: app/routes.php
View::name('layouts.master', 'layout');
$layout = View::of('layout');
Route::get('users/create', array('as' => 'users.create', function() use ($layout)
{
return $layout
->nest('content', 'users.create')
->nest('sidebar', 'users.menu');
}));
/*
|--------------------------------------------------------------------------
| View Composer
|--------------------------------------------------------------------------
|
| Code in this method will be applied to all views that use the master
| layout. We use that to our advantage by injecting an "empty" sidebar
| when none is set when returning the view. It will error otherwise.
|
*/
View::composer('layouts.master', function($view)
{
if (!array_key_exists('sidebar', $view->getData()))
{
$view->with('sidebar', '');
}
});
// File: app/views/layouts/master.blade.php
<html>
<body>
#section('sidebar')
This is the master sidebar
{{ $sidebar }}
#show
<div class="container">
{{ $content }}
</div>
</body>
</html>
Laravel's View composers are a powerful tool. If you have any data (eg logged-in user info) used by all views that share the same template(s), you can use the composers to save injecting the data every time you load the view.

You could also use the #parent tag to append content, assuming you;re using blade for templating. E.g. (in the view)
#section('sidebar')
#parent
<p>This is appended to the master sidebar.</p>
#stop

You don't need to use nesting views if you're using blade.
app/views/users/create.blade.php
You need to extend the master.blade
#extends('layouts.master')
#section('content')
// form stuff here
#stop
Now, all you need to do is call create.blade
return View::make('users.create')

Just throwing this out there as a possible solution using controller routing (whereas you can set the template from within the controller).
app/routes.php
Route::controller('something', 'SomethingController');
app/controllers/SomethingController.php
class SomethingController extends BaseController {
protected $layout = "templates.main"; // denotes views/templates/main.blade.php
public function getIndex() { // the "landing" page for "/something" or "/something/index"
$this->layout->content = View::make('something.index')->with("myVar", "Hello, world!"); // load in views/something/index.blade.php INTO main.blade.php
}
public function getTest() { // for "/something/test"
$this->layout->content = View::make('something.index')->nest("widget", "something.widget", array("myVar" => "Hello, World!"));
}
}
app/views/templates/main.blade.php
#include('templates.partials.header')
#yield('something')
#yield('content')
#include('templates.partials.footer')
app/views/something/widget.blade.php
I'm a widget. {{ $myVar }}
app/views/something/index.blade.php
#section('something')
I will go in the 'something' yield in main.blade.php
#stop
#section('content')
I will go in the 'content' yield in main.blade.php.
{{ $myVar }}
{{ $widget }}
#stop
?>
Now you can test http://myserver/something and http://myserver/something/test to see the differences. Note: not tested but as a rough example.

Related

How to clear a defined section in blade.php

I'm aware that Laravel-blade allows us to define sections of code, but I'm wondering if it's possible to clear, or redefine a section within the same file as where it's been defined.
For example, something like:
#section('scripts')
<script src="/example.js"></script>
#endsection
//something like
#section('scripts')
// nothing
#endsection
// now the 'scripts' stack is an empty block of code.
//print
{{ #yield('scripts') }}
I've figured out a way to do it, by simply using ob_start() in regular php instead.
#php
ob_start();
#endphp
// write blade code here
#php
$scripts = ob_get_contents();
ob_end_clean();
#endphp
//print
{!! $scripts !!}

OctoberCMS | access to static page property from component

There are some way to extract values from extra-fields of static pages into some component?
I need that to implement AJAX handlers...
I can load the static page content but, I need to get properties that was setted by user...
I need some example of code... I can load the static page content as a Partial
#noobhacks :)
public function onOpenHome()
{
$this->page['categories'] = Category::all();
return [
//'main' => $this->renderPartial('home'),
'main' => $this->renderPartial('../content/static-pages/index'),
'.home_categories' => $this->renderPartial('work_list_categories_post')
];
}
or as content:
[viewBag]
==
<main class="home_container" __color="{{ color }}">
<section class="box">
{% content '/static-pages/index.htm' %} <!-- <<<<------ -->
{{ content |raw }}
</section>
</main>
But I have no ideia how to access to property of colorpicker color
Component objects are available using their name (or alias). This means the value of "color" should be available via {{ viewBag.color }}.

NotFoundHttpException at new route Laravel 4

i see there are similar questions but dont find any clue of me problem.
I created a basic users system, to manage groups, permissions, users, etc. The basic routes like create, edit, delete, index are working.
Now im trying to add one more function to UserController, to manage the users groups in a simple view.
Route::group(array('prefix' => 'admin'), function()
{
Route::resource('groups', 'GroupController');
Route::resource('users', 'UserController');
});
The function in controller:
public function groups($id)
{
$user = Sentry::findUserByID($id);
$groups = $user->getGroups();
return View::make('users.show')
->with('groups', $groups);
}
And the users/groups.blade.php:
#extends('layouts.admin')
#section('content')
<header id="page-title">
<h1>User Groups</h1>
</header>
<!-- if there are creation errors, they will show here -->
{{ HTML::ul($errors->all()) }}
{{ Form::open(array('url' => 'admin/users/save_groups')) }}
<div class="form-group">
</div>
{{ Form::submit('Create!', array('class' => 'btn btn-primary')) }}
{{ Form::button('Cancel', array('class' => 'btn btn-danger')) }}
{{ Form::close() }}
#stop
I go to url "mysite/admin/users/2/groups", and im getting the NotFoundHttpException, i try many ways to make it works and dont know what is happening.
I assume it will works like "mysite/admin/users/2/edit", but if i test the show function, it only is "mysite/admin/users/2", dont need the show action to know is that function, maybe i missed something.
You have declared a route for "GroupsController". As per the documentation, this will only handle actions as defined in the table: "Actions Handled By Resource Controller"
Just by adding one more action it won't simply be extended by Laravel.
You should instead type:
Route::get('users/{id}/groups', 'UserController#groups');

Laravel - Check if #yield empty or not

Is it possible to check into a blade view if #yield have content or not?
I am trying to assign the page titles in the views:
#section("title", "hi world")
So I would like to check in the main layout view... something like:
<title> Sitename.com {{ #yield('title') ? ' - '.#yield('title') : '' }} </title>
For those looking on it now (2018+), you can use :
#hasSection('name')
#yield('name')
#endif
See : https://laravel.com/docs/5.6/blade#control-structures
In Laravel 5 we now have a hasSection method we can call on a View facade.
You can use View::hasSection to check if #yeild is empty or not:
<title>
#if(View::hasSection('title'))
#yield('title')
#else
Static Website Title Here
#endif
</title>
This conditional is checking if a section with the name of title was set in our view.
Tip: I see a lot of new artisans set up their title sections like this:
#section('title')
Your Title Here
#stop
but you can simplify this by just passing in a default value as the second argument:
#section('title', 'Your Title Here')
The hasSectionmethod was added April 15, 2015.
There is probably a prettier way to do this. But this does the trick.
#if (trim($__env->yieldContent('title')))
<h1>#yield('title')</h1>
#endif
Given from the docs:
#yield('section', 'Default Content');
Type in your main layout e.g. "app.blade.php", "main.blade.php", or "master.blade.php"
<title>{{ config('app.name') }} - #yield('title', 'Otherwise, DEFAULT here')</title>
And in the specific view page (blade file) type as follows:
#section('title')
My custom title for a specific page
#endsection
#hasSection('content')
#yield('content')
#else
\\Something else
#endif
see "Section Directives" in If Statements - Laravel docs
You can simply check if the section exists:
if (isset($__env->getSections()['title'])) {
#yield('title');
}
And you can even go a step further and pack this little piece of code into a Blade extension: http://laravel.com/docs/templates#extending-blade
Complete simple answer
<title> Sitename.com #hasSection('title') - #yield('title') #endif </title>
I have a similar problem with the solution:
#section('bar', '')
#hasSection('bar')
<div>#yield('bar')</div>
#endif
//Output
<div></div>
The result will be the empty <div></div>
Now, my suggestion, to fix this, is
#if (View::hasSection('bar') && !empty(View::yieldContent('bar')))
<div>#yield('bar')</div>
#endif
New in Laravel 7.x -- sectionMissing():
#hasSection('name')
#yield('name')
#else
#yield('alternative')
#endif
Check if section is missing:
#sectionMissing('name')
#yield('alternative')
#endif
#if (View::hasSection('my_section'))
<!--Do something-->
#endif
Use View::hasSection to check if a section is defined and View::getSection to get the section contents without using the #yield Blade directive.
<title>{{ View::hasSection('title') ? View::getSection('title') . ' - App Name' : 'App Name' }}</title>
I don't think you can, but you have options, like using a view composer to always provide a $title to your views:
View::composer('*', function($view)
{
$title = Config::get('app.title');
$view->with('title', $title ? " - $title" : '');
});
why not pass the title as a variable View::make('home')->with('title', 'Your Title') this will make your title available in $title
Can you not do:
layout.blade.php
<title> Sitename.com #section("title") Default #show </title>
And in subtemplate.blade.php:
#extends("layout")
#section("title") My new title #stop
The way to check is to not use the shortcut '#' but to use the long form: Section.
<?php
$title = Section::yield('title');
if(empty($title))
{
$title = 'EMPTY';
}
echo '<h1>' . $title . '</h1>';
?>
Building on Collin Jame's answer, if it is not obvious, I would recommend something like this:
<title>
{{ Config::get('site.title') }}
#if (trim($__env->yieldContent('title')))
- #yield('title')
#endif
</title>
Sometimes you have an enclosing code, which you only want to have included in that section is not empty. For this problem I just found this solution:
#if (filled(View::yieldContent('sub-title')))
<h2>#yield('sub-title')</h2>
#endif
The title H2 gets only displayed it the section really contains any value. Otherwise it won't be printed...

laravel form post issue

I am building a practice app with the Laravel framework I built a form in one of the views which is set to post to the same view itself but when I hit submit the form is posted however I do not get the desired output, I see the original view again.
Here is my view index.blade.php
#extends('master')
#section('container')
<div class="wrapper">
{{ Form::open(array('url' => '/', 'method' => 'post')) }}
{{ Form::text('url') }}
{{ Form::text('valid') }}
{{ Form::submit('shorten') }}
{{ Form::close() }}
</div><!-- /wrapper -->
#stop
and my routes.php
Route::get('/', function()
{
return View::make('index');
});
Route::post('/', function()
{
return 'successfull';
});
What I've tried so far
I tried changing the post to a different view and it worked.
However I want the form to post to the same view itself.
Instead of returning a string I tried to return make a view still it
didn't work.
What am I doing wrong?
addendum
I see that when the form is making the post request I am getting a 301 MOVED PERMANENTLY HEADER
{{ Form::open(array('url' => ' ', 'method' => 'post')) }}
Passing a space as the url has worked for me.
I think this post: Form submits as GET Laravel 4 is related to your problem. I think the problem as I undersood it is caused by end a form url with a / . I found this when having problems to using post to a ./ url in my form. There is also a bug at github that seems like it is related https://github.com/laravel/framework/issues/1804.
I know this is an old question but I found this thread having the same problem so hopefully someone else is helped by my answer.
You need to make sure that your form's method does NOT end in a / for it to be routed correctly. For example if you have the following route:
Route::post('form/process', function()
{
# code here ...
});
Then you need to have the following form definition:
<form action="/form/process" method="POST">
I hope that helps.
I have same problem with OSx + MAMP, initially I've resolved with Raul's solution:
{{ Form::open(array('url' => ' ', 'method' => 'post')) }}
but after consultation with my friend we have concluded that my problem was due to the fact
my lavarel project is avaliable by long local path, as:
http://localhost/custom/custom2/...
in this location the post/get method on root path ("/") not working correctly.
Lavarel to working correctly must be avaliable by "vhost", in this case the problem get/post method on root location "/" not exist.
My friend advised me to use http://www.vagrantup.com/
BYE
There is some helpfull information in the Laravel Docs. Check these out:
Resource Controllers (or RESTful Controllers)
Forms & HTML
Opening A Form
Routing
Named Routes
I recommend you read the Resource Controllers documentation as it makes form handling a lot easier.
Well, you just return the view, so nothing change. You should bind your route to a controller to do some logic and add data to your view, like this:
index.blade.php
#extends('master')
#section('container')
<div class="wrapper">
#if (isset($message))
<p>{{$message}}</p>
#endif
{{ Form::open(array('url' => '/', 'method' => 'post')) }}
{{ Form::text('url') }}
{{ Form::text('valid') }}
{{ Form::submit('shorten') }}
{{ Form::close() }}
</div><!-- /wrapper -->
#stop
Your routes
Routes::any('/', 'home#index');
You controller HomeController.php
public function index()
{
$data = array();
$url = Input::get('url');
if ($url)
$data['message'] = "foo";
return View::make('index', $data);
}
You can also modify your current routes without using a controller like this (use the new view file)
Route::get('/', function()
{
return View::make('index');
});
Route::post('/', function()
{
return View::make('index')->with('message', 'Foo');
});
The problem is with defualt slashed in Apache from 2.0.51 and heigher:
http://httpd.apache.org/docs/2.2/mod/mod_dir.html#directoryslash
The best solution if you do not want to change Apache config is to make the post in a different path:
GOOD:
Route::get('/',
['as' => 'wizard', 'uses' => 'WizardController#create']);
Route::post('wizard-post',
['as' => 'wizard_store', 'uses' => 'WizardController#store']);
NOT GOOD:
Route::get('/',
['as' => 'wizard', 'uses' => 'WizardController#create']);
Route::post('/',
['as' => 'wizard_store', 'uses' => 'WizardController#store']);

Categories