#include a view with controller functionality - Laravel 5.4 - php

I am working on a profile page for my web application. Within this view profile.blade.php I would like to include the view progress/index.blade.php. I have the following structure:
profile.blade.php
<div class="panel panel-default">
<div class="panel-heading clearfix">
<h1 class="panel-title pull-left">{{ $user->name }} Progress</h1>
</div>
<div class="panel-body">
#include('client.progress.index')
</div>
</div>
web.php
Route::group(['middleware' => ['auth', 'client'], 'prefix' => 'client', 'as' => 'client.'], function () {
Route::get('home', 'Client\HomeController#index')->name('home');
Route::get('profile', 'Client\UserController#profile')->name('profile');
Route::get('progress', 'Client\UserController#progress')->name('progress.index');
});
UserController#progress
public function progress(){
$auth = Auth::user();
$progressPictures = Picture::select('*')
->where('user_id', $auth->id)
->get();
return view('client.progress.index', ['progressPictures' => $progressPictures]);
}
client.progress.index
<p>Progress pictures</p>
#foreach($progressPictures as $progressPicture)
<img src="/storage/uploads/progress/{{ $progressPicture }}" style="width:150px; height:150px; float:left; border-radius:50%; margin-right:25px;">
#endforeach
When I remove the php part from the index.blade.php, the site works. but when i add the foreach loop, $progressPictures is undefined. I am not calling the UserController#progress in some way. Could some one help me with this?

Generally based on my observation, the variable is not making it to the views because you are routing to another while the other view is handled by another controller.
One of the ways you can do that is either to have a trait where you can easily reuse the result of getting progressPictures or because you quickly need it, you might have to duplicate this code as well in the profile method in your UserController so that you can have the progressPictures also in profile page:
So you'll have:
public function profile()
{
//codes before or after
$auth = Auth::user();
$progressPictures = Picture::select('*')
->where('user_id', $auth->id)
->get();
//......
return view('profile', compact('progressPictures'));
Ps: unnecessary code repetition is not generally recommended, but I would do this first then clean up things after.

Change this to
return view('client.progress.index', ['progressPictures' => $progressPictures]);
to this
return view('client.progress.index')-> with('progressPictures', $progressPictures);

Change
#include('client.progress.index')
to
#include('client.progress.index', ['progressPictures' => $progressPictures])

Related

Undefined variable $credentials, tried several solutions but couldn't understand my mistake

I'm a beginner, learning Laravel. I was trying to create a web page which will show me my login Info(like email and password) once I log in. In my controller part I passed values using route parameter, but when I call it in blade, it shows
ErrorException
Undefined variable $credentials (View: .....\new project\NewLearn\resources\views\welcome.blade.php)
My database has users table( email and password columns (which will be shown only), along with name,id, timestamps).
my LoginController
public function loginProcess(Request $request)
{
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:4',
]);
$credentials = $request->except(['_token']);
if (auth()->attempt($credentials)) {
return redirect()->route('welcome', [$credentials->email]);
}
else{
$this->setErrorMessage('Invalid!');
return redirect()->back();
}
my routes
Route::get('/', function () {
return view('login');});
Route::view('/welcome', 'welcome')->middleware('auth')->name('welcome');
Route::post('/login', [App\Http\Controllers\LoginController::class, 'loginProcess'])->middleware('guest')->name('login');
Route::get('/login', [App\Http\Controllers\LoginController::class, 'loginProcess'])->middleware('guest');
my welcome.blade.php
#extends('master')
#section('contents')
#include('partials.jumbotron')
#stop
#section('content')
<h3 class="pb-3 mb-4 font-italic border-bottom">
{{$credentials->email}}
</h3>
<div class="blog-post">
<h2 class="blog-post-title">Sample blog post</h2>
</div>
<nav class="blog-pagination">
<a class="btn btn-outline-primary" href="#">Older</a>
<a class="btn btn-outline-secondary disabled" href="#">Newer</a>
</nav>
#stop
Where am I making the mistake? Thanks in advance.
You are making it pretty hard on yourself.
Let us start by changing
Route::view('/welcome', 'welcome')->middleware('auth')->name('welcome');
to
Route::get('/welcome', function() {
$user = auth()->user();
return view('welcome', compact('user'));
})->middleware('auth')->name('welcome');
Now in login process simply change
if (auth()->attempt($credentials)) {
return redirect()->route('welcome', [$credentials->email]);
}
to
if (auth()->attempt($credentials)) {
return redirect()->route('welcome');
}
Now inside your blade file you can simple use
{{ $user->email }}
You already pass $credentials->email from controller. If you want to keep your blade (view) file you can just pass $credentials from controller and return view with parameters instead of route redirect.
Something like this:
return view('welcome', [
'credentials' => $credentials,
])

