Laravel one click sorting - php

I'm new on this Laravel and was trying to play around the Laravel's quickstart project. I'm not familiar with the variable set within the template. I'm trying to create a one button/link to sort by ascending or decending all the retrieved records.
Usually I have no problem with basic PHP sorting by using switch (), but since I'm using Laravel, things are getting a little bit unfamiliar to me. So here's the code:-
routes.php
Route::group(['middleware' => ['web']], function () {
Route::get('/sort/{id}', function ($id) { // get to the sorted page ("/sort")
switch ($id) {
case 'asc' :
return view('tasks', [ // get the tasks table from the database
'tasks' => Task::orderBy('name', 'asc')->get(),
'sort' => "desc"
// From the tasks table, get the listing from the table and arrange them descending by date of creation
]);
case 'desc' :
return view('tasks', [ // get the tasks table from the database
'tasks' => Task::orderBy('name', 'asc')->get(),
'sort' => "asc" // From the tasks table, get the listing from the table and arrange them ascending by date of creation
]);
}
});
tasks.blade.php
<div class="panel-body">
<table class="table table-striped task-table">
<thead>
<th>Task</th>
<th> </th>
</thead>
<tbody>
#foreach ($tasks as $task) <!-- display the listings from the tasks table -->
<tr>
<td class="table-text"><div>{{ $task->name }}</div></td>
<td class="table-text"><div>{{ $task->description }}</div></td>
<!-- Task Delete Button -->
<td>
<form action="{{ url('task/'.$task->id) }}" method="POST"> <!-- form action select the id on the task table database($task->id) -->
{{ csrf_field() }}
{{ method_field('DELETE') }} <!-- delete the field -->
<button type="submit" class="btn btn-danger">
<i class="fa fa-btn fa-trash"></i>Delete
</button>
</form>
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
I just refer some of the codes on the internet and make some of my own as I'm not used with the variable within the HTML part in Laravel. I thought it would work but when I run the code, it throws the undefined variable: sort in the tasks.blade.php. Usually any variable is within the backend PHP, but this is a whole new environment to me. So, I wonder how does variable in HTML works? and how to make the sort working?
EDIT 1:
Screenshot of error:-

Your sort doesn't work, because you sort Task model ascending in both cases. You should use
Task::orderBy('name', 'desc')->get()
in second case. About variable it would be more clear if you provide screenshot.

I have found a solution for my own question. Instead of using {{$sort}} in the tasks.blade.php which I haven't set any default key, I need to use isset() function to check whether the variable is set accordingly or not. Since Laravel have its own function for that, I just use them:-
{{{ isset($sort) ? $sort : 'asc' }}}
This mean that it will set the default initial $sort variable into ascending (asc).
That's the answer for it. Thank you, me!

Related

How am I supposed to show the data when admin approve in my view

I am new to laravel, I am creating candidates approval/rejected. Now I am working for the approval. I have "general.blade.php" where this is showing all the pending list. Then when the admin approve selected candidates, it will pass the data to the new blade I called "Approved.blade.php". However, in my case. when I click one candidate, It pass all the candidate list to the new blade, either pending or approve.
CandidateController.php
public function postApprove($id)
{
$candidates = GeneralForm::where('id', '=', e($id))->first();
if($candidates)
{
$candidates->status = 1;
$candidates->save();
$candidates=GeneralForm::where('status' , '1')->get();
$menu = Menu::get();
$current_menu = 2;
$candidates = GeneralForm::latest()->paginate(5);
return view('approve', compact('candidates', 'menu', 'current_menu'));}
general.blade.php
*This is my button where admin can approve candidate *
<a class="flex items-center " href="{{route('application',['id'=>$candidate->id])}}"> <i data-feather="user-check" class="w-4 h-4 mr-1"></i> Accept </a>
I am supposed to show only approve candidates here
approve.blade.php
<tbody>#foreach ($candidates as $candidate)
<tr class="intro-x">
<td class="w-40">
<div class="font-medium whitespace-no-wrap">{{ $candidate->fullname }}</div>
</td>
<td class="w-40">
<div class="font-medium whitespace-no-wrap">{{ $candidate->email }}</div>
</td> </tbody>#endforeach
route
Route::get('application/approve/{id}', 'CandidateController#postApprove')->name('application');
What I am getting is, whenever I click one candidate, it will redirect me into approval.blade.php. however it is showing me whole list including the pending. I want it to show only the approve candidate. My database data working fine, only my view is not. Can someone help me which part is wrong?
You're getting 5 candidates using $candidates = GeneralForm::latest()->paginate(5); and passing that data to your view. Since you only need one candidate, you should update your code as follows:
public function postApprove($id)
{
$candidate = GeneralForm::find($id);
$candidate->status = 1;
$candidate->save();
$menu = Menu::get();
$current_menu = 2;
return view('approve', compact('candidate', 'menu', 'current_menu'));
}
GeneralForm::where('id', '=', e($id))->first(); can be shortened to GeneralForm::find($id)
Removed the line $candidates=GeneralForm::where('status' , '1')->get(); since that would get you a list of candidates, and it would be overwritten by $candidates = GeneralForm::latest()->paginate(5); anyway.
Renamed $candidates to $candidate to reflect that there's only one item
Then in your view you can get rid of the #foreach... since we only have one item to display:
<tbody>
<tr class="intro-x">
<td class="w-40">
<div class="font-medium whitespace-no-wrap">{{ $candidate->fullname }}</div>
</td>
<td class="w-40">
<div class="font-medium whitespace-no-wrap">{{ $candidate->email }}</div>
</td>
</tr>
</tbody>
Removed the #foreach since we only have one item to display

Problem with displaying data that I want to delete with many to many relationship in Laravel

I have many to many relationship between users and products table and I set up a view (welcome.blade.php) that when I click on the product name, which is a link, it is supposed to redirect me to page where my delete form is so I can delete that particular product, but I get 404 not found page. I suspect that error is somewhere in my routes but I can't seem to find the problem. Also when I click on some product my url says project/destroy/1 which I think is good. Here is my code:
web.php:
Route::get('/home', 'HomeController#index')->name('home');
Route::post('/store', 'HomeController#store')->name('store');
Route::delete('/destroy/{$id}', 'HomeController#destroy')->name('destroy');
destroy.blade.php:
<div class="col-md-12">
<form action="destroy/{{ $product->id }}" method="POST">
#csrf
#method('DELETE')
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</div>
welcome.blade.php:
#if($products)
<table class="table">
<thead>
<th>#</th>
<th>Product Name</th>
<th>Owner Of The Product</th>
<th>Created At</th>
</thead>
<tbody>
#foreach ($products as $product)
<tr>
<td>{{ $product->id }}</td>
<td>
{{ $product->files }}
</td>
<td>
#foreach ($product->users as $user) {{ $user->name }}
#endforeach
</td>
<td>{{ date('M j, Y', strtotime($product->created_at)) }}</td>
</tr>
#endforeach
</tbody>
</table>
#endif
HomeController.php:
<?php
namespace App\Http\Controllers;
use App\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class HomeController extends Controller
{
public function destroy(Product $product)
{
$product->users()->detach();
$product->delete();
return view('destroy');
}
}
You defined the following route in your file.
Route::delete('/destroy/{$id}', 'HomeController#destroy')->name('destroy');
This creates a DELETE route. DELETE routes are meant to be accessed by APIs. Links in anchor tags use GET routes. Clicking on
{{ $product->files }}
makes the router try and match GET /destroy/{$id} which is not defined, so it throws either an exception if debug is on or a 404 if not. You can see this in action by looking at the network tab of your browser's developer console.
Unless you add another GET route, you'll keep getting 404s.
Route::get('/destroy/{$id}', 'HomeController#destroy')->name('product.destroy-form');
will make the following link work.
{{ $product->files }}
Also, in the destroy method you're returning the view without passing any variables but in destroy.blade.php you seem to be using $product. Don't forget to add it!
You are nearly there, you just have a step too many.
Good call on the form and using the delete method, this is absolutely what you are supposed to do
However where you are going wrong is in using the link to go to a separate page with the form on to delete. You are better using a little javascript so the link submits a hidden form from the link.
<a onclick="document.getElementById('delete-form-{{$product->id}}').submit();}">{{ $product->files }}</a>
<form id="delete-form-{{$product->id}}" action="{{ route('destroy', ['id' => $product->id]) }}" method="POST" style="display: none;">
#csrf
#method('delete')
</form>
You can do the method you have but you need an additional route::get request to a page that loads the form and then you can submit the form on that page to delete.
I think it is because to delete a product using a new page the first thing to do is navigate to that page which you are not doing. You are instead going directly to the delete function using this
Route::delete('/destroy/{$id}', 'HomeController#destroy')->name('destroy');
You need to define a route that lets you go to that page first which u can do by creating a route like this:
Route::get('/delete/{$id}', 'HomeController#delete')->name('delete');
You should create a new function delete in the HomeController that just returns the destroy.blade.php. Something like this.
$product= Product::find($id);
return view('destroy')->with('product', $product);
where $id is the product id and Product is the model that you are using.

Laravel parent-child data displaying in Bootstrap table in blade

I have a simple Laravel project to show parent records in a table, with collapsible row(s) to show child records. I have a nice Bootstrap table, can join the parent and child tables in my controller and populate the table, but can't group the children under the one parent. I'm not sure if I built the passed dataset incorrectly in my controller, or if I'm missing some "Laravel way" to do this. It's an easy proposition, loop through the parents until one has a child, then loop through it's children, then resume looping parents, etc., but it's driving me insane. I can't find any direct example or reference to solve my issue, but this is a common requirement.
I need to know how to reference the child records to loop through them to populate the collapsed section. My attempts either result in a parent row for each individual child (the code shown) or a bunch of duplicated child items. If I could pass two datasets from my controller, one of parents and a separate of children, then I could in code build this, but I don't know how to do that in Laravel or if there's an easier way.
I did start with Laravel DataTables but to get detail child rows requires implementing handlebar templates in Laravel and I couldn't find a usable reference to do that, so decided to revert to from-scratch-code my own using a Bootstrap table. Than I got stuck.
Here's my controller (DataassetsController.php). The "investment-accounts" table contains parents (as do the other joined tables), and the "investment-line-items" table contains child records for the "investment-accounts".
class DataassetsController extends Controller
{
public function getUnion()
{
$money = DB::table('monetary_assets')
->select(['monetary_asset_name as name', 'monetary_asset_type as type', 'monetary_asset_value as value', DB::raw("NULL as item"), DB::raw("NULL as institution_id"), DB::raw("NULL as item_id")]);
$personal = DB::table('personal_property_assets')
->select(['personal_name as name', 'personal_type as type', 'personal_current_value as value', DB::raw("NULL as item"), DB::raw("NULL as institution_id"), DB::raw("NULL as item_id")]);
$investments = DB::table('investment_accounts')
->join('investment_line_items', 'investment_institution_name_id', '=', 'investment_accounts.id')
->select(['investment_institution_name as name', 'Investment_account_type as type', DB::raw("NULL as value"), 'investment_name as item', 'investment_institution_name_id as institution_id', 'investment_accounts.id as item_id' ]);
$union = DB::table('real_property_assets')
->select(['real_name as name', 'real_type as type', 'real_current_value as value', DB::raw("NULL as item"), DB::raw("NULL as institution_id"), DB::raw("NULL as item_id")])
->union($money)
->union($personal)
->union($investments)
->get();
return view('assets.allassets', ['user_assets' => $union]);
}
Here's my route:
Route::get('/dataassets', 'DataassetsController#getUnion');
Here's my blade (allassets.blade.php) code:
#extends('layouts.master')
<!-- Collapsible accordion rows in bootstrap -->
<div class="col-lg-6">
<div class="panel panel-default">
<div class="panel-heading"><h3>All Assets</h3></div>
<div class="panel-body">
<table class="table table-condensed" style="border-collapse:collapse;">
<thead>
<tr><th> </th>
<th>Asset Name</th>
<th>Type</th>
<th>Value</th>
</tr>
</thead>
<tbody>
#foreach ($user_assets as $user_asset) <!-- don't forget to add a variable to the loop to index ID's of subrow -->
<tr data-toggle="collapse" data-target="#demo{{$loop->index}}" class="accordion-toggle">
#isset($user_asset->item)
<td><button class="btn btn-default btn-xs"><span class="glyphicon glyphicon-eye-open"></span></button></td>
#else
<td></td>
#endisset
<td>{{$user_asset->name}}</td>
<td>{{$user_asset->type}}</td>
<td style="text-align:right">${{ number_format($user_asset->value,2)}}</td>
<?php $var = ($user_asset->name); ?>
</tr>
#isset($user_asset->item)
<tr>
<td colspan="12" class="hiddenRow"><div class="accordian-body collapse" id="demo{{$loop->index}}">
<table class="table table-striped">
<thead>
<th>Item</th>
<th>Value</th>
<th>Institution</th>
<th>Item</th>
<th>Edit</th>
</thead>
<tbody>
<tr>
<td>{{$user_asset->item}}</td>
<td> placeholder</td>
<td> {{$user_asset->institution_id}}</td>
<td> {{$user_asset->item_id}}</td>
<td><a href="#" class="btn btn-default btn-sm">
<i class="glyphicon glyphicon-cog"></i></a></td></tr>
</tbody>
</table>
</div> </td>
</tr>
#endisset
#endforeach
</tbody>
</table>
</div>
</div>
</div>
<!-- end Bootstrap table -->
Here's a picture of what I get, with one of the children rows popped out:
Bootstrap table showing only one child at a time with multiple copies of parent
Here's a pic of the database tables in question:
The parent and child tables (other tables referenced above do not have children, only this one)
I'm using Laravel 5.5 & PHP7 on XAMPP
Any help or suggestions are very welcome.

Passing Parameters from one view to another Laravel

I'm new with Laravel and there are some concepts that I don't understand very well. I really need your help on this because I've read many many pages, tutorials and stackoverflow solutions and I dont get the results that I need.
I have a list of "patients" shown on a index page from a database.
Here is the code:
#if($data)
<table class="table">
<thead>
<tr>
<td>Nombre de Paciente</td>
<td>Cedula</td>
<td>Fecha</td>
<td>Telefono</td>
<td>Email</td>
<td>Direccion</td>
<td>Fecha de Creación</td>
<td></td>
</tr>
</thead>
<tbody>
#foreach($data as $row)
<tr>
<td>
{{ $row->paciente }}</td>
<!--<td>{{ $row->paciente }}</td>-->
<td>{{ $row->cedula }}</td>
<td>{{ $row->fecha_nacimiento }}</td>
<td>{{ $row->telefono }}</td>
<td>{{ $row->email }}</td>
<td>{{ $row->direccion }}</td>
<td>{{ $row->created_at }}</td>
<td>
</td>
</tr>
</tbody>
#endforeach
</table>
#endif
What I want to do, and as you can see, the "patient" name is a link, which referese to (in this case)a form.
I want to get two things from this.
ONE: I want to get the id of the patient I'm clicking on and the name of the "patient" and send it to the form page.
TWO: on the form page I want to show the "patient" name on the top of the form, and have the "patient_id" hidden to save it on the form table (this patient_id will be a foreing key)
This are my current components:
ROUTE:
Route::get('/care/{id}', [
'as' => 'create',
'uses' => 'CareController#create' ]);
CONTROLLER
public function create($id)
{
//
return view ($this->path.'.care',['id'=>$id]);
}
VIEW:
<div class="form-group">
<label for="exampleInputEmail">Paciente </label>
<input type="hidden" name="id" value="{{$id}}">
</div>
But whenever I load the page, it shows a blank page and on the url I see the following:
http://hospital.dev/care/$row->id
I really appreciate your help with this.
UPDATE:
THANKS.
Its sending now the id. But when trying to display the form page, it still sends the blank page, and the url is the following:
"http://hospital.dev/care/1"
I dont know if it is something on the controller:
CONTROLLER:
public function create($id)
{
//
return view ($this->path.'.care',['id'=>$id ]);
}
how should I pass the id value no to the url but to the view?
You could simply concatenate the href:
<a href='/care/{{$row-id}}'></a>
Once you have passed the id into your route. You can then handle with the route definition and pass it to your other controller.
for example a view that creates dynamic links:
#extends('layouts.app')
#section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Endpoint</div>
</div>
<table class="table table-bordered" id="endpoint-table">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>ip</th>
<th>mac</th>
<th>proxy</th>
<th>model</th>
</tr>
</thead>
<tbody id="endpoint-table-body">
#foreach($endpoints as $endpoint)
<tr><td>{{$endpoint->id}}</td><td>{{$endpoint->name}}</td><td>{{$endpoint->ip}}</td><td>{{$endpoint->mac}}</td><td>{{$endpoint->proxy}}</td><td>{{$endpoint->model}}</td></tr>
#endforeach
</tbody>
</table>
</div>
</div>
</div>
#endsection
then in your routes/web.php:
Route::get('/endpoint/{id}', 'EndpointController#show');
then it gets passed to the controller # function show where you can do some logic:
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$endpoint = Endpoint::getObjectById($id);
$e = new \stdClass();
$e->id = $endpoint->id;
$e->name = $endpoint->name;
$e->ip = $endpoint->ipaddress;
$e->mac = $endpoint->macaddress;
$e->model = $endpoint->model_id;
$e->proxy = $endpoint->proxy_id;
$endpoint = $e;
$endpoints = array();
$endpoints[] = $endpoint;
return view('endpoints', ['endpoints' => $endpoints]);
}
and when you return your view. You can pass it data passed from the function you defined on your controller. In this instance that function is show() on the EndpointController.
The reason that the url is http://hospital.dev/care/$row->id is because you are using single quotes, so it won't get the value of the variable.
In the list replace:
{{url('/care/$row->id')}}
With:
{{url('/care/'+$row->id)}}
Here you're echoing variable $row->id as a string <a href="{{url('/care/$row->id')}}">, you need to print the value.
Since you've got you routes named I suggest you rewrite it like this using route() helper:
<a href="{{ route('create', ['id' => $row->id]) }}">
Here I called the route() helper, passed the route name create as first argument and the {id} that the route expects as second argument.
Another way would be to just correct your method, by moving the variable out of '' and appending it to the url like this:
<a href="{{url('/care/' . $row->id)}}">
Period . appends a string to another string in php, not +
The link you are using is like id')}}">
so here you are printing the id as a string. But you need to use this like
id)}}">
OR
id}}">

