I would like to know an appropriate way to provide information to a layout / master page.
A friend recommended adding this to App\Providers\AppServiceProvider.php
view()->composer('app', function($view) {
$view->with('stages', Stage::all());
});
This is working, but only on the homepage.
Here is how the data is used in the master page app.blade.php
<ul class="dropdown-menu" role="menu">
#if(isset($stages))
#foreach($stages as $stage)
<li>{{ $stage->name }}</li>
#endforeach
#endif
</ul>
Please assist, thank you.
Solution
use Illuminate\Support\ServiceProvider;
use View;
use App\Stage;
class AppServiceProvider extends ServiceProvider {
public function boot() {
View::share('stages', Stage::all());
}
.....
You gotta use View::share() if you want to have the data throughout all the views. Inside the AppService Provider just do:
View::share('stages', Stage::all());
Here you have the docs.
EDIT: to use the view facade, just add at the top of the file:
use View;
You can also use
view()->share()
Related
In laravel 8 how can i do login registration in same page , Problem is in both form email and password are same . valiadation error shows in both form .
Thanks in advance
If you want to have multiple forms with the same input names on one page you need to take a look at named error bags.
If you are using FormRequests, it's quite easy. You can set a custom ErrorBag on the specific FormRequest.
<?php
use Illuminate\Foundation\Http\FormRequest;
class LoginFormRequest extends FormRequest
{
protected $errorBag = 'loginForm';
}
<?php
use Illuminate\Foundation\Http\FormRequest;
class RegisterFormRequest extends FormRequest
{
protected $errorBag = 'registerForm';
}
Earlier you have been used to use something like this in your blade files:
<div>{{ $errors->first('email') }}</div>
This uses the default ErrorBag. But in our case, we have overwritten the bag with our custom ones. The syntax changes a little bit if you want to access them. Here's how.
<div>{{ $errors->loginForm->first('email') }}</div>
<div>{{ $errors->registerForm->first('email') }}</div>
Introduction
I'm using this Add-on for Visual Studio Code.
When creating relations with it. My views seem not working. I get an error in the browser (see below).
Laravel Snippets ID: onecentlin.laravel5-snippets Beschreibung:
Laravel snippets for Visual Studio Code (Support Laravel 5 and above)
Version: 1.13.0 Herausgeber: Winnie Lin Link zum Visual Studio
Marketplace: https://marketplace.visualstudio.com/items?itemName=onecentlin.laravel5-snippets
My Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Person extends Model
{
use HasFactory;
protected $fillable = [];
/**
* Get the phone associated with the Person
*
* #return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function phone(): HasOne
{
return $this->hasOne(Phone::class);
}
}
Error shown by the browser, when calling the view
TypeError Return value of App\Models\Person::phone() must be an instance of
App\Models\HasOne, instance of
Illuminate\Database\Eloquent\Relations\HasOne returned (View:
C:\Users\MusaSaglam\componenttest\resources\views\test\index.blade.php)
My view
<x-layout>
<main class="main" id="top">
<div class="container" data-layout="container">
<script>
var isFluid = JSON.parse(localStorage.getItem('isFluid'));
if (isFluid) {
var container = document.querySelector('[data-layout]');
container.classList.remove('container');
container.classList.add('container-fluid');
}
</script>
<x-nav.admin-nav/>
<div class="content">
<x-nav.admin-nav-top/>
<h1>People</h1>
#foreach ($people as $person)
<h2>{{ $person->id }}</h2>
<h2>{{ $person->phone->number }}</h2>
#endforeach
</div>
</div>
</main>
</x-layout>
But if I remove : HasOne after public function phone() in my model. Everything works fine.
Two questions
Why does the Snippet adds : HasOne. What is the benefit of this?
Does not make it easier for users like me using the snippet without : HasOne?
I'm a beginner and I could not understand why the tutorials did not work.
You can refer to the type declaration https://www.php.net/manual/en/language.types.declarations.php
Why does the Snippet add: HasOne. What is the benefit of this?
It’s the return type of method and it’s standard so the VS code add-on is giving you the snippet(code) which follows the industry standards.
Does not make it easier for users like me using the snippet without : HasOne? I'm a beginner and I could not understand why the tutorials did not work.
This snippet will work don’t worry about it. Just declare the HasOne before the class initialization like use Illuminate\Database\Eloquent\Relations\HasOne and it should work.
By the way type hinting is optional so a snippet will work if you just remove :HasOne(return type of method). which you already tried.
I've created file GlobalVariable.php inside app\Composers
public function compose($view)
{
$categories = \App\Models\Category::all();
$view->with('globCategory', $categories);
}
then register to AppServiceProvider the code view()->composer('*', GlobalVariable::class);
I use global $globCategory for creating dynamic navbar
<ul class="nav nav-tabs border-0 flex-column flex-lg-row">
#foreach ($globCategory as $item)
<li class="nav-item">
{{$item->name}}
</li>
#endforeach
</ul>
the only problem here when I see laravel debuggar it show repetition of categories query.
here is the result
How to avoid this looping query? is there correct way?
The way you're registering your view composer (using '*' instead of a particular view name), it's going to call the compose method for every single rendered view + subview.
What you can do is instead of this:
view()->composer('*', GlobalVariable::class);
Have this:
\View::share('globCategory', \App\Models\Category::all());
This will globally share your categories (within views), and run the query only once.
View composers, as described from the laravel documentation, bind data to a view every time it is rendered. They clean our code by getting fetching data once and passing it to the view.
While it is possible to get the data in every controller method and pass it to the single view, this approach may be undesirable.
Replace the view name with an asterisk wildcard.
I am using/learning Laravel 5.6 and wondered if this is the best approach in trying to accomplish dynamic pages from a database.
The approach I have taken works but I feel it could be improved especially with having to retrieve the pages for the navigation bar with every request.
I have a route in web.php
Route::get('/', 'PageController#index')->name('index');
Route::get('/{page}', 'PageController#show');
I then have my page controller with index and show functions.
public function index()
{
$pages = Page::all();
$posts = Post::latest('created_at')->paginate(2);
return view('index', compact('posts','pages'));
}
public function show($uri)
{
$pages = Page::all();
$page = Page::where('uri', $uri)->first();
return view('templates.page', compact('page','pages'));
}
Now in my header.blade.php I display the list of pages like this:
#foreach($pages as $page)
<li class="nav-item">
<a class="nav-link" href="/{{ $page->uri }}">{{ $page->title }}</a>
</li>
#endforeach
Now my problem is with all the other controllers I have to get the page's information from the database everytime which seems inefficient.
Any advice would be appreciated. Thank you in advance.
You can share your pages data with every view automatically by adding View::share('key', 'value');in the boot method of a service provider. Alternatively you can create a view composer.
one layout blade.
yield title by
<title>#yield('page-title')</title>
then on view,
//process title using php from DB
then display using
#section('page-title')
{{$page_title}}
#endsection
Hi I am very new to Laravel and MVC frameworks in general and am looking to create a list of links (in a view within a template) that links to some content. I am using this to display a list of nine people and to display their profile description when the link is clicked on. I have created a model of what the page looks like at http://i.imgur.com/8XhI2Ba.png. The portion that I am concerned with is in blue. Is there a way to route these links to something like /about/link2 or /about?link2 while maintaining the same exact page structure but modifying the ‘link content’ section (on the right of the link menu) to show the specific link's content? I would greatly appreciate it if someone could point me in the right direction, as I have literally no clue where to go with this!
There are a couple ways you can go about doing this.
Templates
Create your route.
Im assuming a lot about your app here but hopefully you get the picture. If you need help with anything in particular, be sure to update your question with the code youve tried so it will be easier to help you.
Route::get('about/{page}', function($page)
{
$profile = Profile::where('name', $page)->first();
return View::make('about')->with('profile', $profile);
});
Modify Template.blade.php
Put this line where you wish for About.blade.php to appear.
#yield('content')
Create your view which will extend your template
#extends('Template')
#section('content')
<h2>User Profile</h2>
<ul>
<li>Name: {{ $profile->name }}</li>
<li>Last Updated: {{ $profile->updated_at }}</li>
</ul>
#stop
AJAX
This solution will utilize AJAX to grab the data from the server and output it on the page.
Route for initial page view
Route::get('about', function($page)
{
$profiles = Profile::all();
return View::make('about')->with('profiles', $profiles);
});
Feel free to follow the same templating structure as before but this time we need to add some javascript into the template to handle the AJAX. Will also need to id everything which needs to be dynamically set so we can easily set it with jquery.
#extends('Template')
#section('content')
<h2>Links</h2>
#foreach($profiles as $profile)
{{ $profile->name }}
#endforeach
<h2>User Profile</h2>
<ul>
<li>Name: <span id="profile_name">{{ $profile->name }}</span></li>
<li>Last Updated: <span id="profile_updated_at">{{ $profile->updated_at }}</span></li>
</ul>
<script>
function setProfile(a)
{
$.ajax({
method: 'get',
url: 'getProfile',
dataType: 'json',
data: {
profile: $(a).data('id')
},
success: function(profile) {
$('#profile_name').html(profile.name);
$('#profile_updated_at').html(profile.updated_at);
},
error: function() {
alert('Error loading data.');
}
});
}
</script>
#stop
Route to handle the AJAX request
Route::get('getProfile', function()
{
$profile_id = Input::get('profile');
$profile = Profile::find($profile_id);
return $profile->toJson();
});
Now, the page should not have to reload and only the profile information should be updated.
Making some assumptions here as no code posted and assuming you're using the latest version of Laravel, Laravel 5.
Lets say you have a table in your database named users and you have a Model named Users (Laravel 5 comes with the Users model as default, see app/Users.php). The users will be the base of our data for the links.
Firstly, you want to register a route so you can access the page to view some information. You can do this in the routes file. The routes file can be found here: app/Http/routes.php.
To register a route add the following code:
Route::get('users', ['uses' => 'UserController#index']);
Now what this route does is whenever we hit the URL http://your-app-name/public/users (URL might be different depending on how you have your app set up, i.e. you may not have to include public) in our web browser it will respond by running the index method on the UserController.
To respond to that route you can set up your UserController as so:
<?php namespace App\Http\Controllers;
class UserController extends Controller {
public function index()
{
}
}
Controllers should be stored in app/Http/Controllers/.
Now lets flesh out the index method:
public function index()
{
// grab our users
$users = App\Users::all();
// return a view with the users data
return view('users.index')->with('users');
}
This grabs the users from the database and loads up a view passing the users data.
Here's what your view could look like:
<!DOCTYPE html>
<html>
<head>
<title>Users Page</title>
</head>
<body>
#foreach($users as $user)
<a href="{{ URL::route('user', ['id' => $user->id]) }}">
{{ $user->username }}
</a>
#endforeach
</body>
</html>
The view code will loop through each user from the $users data we passed to the view and create a link to their user page which is different for each user based on their id (their unique identifier in the DB)
Due to the way I've named it, this would be found in app/views/users/index.blade.php - if you save files ending in blade.php you can use Laravel's templating language, blade.
Now you need to finally set up another route to respond to a user page, for example http://your-app-name/public/user/22.
Route::get('user/{id}', ['uses' => 'UserController#show']);
Then add the show method to UserController
public function show($id)
{
// this will dump out the user information
return \App\User::find($id);
}
Hope that helps a little! Wrote most of it off the top of my head so let me know if you get any errors via comment.
This question is very bare, and it is difficult to actually help your situation without you showing any code. Just to point you in the right direction though, here is what you would need.
A Model called People, this is how you will access your data.
A controller. In this controller you will do the following
Get the ID of the profile you want from the functions parameters
Find that persons information e.g. People::find($person_id);
return the profile view with that persons data e.g. return view('profile')->with('person', $person);
In your view you can then use that data on that page e.g. {{ $person->name }}
For the page that needs to display the links to the people you would have a method in your controller which..
Get all the people data e.g. People::all();
Return a view with that data return view('all-people')->with('people', $people);
You will then need a route to access an individual person. The route will need to pass the persons ID into a controller method e.g.
Route::get('get-person/{id}',
[ 'as' => 'get-person',
'uses' => 'PeopleController#getPerson' ]);
You can then use this route in your view to get the links to each person
#foreach($people as $person)
{{$person->name}}
#endforeach
This would produce the list of links you want.