ErrorException Undefined variable:

Why I am getting this error?
ErrorException
Undefined variable: features (View: C:\xampp\htdocs....views\layouts\index.blade.php)
FeaturedController.php
public function index()
{
$features = Feature::get();
return view ('layouts.index')->with(compact('features'));
}
ProductsController.php
public function index()
{
$products = Product::get();
return view ('products')->with(compact('products'));
}
layouts page- index.blade.php
#yield('content')
#foreach($features as $f)
<li>
<div class="prodcut-price mt-auto">
<div class="font-size-15">LKR {{ $f ['features_id'] }}.00</div>
</div>
</li>
#endforeach
view page - index.blade.php
#extends('layouts.index')
#section('content')
#foreach($products as $p)
<div class="mb-2">{{ $p ['prod_sub_category'] }}</div>
<h5 class="mb-1 product-item__title">{{ $p ['prod_name'] }}</h5>
<div class="mb-2">
<img class="img-fluid" src="{{asset('/storage/admin/'.$p ['prod_image_path'] ) }}" alt="Image Description">
</div>
<div class="flex-center-between mb-1">
<div class="prodcut-price">
<div class="atext">LKR {{ $p ['prod_price'] }}.00</div>
</div>
<div class="d-none d-xl-block prodcut-add-cart">
<i class="ec ec-shopping-bag"></i>
</div>
web.php
Route::resource('/products', 'ProductsController');
Route::resource('/layouts/index', 'FeaturedController#index');
Aside from not passing your variables to your blade views appropriately which other answers have pointed out, your trying to access features from a controller that does not have features set.
The controller below sets features and then makes use of it in the layouts.index blade file.
FeaturedController.php
public function index()
{
$features = Feature::get();
return view ('layouts.index')->with(['features' => $features]);
// or
// return view ('layouts.index', compact('features'));
}
While this controller sets products but then makes use of a blade file that extends another blade file that has a features variable in it. This is why your getting the error
ProductsController.php
public function index()
{
$products = Product::get();
return view ('products', compact('products'));
}
And to fix it you must pass the features variable along side products like so:
ProductsController.php
public function index()
{
$products = Product::get();
$features = Feature::get();
return view ('products')->with(['features' => $features, 'products' => $products]);
}
But if more than one blade file is going to extend this layouts.index file then this approach is not advisable, and situations like this is why Taylor Otwell introduced Blade Components. You can now move the features blade view and logic to a component that can wrap around any other file you want or be included.
The documentation is straight forward but if you want me to show you how to implement it to solve your dilemma then hit me up on the comment below.
as u r using data in layout u should use laravel view composer to share data to layout file ref link https://laravel.com/docs/7.x/views#view-composers
in your AppServiceProvider.php
inside boot() add this line
public function boot()
{
\View::composer('layouts.index', function ($view) { // here layout path u need to add
$features = Feature::get();
$view->with([
'features'=>$features,
]);
});
}
It share data based on specif view file like here layouts.index data is send to this view so if u not send data from controller it will get data from view composer
You can change your controller to this:
public function index()
{
$features = Feature::all();
return view ('layouts.index', compact('features'));
}
A your blade you should actually do #section instead:
#section('content')
#foreach($features as $f)
<li>
<div class="prodcut-price mt-auto">
<div class="font-size-15">LKR {{ $f->features_id }}.00</div>
</div>
</li>
#endforeach
#endsection

CRUD error in Laravel

