Laravel soft delete: model::onlyTrashed() returns all - laravel

When I try to view only soft deleted records in Laravel the onlyTrashed returns all records.
As you will see I also have a searchform which complifies things a bit. And I think the searchform is the reason this doesn't work but I don't understand why excactly.
Controller:
public function toTrashbin(Request $request) {
$search = '%' . $request->input('search') . '%';
$students = Student::onlyTrashed()
->where('first_name', 'like', $search)
->orWhere('last_name', 'like', $search)
->orWhere('rnumber', 'like', $search)
->paginate(15)
->appends(['search'=> $request->input('search')]);
return view('admin.students.students_trashbin')->with('students', $students);;
}
View:
{{--searchform--}}
<form method="get" action="/students/trashbin" id="searchForm">
<div class="row">
<div class="col-sm-6 mb-2">
<input type="text" class="form-control" name="search" id="search"
value="{{request()->search}}" placeholder="Search by name or R-number">
</div>
<div class="col-sm-2 mb-2">
<button type="submit" class="btn btn-success btn-block">Search</button>
</div>
</div>
</form>
<hr>
#if (count($students) > 0)
{{--table--}}
<table class="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">R-number</th>
<th scope="col">Deleted at</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
#foreach ($students as $student)
<tr>
<td>{{$student->first_name}} {{$student->last_name}}</td>
<td>{{$student->rnumber}}</td>
<td>{{$student->deleted_at}}</td>
<td>
restore
</td>
</tr>
#endforeach
</tbody>
</table>
{{$students->links()}} {{--pagination--}}
#else
<p>No students found using your searchquery.</p>
#endif
Somehow the view displays all students, both soft deleted and not soft deleted ones.
However: It works perfectly if I remove the 3 "where"s in the controller. But then I can't use search obviously. Does anyone know how I can make this work with search?
Thanks.

Fixed it by changing the controller to this:
public function toTrashbin(Request $request) {
$search = '%' . $request->input('search') . '%';
$conditions = [
['first_name', 'like', $search, 'or'],
['last_name', 'like', $search, 'or'],
['rnumber', 'like', $search, 'or'],
];
$students = Student::onlyTrashed()
->where($conditions)
->paginate(15)
->appends(['search'=> $request->input('search')]);
return view('admin.students.students_trashbin')->with('students', $students);;
}
Honestly still not sure what was wrong with my original controller so if anyone knows the cause, please let me know. But hey, at least I got it to work.

On your first try, Laravel did something like this:
select * from `students` where `students`.`deletedAt` is not null and `last_name` like 'test' or `last_name` like 'test';
On your second approach, the query was mounted like this:
select * from `students` where `students`.`deletedAt` is not null and (`last_name` like 'test' or `last_name` like 'test');
Be extra careful when using "OR" on SQL because it can mess up your results and "ignore" some conditions.
You can control your parentheses doing somethin like this:
$search = '%' . $request->input('search') . '%';
$query = Student::onlyTrashed();
$query->where('votes', '>', 100)
->orWhere(function($query) use ($search) {
$query->where('name', $search)
->where('votes', '>', 50);
});
$query->paginate(15);
Extra information on Closures here: https://laravel.com/docs/7.x/queries#where-clauses
Have a good day!

Related

How to order column by relationship in Laravel Livewire