Best way to fill a roster schedule

Fellow programmers,
I got a roster application build in PHP with the framework : Laravel. And i have the following issue:
My application has : Users, Taskdate's, and TaskdateTime. Each user can get a TaskdateTime assigned to them. That TaskdateTime is a child of Taskdate. I want to populate a schedule where each user can see all their times. The schedule looks like this :
What i do in my application is : Fetch all users, Fetch all Taskdate's and according to the Taskdate's, fetch the TaskdateTime's for the right Taskdate. I do this in the following way :
$taskdates = Taskdate::with('users')->where_date($date)->get();
$employees = Usergroup::with(array('users', 'users.workdates'))->where('usergroup_title', '=', 'Employees')->first();
You can see that i fetch usergroups, with the relationship : Users and with the User->workdates relationship. Where the workdates returns the TaskdateTime objects as mentioned above.
Now in my view, i do this to populate it with data. And this seems like a lot of extra hassle and i think it could me much easier but i can't wrap my head around it. Anyway, this is the code :
<table id="plan" class="table table-bordered">
<thead>
<th></th>
#foreach($taskdates as $taskdate)
<th id="{{ $taskdate->id }}">{{ $taskdate->subject }}</th>
#endforeach
</thead>
<tbody>
#foreach($employees as $employee)
<tr id="{{ $employee->id }}">
<td>{{ $employee->name }}</td>
#foreach($taskdates as $taskdate)
<?php
$result = array_filter($employee->workdates, function($user) use ($taskdate){
return $user->id === $taskdate->id;
});
?>
#if( empty($result) )
<td></td>
#else
<td id="{{$result[key($result)]->pivot->id }}" style="{{ ($result[key($result)]->pivot->taskdate_isread) ? '' : 'font-weight:bold;'}}">
{{date('H:i', strtotime($result[key($result)]->pivot->taskdate_time))}}
</td>
#endif
#endforeach
</tr>
#endforeach
</tbody>
</table>
So i am filtering the whole workdates relationship of each user, if its hold the Taskdate id. And if it is empty, then don't echo anything.
The syntax of the HTML/PHP is in BLADE, so it might not seem correct PHP parsing, but it is.
Edit :
Question :
My code feels bloated. I don't think this is the most efficient way to achieve the result. What is your opinion on this? I like to be as efficient as possible.

Categories