Hello guys I made a CRUD(just create and read ) in Laravel project ,the create is working good and i passed the "loan" in show function but in the view it says undefined variable:
my show function in controller:
public function show($id)
{
$loan=loan::find($id);
return view('finance/loans')->with('loan',$loan);
}
My routes:
Auth::routes();
Route::get('/loans', 'LoanController#viewLoanForm');
Route::post('/loans', 'LoanController#store');
Route::get('/home', 'HomeController#index')->name('home');
Route::resource('loan','loanController');
Route::get('finance/loans', function () {
return view('loans');
});
And here is where i call the variable loan in the view:
#extends('layouts.app')
#section('content')
<link href="{{ asset('css/loans.css') }}" rel="stylesheet">
<html>
<div class="container">
...
</div>
</div>
</div>
<div class="row">
<h1>{{$loan->nume}}</h1>//"nume"is the row from db i want to show
</div>
</div>
</html>
#endsection
The ERROR
You misspelled the route!
Your request does not reach the controller method
Route::get('finance/loans', function () {
return view('loans');
});
should be so
Route::get('finance/loans/{$id}','loanController#show');
or should use the controller resource route
Route::resource('loans','loanController');
url 'loans/show/{$loan_id}'
Show Loan
your return should be like this:
return view('finance/loans')->with(['loan'=>$loan]);
instead of
return view('finance/loans')->with('loan',$loan);
I think you need to on the route::resource('finance/loans') instead of ('loans').
And will work for sure
Use this :
return view('finance.loans',compact(['loan']));

Laravel Datatables - Multiple tables on one view

