I have a problem with my pagination, i have my every page displayed, when i want go to other page my search is canceled and it displays all the elements of the site.
<?php
namespace App\Http\Controllers;
use App\Models\Furniture;
use Illuminate\Http\Request;
use App\Models\Tag;
class MainController extends Controller
{
public function showHomepage()
{
$latestProducts = Furniture::latest()->take(5)->get();
return view('templates.homepage', compact('latestProducts'));
}
public function showFurniture(Furniture $furniture)
{
return view('templates.furniture', compact('furniture'));
}
public function showSearchResults(Request $request)
{
$search = $request->get('q');
$tag = Tag::where('title', 'like', '%' . $search . '%')->first();
$query = Furniture::select("furniture.*")
->join("furniture_tag", "furniture_tag.furniture_id", "=", "furniture.id");
if ($tag){
$query->where('furniture_tag.tag_id', $tag->id);
}
$query->orWhere('furniture.title', 'like', '%' . $search . '%');
$furnituresCount=$query->count();
$furnitures=$query->paginate(5);
return view('templates.search', compact('search', 'furnitures', 'furnituresCount',));
}
}
To append all of the current request's query string values to the pagination links you need to change
$furnitures=$query->paginate(5);
to
$furnitures = $query->paginate(5)->withQueryString();
Manual: Appending Query String Values
Related
I have a Livewire component with search field whick works like a charm, and above that I have a list of Location model. /locations. Also, I have a relation table Categories with category_id. Now, i want to implement checkbox filter on same page with category (catA, catB, catC). I maked a Livewire component with
PLease can you help me. Thanky much
class LocationSearch extends Component
public $searchTerm = "";
public $locations;
public $categories = [];
public function render()
{
sleep(1);
$searchTerm = '%' . $this->searchTerm . '%';
$this->locations = Location::query()
->where('name', 'LIKE', "%{$searchTerm}%")
->orWhere('description', 'LIKE', "%{$searchTerm}%")
->orWhere('visibility', 'LIKE', "%{$searchTerm}%")
->get();
return view('livewire.location-search', [
]);
}
I have two models which linked with each other:
class Task extends Model{
public function user(){
return $this->belongsTo('App\User', 'user_id');
}
}
class User extends Model{
public function tasks(){
return $this->hasMany('App\Task', 'user_id');
}
}
Now I want to create some search or filter system.
There is a form where the user can choose Task only then the User's parameters (age, sex etc)
How can I do this kind of things? I tried to use newQuery on relation but...
Any help, thanks
I hope i understood you well.
Use nested where and whereHas as such
$tasks = Task::where('condition', $var)
->orWhereHas('user', function($q) use ($var){
$q->where('condition', 'LIKE', '%'. $var.'%');
});
try this. i hope it will work for you.
use join to get data from two tables
function getBuildings($request) {
if (isset($request->keyword) && $request->keyword != '') {
$data = $this->where(function($query) use ($request) {
$query->orWhere('users.column_name', 'LIKE', '%' . $request->keyword . '%');
$query->orWhere('users.column_name', 'LIKE', '%' . $request->keyword . '%');
});
}
$datacount = $this->count();
$dataArray = $this->select('users.*,task.whatever data you want to get from task');
if ($request->length == -1) {
$dataArray = $dataArray->get();
} else {
$dataArray = $dataArray->skip($request->start)->take($request->length)->get();
}
return [$datacount, $dataArray];
}
Hi I am developing a rest api endpoint for retrieving paginated list of users. In the frontend, there are options to search with all the listed columns, sort by all columns and filter by name, status and created date.
So far I have created a repository and local scopes in user model for search, sort and filter. This is my code so far. I am confused with the filter option. Since a user a call filter with all the three options. How to pass those values in api in most optimised way?
Controller:
public function index(Request $request)
{
$this->userRepository->getAllUsers($request);
}
Repository function:
public function getAllUsers($request)
{
// Search Parameter
isset($request->q)? $q = $request->q: $q = null;
// Sort Parameter
if ( isset($request->sortby) && (isset($request->direction)) ) {
$sort[$request->sortby] = $request-> direction;
}
return User::where('type','=','student')
->ofSearch($q)
->ofSort($sort)
->paginate($per_page)
}
Model:
public function scopeOfSearch($query, $q)
{
if ( $q ) {
$query->orWhere('name', 'LIKE', '%' . $q . '%')
->orWhere('school', 'LIKE', '%' . $q . '%')
->orWhere('email', 'LIKE', '%' . $q . '%')
->orWhere('phone', 'LIKE', '%' . $q . '%')
->orWhere('class', 'LIKE', '%' . $q . '%');
}
return $query;
}
public function scopeOfSort($query, $sort = [])
{
if ( ! empty($sort) ) {
foreach ( $sort as $column => $direction ) {
$query->orderBy($column, $direction);
}
}
else {
$query->orderBy('users.name');
}
return $query;
}
Anyways I fixed it my creating another post endpoint which will send all the filters with its value. I am not sure if this is the correct way but now I can think of only like this.
Update
I had implemented the filter by following the below tutorial.
https://m.dotdev.co/writing-advanced-eloquent-search-query-filters-de8b6c2598db
I'll change your repository's code this way:
public function getAllUsers($request)
{
// Set query builder
$qb = User::query();
if($request->has('q')){
$qb->ofSearch($q);
}
if($request->has('sortby')){
//Handle default parameter of get with second argument
$qb->orderBy($request->get('sortBy'), $request->get('direction', 'ASC'));
}
return $qb->paginate();
}
Request::get method handle isset checks for you!
An easy solution for who needs sort and filter DB data using a Laravel API (tested in Laravel 5.x and 6.1).
First:
Create your table in DB. You can do it manually for test proposital, but I recommend follow this: https://laravel.com/docs/5.7/migrations
In that exemple the table was named 'my_task';
Then create your Model typing in the root Laravel directory:
php artisan make:model MyTask (return: Model created successfully.)
The model will be created inside app directory.
Next, create your Controller typing in the root Laravel directory:
php artisan make:controller MyTaskController (return: Controller created successfully.)
The controller will be created inside app/Http/Controllers/
After, insert the code below inside the controller MyTaskController.php file:
<?php
namespace App\Http\Controllers;
use App\MyTask;
use DB;
use Illuminate\Http\Request;
class MyTaskController extends Controller
{
public function filter($parameter)
{
$filter = DB::table('my_task')
->where('field123', '=', $parameter)
->get();
return $filter;
}
}
Lastly:
Add a route pointing to your controller in the routes/api.php file:
Route::get("my-task/{parameter}", "MyTaskController#filter");
Test your endpoint using a browser or the Postman:
http://127.0.0.1/api/my-task/value
In the url above "value" is the value you want to look for in the database my-task table.
Ps: You can create new routes poiting to other functions inside the same controller to have others types of manipulations, as 'sort'.
I have 3 models like this:
WarehousePivotCategory:
id - warehouse_id - warehouse_category_id
Warehouse:
title
WarehouseCategory:
title_en
I've created 2 hasOne relationships inside WarehousePivotCategory and they work fine:
public function Warehouse()
{
return $this->hasOne('App\Models\Warehouse','id','warehouse_id');
}
public function WarehouseCategory()
{
return $this->hasOne('App\Models\WarehouseCategory','id','warehouse_category_id');
}
in the database I have two records in warehouses table :
id title
1 AA
2 BB
I want to search title in warehouses :
$title = 'AA';
$warehouses = WarehousePivotCategory::with(['warehouse' => function($q) use ($title) {
$q->where('title', 'like', '%' . $title . '%');
},'WarehouseCategory'])->get();
foreach ($warehouses as $w)
{
echo $w->warehouse->title; // no thing
}
but it doesn't return any of title of warehouses.
my relationships is correct because below code works fine :
WarehousePivotCategory::with('warehouse','WarehouseCategory')->paginate(10);
I think you're missing get method in your closure. Try it like this:
$warehouses = WarehousePivotCategory::with(['warehouse' => function($q) use ($title) {
$q->where('title', 'like', '%' . $title . '%')->get(); },'WarehouseCategory'])->get();
You can also send array of fields you want to fetch to get method, like this:
$warehouses = WarehousePivotCategory::with(['warehouse' => function($q) use ($title) {
$q->where('title', 'like', '%' . $title . '%')->get(['id', 'title']); },'WarehouseCategory'])->get();
That is wrong. You don't need to use hasone while you have created pivot.You need to use BelongsToMany
class warehouse extends Model{
public function ware_cat(){
return $this->BelongsToMany('App\Models\WarehouseCategory');
}
public function getWarehouse(){
$this->with('ware_cat')->get();
}
}
Pivot table will fetch it so in warehouse model you will get its category and in category model you will get the warehouse same way visa-versa.
<?php
namespace App\Http\Controllers;
use App\Clients;
use Illuminate\Http\Request;
use App\Http\Requests;
class AuditsController extends Controller {
public function index() {
$clients = Clients::distinct()->select('tag')->where('tag', '!=', 'NA')->get();
return view('clients', compact('clients'));
}
public function show($client) {
$machines = Clients::with('machines', 'bios')->where('TAG', $client)->get();
$server = $machines->where('OSNAME', 'LIKE', '%server%')->get();
return view('audit', compact('client'))->with('server', $server);
}
}
$machines creates a list of machines the client has, i need to have this list only show the machines with the word server in the field OSNAME, ive tried doing it as follows but it also did not work
$machines = Clients::with('machines', 'bios')->where('TAG', $client)->where('OSNAME', 'LIKE', '%server%')->get();
I'm not sure on what is the correct laravel method for doing this, should i create a new model?
Clients/machines reference 2 different tables in DB.
Use Eager-loading Filters:
Before:
public function show($client) {
$machines = Clients::with('machines', 'bios')->where('TAG', $client)->get();
$server = $machines->where('OSNAME', 'LIKE', '%server%')->get();
return view('audit', compact('client'))->with('server', $server);
}
After:
public function show($client) {
$machines = Clients::with(['machines' => function($query) {
//Filter eager loaded relation
return $query->where('OSNAME', 'LIKE', '%server%');
}, 'bios'])->where('TAG', $client)->get();
return view('audit', compact('client'))->with('machines', $machines);
}
See: https://laravel.com/docs/5.1/eloquent-relationships#constraining-eager-loads
The Right Way (Avoids unnecessary queries):
public function show($client) {
//Proper way to do it
$server = Machine::whereHas('client',function($query) use ($client){
return $query->where('TAG', $client)
})->where('OSNAME', 'LIKE', '%server%')->get();
return view('audit', compact('client'))->with('server', $server);
}