I've just followed this tutorial about implementing a data table with Livewire in Laravel.
So far so good. Now I want to order a column that comes from a one-to-one relationship, but I just can't get the sorting work well when selecting this phones relationship column.
In this case, phones is the relationship method and number is the column I display in the table, which I want to allow the sorting, as well.
How do I implement the sorting by column relationship?
Here is part of my code of the livewire blade (original repo of the tutorial):
<select wire:model="orderBy" class="...">
<option value="firstname">Name</option>
<option value="lastname">Lastname</option>
<option value="email">E-mail</option>
<option value="phones">Phone number</option>
</select>
...
<table class="table-auto w-full mb-6">
<thead>
<tr>
<th class="px-4 py-2">Name</th>
<th class="px-4 py-2">Lastname</th>
<th class="px-4 py-2">E-mail</th>
<th class="px-4 py-2">Phone number</th>
</tr>
</thead>
<tbody>
#foreach($users as $user)
<tr>
<td class="border px-4 py-2">{{ $user->firstname }}</td>
<td class="border px-4 py-2">{{ $user->lastname }}</td>
<td class="border px-4 py-2">{{ $user->email }}</td>
<td class="border px-4 py-2">{{ $user->phones->number }}</td>
</tr>
#endforeach
</tbody>
</table>
{!! $users->links() !!}
And here is the Livewire controller (original repo of the tutorial):
class UsersTable extends Component
{
use WithPagination;
public $perPage=5;
public $search = '';//Search string
public $orderBy='firstname';
public $orderAsc=true;
public $relationship_columns=['phones'];
public function render()
{
if(!in_array($this->orderBy,$this->relationship_columns)){
$users = User::search($this->search)
->orderBy($this->orderBy,$this->orderAsc ? 'asc' : 'desc')
->simplePaginate($this->perPage);
}else if($this->orderBy=='phones'){
$order = $this->orderAsc ? 'asc': 'desc';
$users = User::search($this->search)
->with(['phones' => function ($q) use($order){
$q->orderBy('number',$order);
}])
->simplePaginate($this->perPage);
}
return view('livewire.users-table',compact('users'));
}
}
Reference.
The sorting of (order by) phones is not working well. It seems it sorts some parts well, but in general, sorting is flawed. It can be sorted neither ascendant nor descendant.
Looks like the sorting type (asc,desc) is not taking effect in
$q->orderBy('number',$order);
Moreover, if I use the whereHas() method:
$order = $this->orderAsc ? 'asc': 'desc';
$users = User::search($this->search)
->whereHas('phones',function ($q) use($order){
$q->orderBy('number',$order);
})
->simplePaginate($this->perPage);
I get the following error:
SQLSTATE[HY000]: General error: 20018 The ORDER BY clause is invalid
in views, inline functions, derived tables, subqueries, and common
table expressions, unless TOP, OFFSET or FOR XML is also specified.
[20018] (severity 15)
What am I missing? Any ideas on how to fix this?
How do I implement the order by functionality on the relationship column in Livewire?
Based on these posts Ordering database queries by relationship columns in Laravel and Laravel Eloquent whereColumn Query Example, I have solved the ordering by relationship this way:
I set any name to the relationship, in the parameter search function, let's say phone.number.
Then, with an if statement I detect if the ordering is that relationship:
if($this->field == 'phone.number'){
$users = $users->orderBy(\App\Models\Phone::select('number')->whereColumn('users.phone_id','phones.id'));
}else{
$users = $users->orderBy($this->field,$this->order);
}
Moreover, in this answer it is explained how to search inside a column relationship.
You can use
$user = User::search($this->search)
->whereHas('phones', function ($q){
$q->orderBy('number', $order);
})
->simplePaginate($this->perPage);
instead of
$users = User::search($this->search)
->with(['phones' => function ($q) use($order){
$q->orderBy('number',$order);
}])
->simplePaginate($this->perPage);

Want to Join three table but not work [Eloquent]