I'm using laravel 5.4 and the latest version of yajra/laravel-datatables as a service.
I have it working fine with one datatable on a page. I want to create a dashboard of unrelated tables. Users, products, bookings etc.
I was hoping to have my controller look something like this:
public function index(ProductsDataTable $productDatatable, UsersDataTable $userDatatable)
{
$user = Auth::user();
$products = $user->products;
return view('admin.dashboard', compact('products', 'user', 'productDatatable', 'userDatatable'));
}
and in my blade do
#section('content')
{!! $productDatatable->table() !!}
{!! $userDatatable->table() !!}
#endsection
#push('scripts')
{!! $dataTable->scripts() !!}
#endpush
However this obviously doesn't work. I'm unsure how to proceed.
I tried to create a route for each datatable but wasn't sure how to reference it from my dashboard controller.
I'm sure there's a better way of implementing multiple tables in one view, but this is what I came up with after reviewing this. Comments/improvements would be highly appreciated.
Controller
The controller will render the tables once in the index() method but will fetch data from both the getUsers() method or getProducts() method.
// DashboardController.php
public function index(UsersDataTable $usersDataTable, ProductsDataTable $productsDataTable)
{
return view('dashboard.index', [
'usersDataTable' => $usersDataTable->html(),
'productsDataTable' => $productsDataTable->html()
]);
}
//Gets Users JSON
public function getUsers(UsersDataTable $usersDataTable)
{
return $usersDataTable->render('admin.dashboard');
}
//Gets Products JSON
public function getProducts(ProductsDataTable $productsDataTable)
{
return $productsDataTable->render('admin.dashboard');
}
Routes
Add two extra routes that will be used to fetch Users and Projects data.
// web.php
Route::get('/', 'DashboardController#index')->name('dashboard.index');
Route::get('projects', 'DashboardController#getProjects')->name('dashboard.projects');
Route::get('users', 'DashboardController#getUsers')->name('dashboard.users');
DataTables Service Class
For both the UsersDataTable and ProductsDataTable service classes, include the relevant routes we created above.
// UsersDataTable.php
public function html()
{
return $this->builder()
->minifiedAjax( route('dashboard.users') );
}
View
// dashboard.blade.php
#section('content')
{!! $productsDataTable->table() !!}
{!! $usersDataTable->table() !!}
#endsection
#push('scripts')
{!! $productsDataTable->scripts() !!}
{!! $usersDataTable->scripts() !!}
#endpush
Submitted a question to the creator of the package. This is his response:
Unfortunately, DataTable service class is designed to handle single instance. However, I think we can make a workaround for it by adding additional query param in our request for us to identify which class is being requested to handle the request.
Maybe something like below:
public function index(ProductsDataTable $productDatatable, UsersDataTable $userDatatable)
{
if (request()->has('product') {
return $productDatatable->render('view');
}
if (request()->has('user') {
return $productDatatable->render('view');
}
$user = Auth::user();
$products = $user->products;
return view('admin.dashboard', compact('products', 'user', 'productDatatable', 'userDatatable'));
}
Step 1:
Define a route '/home-page' in web.php/route.php' (depending on the laravel version you are using) that returns the view called 'dt.blade.php'. (we will create this view in step 4)
i.e. Route::get('/home-page', function(){
return view('dt');
});
Step 2:
Suppose you want to display two dataTables in 'dt.blade.php' view. (first datatable shows all the students in a school while other shows all the classes in a school)
To do that, you need to create two Builder instances ('Builder' class belongs to DataTables package) in the '/home-page' route's callback function and pass them to the 'dt.blade.php' view . i.e
Route::get('/home-page', function() {
$student_dt = app(Builder::class)->columns(['id', 'student_name'])->ajax('/show-students-datatable')->setTableId('t1');
$classes_dt = app(Builder::class)->columns(['id', 'class_name'])->ajax('show-classes-datatable')->setTableId('t2');
return view('dt', compact('student_dt', 'classes_dt'));
});
Step 3
Now define two more routes in web.php/route.php file:
Route::get('/show-students-datatable', function () {
return datatables(App\Student::query()->select(['id', 'student_name']))->toJson();
});
Route::get('/show-classes-datatable', function () {
return datatables(App\Class::query()->select(['id', 'class_name'])))->toJson();
});
Step 4
Define the 'db.blade.php' view, this view show both the dataTables that were passed to it in step 1.
#extends('layouts.master')
#section('content')
{{ $student_dt->table() }}
{{ $classes_dt->table() }}
#endsection
#push('scripts')
{{$student_dt->scripts()}}
{{$classes_dt->scripts()}}
#endpush

Let Authenticated User view the profile of other users in Laravel 4 using Sentry 2

I'm sort of a newb to Laravel 4 and Sentry 2, but i've managed to survive so far. I'm running into a problem right now, cause when im logged in as userid(1) and i want to view the profile of userid(2) i'm just seeing the information of userid(1) on the profile of userid(2).
I'm aware that using filters might come in handy at this, but if i have to be honest. I have no idea what i should look at etc.
I know this site is not meant for giving answers. But if someone could give me a bit of an answer, where to look, what i should keep in mind etc. that would be very much appreciated.
---EDIT---
Route:
Route::group(array('before'=>'auth'), function(){
Route::get('logout', 'HomeController#logout');
Route::get('profile/{username}', 'ProfileController#getIndex');
});
Route::filter('auth', function($route)
{
$id = $route->getParameter('id');
if(Sentry::check() && Sentry::getUser()->id === $id) {
return Redirect::to('/');
}
});
ProfileController
public function getIndex($profile_uname)
{
if(Sentry::getUser()->username === $profile_uname) {
// This is your profile
return View::make('user.profile.index');
} else {
// This isn't your profile but you may see it!
return ??
}
}
View
#extends('layouts.userprofile')
#section('title')
{{$user->username}}'s Profile
#stop
#section('notification')
#stop
#section('menu')
#include('layouts.menus.homemenu')
#stop
#section('sidebar')
#include('layouts.menus.profilemenu')
#stop
#section('content')
<div class="col-sm-10 col-md-10 col-xs-10 col-lg-10">
<div class="panel panel-info">
<div class="panel-heading"><h3>{{ $user->username }}</h3></div>
</div>
</div>
#stop
#section('footer')
#stop
This might work for you:
<?php
public function getIndex($profile_uname)
{
if(Sentry::getUser()->username === $profile_uname) {
// This is your profile
return View::make('user.profile.index');
} else {
// This isn't your profile but you may see it!
return View::make('user.profile.index')->with('user', Sentry::findUserByLogin($profile_uname));
}
}
If username is not your login column, then you can do it in two steps:
$userId = \Cartalyst\Sentry\Users\Eloquent\User::where('username', $profile_uname)->first()->id;
return View::make('user.profile.index')->with('user', Sentry::findUserById($userId));
If you have a User model tied to your users table, you can just do:
$userId = User::where('username', $profile_uname)->first()->id;
return View::make('user.profile.index')->with('user', Sentry::findUserById($userId));
And in this last case you probably will be able to use that same model, since they would be the same in Sentry and pure Eloquent:
$user = User::where('username', $profile_uname)->first();
return View::make('user.profile.index')->with('user', $user);
Also, to avoid a conflict between your views related to the current logged user, you should rename the $user variable you are instantiating via View::share() or View::composer() from $user to $loggedUser or something like that.

Categories