I want to
SELECT events.id = scan.event_id IF Scan.student_id MATCH user.student_id SHOW events.id and events.name
But my code dint work, it blank screen nothing happen to show
so blind :|
Controller
public function pdftranscript($id)
{
$users = DB::table('users')
->join('scan', 'users.student_id', '=', 'scan.student_id')
->join('events', 'scan.event_id', '=', 'events.id')
->select('users.*', 'events.m_event_name', 'scan.event_id')
->get();
This blade
#foreach($user as $user)
<tr>
<td>{{$user->student_id}}</td>
<td>{{$user->name}}</td>
#foreach($event as $event)
<td>{{$event->m_event_name}}</td>
#endforeach
<tr>
#endforeach
First you could dd($users) in your controller to check whether you have got a successful query. Then in blade, it should be:
#foreach($users as $user)
<tr>
<td>{{$user->student_id}}</td>
<td>{{$user->name}}</td>
<td>{{$user->m_event_name}}</td>
<tr>
#endforeach
You already took the values in $users variable..No need for the second foreach loop.
#foreach($users as $user)
<tr>
<td>{{$user->student_id}}</td>
<td>{{$user->name}}</td>
<td>{{$user->event_id}}</td>
<td>{{$user->m_event_name}}</td>
<tr>
#endforeach

Real Live Search and Filter Laravel

I'm new on Laravel and try to implement real live search and filter on my project, but it doesn't work at all. I dont understand ajax ver much and just copy paste the code from other website. I tried to understand the code and I think its correct but it doesn't work, so please help. Thanks
Here is my controller
public function search(Request $request)
{
if($request->ajax())
{
$output = '';
$query = $request->get('query');
if($query != '')
{
$data = Service::table('service')
->where('keterangan', 'like', '%'.$query.'%')
->orWhere('biaya', 'like', '%'.$query.'%')
->get();
}
else
{
$data = Service::table('service')
->orderBy('kodeService', 'asc')
->get();
}
$total_row = $data->count();
if($total_row > 0)
{
foreach($data as $row)
{
$output .= '
<tr>
<td>'.$row->kodeService.'</td>
<td>'.$row->keterangan.'</td>
<td>'.$row->biayaService.'</td>
</tr>
';
}
}
else
{
$output = '
<tr>
<td align="center" colspan="5">No Data Found</td>
</tr>
';
}
$data = array(
'table_data' => $output
);
echo json_encode($data);
}
}
This is the script
$(document).ready(function(){
fetch_customer_data();
function fetch_customer_data(query = '')
{
$.ajax({
url:"{{ route('live_search.action') }}",
method:'GET',
data:{query:query},
dataType:'json',
success:function(data)
{
$('#table tbody').html(data.table_data);
}
});
}
$(document).on('keyup', '#search', function(){
var query = $(this).val();
fetch_customer_data(query)
});
});
Route :
Route::resource('service', 'ServiceController');
Route::get('service/search', 'Service#search')->name('live_search.action');
And index.blade
<table class="table table-striped table-hover table-bordered" id="table">
<thead>
<tr>
<th>Kode Service</th>
<th>Keterangan</th>
<th>Biaya</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
#foreach($service as $data)
<tr>
<td><?= $data->kodeService?></td>
<td><?= $data->keterangan ?></td>
<td><?= $data->biayaService?></td>
<td>
<a class="btn btn-sm btn-info" href="{{ route('service.edit', $data['kodeService']) }}"> <i class="oi oi-pencil"></i> Edit</a>
<button type="button" class="btn btn-sm btn-danger" data-toggle="modal" data-target="#myModal"><span class="oi oi-trash"></span> Hapus</button>
</td>
</tr>
#endforeach
</tbody>
</table>
Put your route like this :
Route::get('service/search', 'ServiceController#search')->name('live_search.action');
Route::resource('service', 'ServiceController');
After that open the Browser Console panel (Press F12 to open it) and check the Ajax request in Network tab.
Where you can get the specific error if any in the Response tab.
If you need an extra route to your resource route,you should place the new route before the resource route.
Route::get('service/search', 'ServiceController#search')->name('live_search.action');
Route::resource('service', 'ServiceController');

Method addSelect does not exist

I'm getting this error message when I try to do a addSelect method in Laravel 5.2
Any ideas?
BadMethodCallException in Macroable.php line 74:
Method addSelect does not exist.
Here is the function in my controller
public function summaryOfMembersTable()
{
$members = MotherProfile::select('last_name')
->orderBy('last_name','ASC')
->distinct()
->get();
$count = $members->count();
$mothers = MotherProfile::select(DB::raw('count(*) as user_count, gender'))
->where('gender', '<>', 'F')
->groupBy('gender')
->get();
$fullnames = $members
->addSelect('first_name')
->orderBy('last_name','ASC')
->distinct()
->get();
$data = [];
$data['members'] = $members;
$data['memberCount'] = $count;
$data['mothers'] = $mothers;
$data['fullnames'] = $fullnames;
return view( 'user/masterlist/summary-of-members', $data);
}
My blade:
Total is {{ $memberCount }}
#foreach ($fullnames as $fullname)
{{ $fullname }}<br>
#endforeach
<hr>
<div class="page-header" style="text-align:center;">
<h3 class="pageHeader">
List of Members
<br>
</h3>
</div>
<div class="row">
<table class="table table-bordered" style="text-align: left;">
<tr>
<th></th>
<th>Full Name (Last, First, Middle)</th>
<th>KLC</th>
<th>Category</th>
<th>Mem Type</th>
<th>Mem Status</th>
<th>Date Baptized</th>
<th>Mother in Spirit</th>
<th>Encoder</th>
</tr>
<tbody>
</tbody>
</table></div>
you are getting a collection instead of an object. addSelect method belong to builder object not to collection. So remove get() from your query and you'll be fine.
$members = MotherProfile::select('last_name')
->orderBy('last_name','ASC')
->distinct()
->get();
$members = MotherProfile::select('id','last_name')
->orderBy('last_name','ASC')
->distinct()
->addSelect(DB::raw("'value' as nameFake"))->get();
before to get()

Laravel 4 search - in view, show value submitted in form

Below is the beginnings of filter form I have built. It works ok but what I'd like to do is retrieve in my view, the values entered for. So, in this example I'd like to display "you searched by 'the keyword user entered'", and also display this within the keyword text field. This will be the same principle when I add select lists.
If the user wishes to change filter settings, or paginate through the results, the values are always stored.
My question is how to do this. I'm quite sure it's possible in laravel but only know how to do this in PHP
FORM
<div class="row">
{{ Form::open(array('url'=>'events/search', 'class'=>'form-search', 'role'=>'form')) }}
<div class="col-lg-6">
<div class="input-group">
{{ Form::text('search', '', array('class'=>'form-control', 'placeholder'=>'Search by keyword.'))}}
<span class="input-group-btn">
{{ Form::submit('Search', array('class'=>'btn btn-default'))}}
</span>
</div>
</div>
{{ Form::close() }}
</div>
SEARCH CONTROLLER
public function postSearch() {
$search = Input::get('search');
$events = DB::table('events')
->where(function($query) use ($search)
{
$query->where('title', 'LIKE', '%' . $search . '%')
->where('date','>=', DB::raw('CURDATE()'));
})
->orderBy('date', 'DESC')
->get();
$this->layout->content = View::make('events.results',
array(
'events' => $events
)
);
}
VIEW
#foreach($events as $event)
<div class="col-md-9">You search for ''</div>
{{-- filter form will again display here --}}
<h2>{{ HTML::link("events/$event->id/", "$event->title") }}</h2>
#endforeach
Controller:
public function postSearch() {
$search = Input::get('search');
$events = DB::table('events')
->where(function($query) use ($search)
{
$query->where('title', 'LIKE', '%' . $search . '%')
->where('date','>=', DB::raw('CURDATE()'));
})
->orderBy('date', 'DESC')
->get();
$this->layout->content = View::make('events.results',
array(
'events' => $events,
'search' => $search <-------- pass the search parameter to view
)
);
}
View:
#if(!empty($search))
<div class="col-md-9">You search for {{$search}}</div>
#endif
#foreach($events as $event)
{{-- filter form will again display here --}}
<h2>{{ HTML::link("events/$event->id/", "$event->title") }}</h2>
#endforeach
Two issues:
Generally search forms are GET and not POST. (easier to bookmark, give the links elsewhere)
put the search term outside the loop.

Resources