I have two tables: admins and log_doctor_infos. admins table has relationship hasOne with log_doctor_infos throught doctor_id like this.
In model Admin:
public function logDoctorInfo() {
return $this->hasOne(LogDoctorInfo::class, 'doctor_id', 'id');
// Model LogDoctorInfo is log_doctor_infos table
}
And in Model LogDoctorInfo:
public function doctor(){
return $this->belongsTo(Admin::class, 'doctor_id', 'id');
// Model Admin is admins table
}
I get all data form admins table and i want to sort record has relationship with log_doctor_infos to top.
Yellow record, which has relationship with log_doctor_infos and i want to sort it in top.
Edit: i use paginate in this query and i really want to get quantity of Yellow record.
Thanks for reading!
In my controller, i have custom filter and paginate. Help me.
public function index(Request $request) {
$fullname = $request->query('fullname', NULL);
$phone = $request->query('phone', NULL);
$status = $request->query('status', NULL);
$doctors = (new Doctor)->newQuery();
if ($fullname != NULL) {
$doctors = $doctors->where('fullname', 'LIKE', '%'.$fullname.'%');
}
if ($phone != NULL) {
$doctors = $doctors->where('phone', 'LIKE', '%'.$phone.'%');
}
if ($status != NULL) {
$doctors = $doctors->where('status', $status);
}
$doctors = $doctors
// ->with(array('logDoctorInfo' => function($query) {
// $query->orderBy('updated_at', 'ASC');
// }))
->latest()
->paginate()
->appends([
'fullname' => $fullname,
'phone' => $phone,
'status' => $status
]);
// dd($doctors);
return view('admin.doctors.index', compact('doctors'));
}
you can use the withCount method.
Admin::withCount('logDoctorInfo')
->orderBy('log_doctor_info_count', 'desc')
->paginate(5);
Your controller will look like this
public function index(Request $request) {
$fullname = $request->input('fullname', NULL);
$phone = $request->input('phone', NULL);
$status = $request->input('status', NULL);
$doctorQuery = Doctor::query();
if ($fullname) {
$doctorQuery->where('fullname', 'LIKE', '%'.$fullname.'%');
}
if ($phone) {
$doctorQuery->where('phone', 'LIKE', '%'.$phone.'%');
}
if ($status) {
$doctorQuery->where('status', $status);
}
$doctorQuery->withCount('logDoctorInfo')
->orderBy('log_doctor_info_count');
$doctors = $doctorQuery->paginate()
->appends([
'fullname' => $fullname,
'phone' => $phone,
'status' => $status
]);
// dd($doctors);
return view('admin.doctors.index', compact('doctors'));
}
Doctor::with('logDoctorInfo')->get()->sortByDesc('logDoctorInfo.id');
Related
I have seen many similar questions but most of the answers look complicated and do not seem too similar to my issues. Again, I am new to Laravel and would need the simplest form of explanation.
I want to don't show info in view, show up as long as I searched.
My Controller
public function index(Request $request)
{
$transactions = UserTransaction::query();
$userId = request()->get('userId');
$price = request()->get('price');
$type = request()->get('type');
$status = request()->get('status');
$ordering = request()->get('ordering');
if($userId){
$transactions->where('userId' , $userId);
}
if ($price) {
$transactions->where('price' , $price);
}
if ($type) {
$transactions->where('type' , $type);
}
if ($status) {
$transactions->where('status' , $status);
}
return view('admin.transaction.index',[
'transactions' => $transactions->paginate(5)->appends($request->except('page')),
'stats' => $stats
]);
}
My Blade
#if( $transactions->count() > 0 && request()->has() )
#foreach($transactions as $transaction)
{{ $transaction->id }}
{{ optional($transaction->user)->full_name }}
{{ $transaction->type }}
#endforeach
#endif
I get this error
I think you are looking for hiding view until user searched any one field.So you can do the following
#if( $transactions->count() > 0 &&collect($request->all())->filter()->isNotEmpty())
if you want to ignore page from checking then you can use except
collect($request->except('page'))->filter()->isNotEmpty()
Better don't execute query until one of the filter value is filled because any way you don't to display it in view
public function index(Request $request)
{
$userId = request()->get('userId');
$price = request()->get('price');
$type = request()->get('type');
$status = request()->get('status');
$ordering = request()->get('ordering');
$transactions=[];
if(collect($request->all())->filter()->isNotEmpty()){
$transactions = UserTransaction::query();
if($userId){
$transactions->where('userId' , $userId);
}
if ($price) {
$transactions->where('price' , $price);
}
if ($type) {
$transactions->where('type' , $type);
}
if ($status) {
$transactions->where('status' , $status);
}
$transactions->paginate(5)->appends($request->except('page'))
}
return view('admin.transaction.index',[
'transactions' =>$transactions,
'stats' => $stats
]);
}
Also instead of repeating collect($request->except('page'))->filter()->isNotEmpty() this in multiple place ,you can assign to variable in controller
You should check in the controller whether data has been entered or not. If not, then return the null for $transactions.
public function index(Request $request)
{
if(count($request->all()) > 0) {
$transactions = UserTransaction::query();
$userId = request()->get('userId');
$price = request()->get('price');
$type = request()->get('type');
$status = request()->get('status');
$ordering = request()->get('ordering');
if($userId){
$transactions->where('userId' , $userId);
}
if ($price) {
$transactions->where('price' , $price);
}
if ($type) {
$transactions->where('type' , $type);
}
if ($status) {
$transactions->where('status' , $status);
}
$transactions= $transactions->paginate(5)->appends($request->except('page'))
} else {
$transactions = null;
}
return view('admin.transaction.index',[
'transactions' => $transactions,
'stats' => $stats
]);
}
Then in your view just check $transactions->count() > 0
I am trying to add new functionality to my project to be able to add tweet anonymously so I need to check if the public field = 0 , return the tweets without user or null user object !
How I can use "with" with OrWhere or something like that?
I have done that by merging the collections but I need more efficient query to do that
when I try OrWhere()->with() that return user data for all collection I need the data in with() comes only with condition ? how to do that ?
Thanks
$tweets = Tweet::where(function ($query) {
$query->where('public',1);
$query->where('hashtag_id', request('hashtag_id'));
})->with([
'user' => function ($query) {
$query->select('id', 'name', 'username', 'photo', 'verified')->withTrashed();
},
'hashtag' => function ($query) {
$query->withTrashed();
},
])-> where(function ($query) {
$query->whereRaw('DATE_ADD(created_at,INTERVAL expiration_time SECOND) >= "' . Carbon::now()->toDateTimeString() . '" or expiration_time = 0');})
->withCount(['replies'])->orderBy('created_at', 'desc')->get();
$tweets2 = Tweet::where(function ($query) {
$query->where('public',0);
$query->where('hashtag_id', request('hashtag_id'));
})->with(['hashtag' => function ($query) {
$query->withTrashed();
},
])-> where(function ($query) {
$query->whereRaw('DATE_ADD(created_at,INTERVAL expiration_time SECOND) >= "' . Carbon::now()->toDateTimeString() . '" or expiration_time = 0');})
->withCount(['replies'])->orderBy('created_at', 'desc')->get();
$tweets = $tweets->merge($tweets2);
I have figured this solution by adding method in the model check this condition and return depends on this condition
$tweets = Tweet::Where(function ($query) {
$query->where('hashtag_id', request('hashtag_id'));
})->with([
'hashtag' => function ($query) {
$query->withTrashed();
},
])->where(function ($query) {
$query->whereRaw('DATE_ADD(created_at,INTERVAL expiration_time SECOND) >= "' . Carbon::now()->toDateTimeString() . '" or expiration_time = 0');})
->withCount(['replies'])->orderBy('created_at', 'desc')->get();
foreach($tweets as $tweet){
$tweet->user = $tweet->GetPublic();
}
That is the method in the model
public function GetPublic()
{
if($this->public == 1)
{ $user = $this->user;
return $user;
}
else{
return null;
}
}
By checking out this tutorial I'm implementing a search url in my Laravel 5.4 application. I've implemented a trait in my model for example if I'm having Company model so in model I'm including my trait something like this:
class Company extends Model
{
use SoftDeletes, DataViewer;
protected $fillable = [
'name', 'address', 'city', 'state', 'country', 'type', 'sub_type',
];
public static $columns = [
'name', 'address', 'city', 'type', 'sub_type'
];
}
Now I'm having this DataViewer trait something like this:
trait DataViewer {
protected $operators = [
'equal' => '=',
'not_equal' => '<>',
'less_than' => '<',
'greater_than' => '>',
'less_than_or_equal_to' => '<=',
'greater_than_or_equal_to' => '>=',
'in' => 'IN',
'like' => 'LIKE'
];
public function scopeSearchPaginateAndOrder($query)
{
$request = app()->make('request');
return $query
->orderBy($request->column, $request->direction)
->where(function($query) use ($request) {
if($request->has('search_input')) {
if($request->search_operator == 'in') {
$query->whereIn($request->search_column, explode(',', $request->search_input));
} else if($request->search_operator == 'like') {
$query->where($request->search_column, 'LIKE', '%'.$request->search_input.'%');
}
else {
$query->where($request->search_column, $this->operators[$request->search_operator], $request->search_input);
}
}
})
->paginate($request->per_page);
}
}
And I'm calling this in controller something like this:
public function getData()
{
$models = Company::searchPaginateAndOrder();
return response()->json([
'model' => $models
]);
}
And to achieve this I'm calling url something like this:
http://stellar.dev/api/companies?column=name&direction=asc&page=1&per_page=50&search_column=name&search_operator=like&search_input=icici
The problem which I'm facing here is that it can search can only through one column, I want to have search with multiple columns in one query. Suggest me what can be done.
Thanks.
You should make your query string as an array for multiple columns like this.
http://stellar.dev/api/companies?column=name&direction=asc&page=1&per_page=50&search_column[]=name&search_operator[]=like&search_input[]=icici&search_column[]=lastname&search_operator[]=like&search_input[]=asd
Then read and use them as an array. Also you need to check their length to prevent unexpected errors. Then you can simple use a simple loop to concatenate your conditions like the following code block.
trait DataViewer {
protected $operators = [
'equal' => '=',
'not_equal' => '<>',
'less_than' => '<',
'greater_than' => '>',
'less_than_or_equal_to' => '<=',
'greater_than_or_equal_to' => '>=',
'in' => 'IN',
'like' => 'LIKE'
];
public function scopeSearchPaginateAndOrder($query)
{
$request = app()->make('request');
$searchInputs = $request->get('search_input', []);
$searchOperators = $request->get('search_operator', []);
$searchColumns = $request->get('search_column', []);
$query->orderBy($request->column, $request->direction);
if(count($searchInputs) == count($searchOperators) && count($searchOperators) == count($searchColumns)) {
$query->where(function($query) use ($searchInputs, $searchOperators, $searchColumns) {
for($x = 0, $l = count($searchColumns); $x < $l; $x++){
if($searchOperators[$x] == 'in') {
$query->whereIn($searchColumns[$x], explode(',', $searchInputs[$x]));
} else if($searchOperators[$x] == 'like') {
$query->where($searchColumns[$x], 'LIKE', "%{$searchInputs[$x]}%");
}
else {
$query->where($searchColumns[$x], $searchColumns, $searchInputs[$x]);
}
}
});
}
return $query->paginate($request->per_page);
}
}
Note: I strongly recommend use post verb for this search page or your data will be html encoded and your url is absolutely not user friendly.
Edited Answer
I have changed the code for multiple columns, single operator and single field.
public function scopeSearchPaginateAndOrder($query)
{
$request = app()->make('request');
$searchInput = $request->get('search_input');
$searchOperator = $request->get('search_operator');
$searchColumns = $request->get('search_column', []);
$query->orderBy($request->column, $request->direction);
if(count($searchColumns) > 0) {
$query->where(function($query) use ($searchInput, $searchOperator, $searchColumns) {
for($x = 0, $l = count($searchColumns); $x < $l; $x++){
if($searchOperator == 'in') {
$query->whereIn($searchColumns[$x], explode(',', $searchInput));
} else if($searchOperator == 'like') {
$query->where($searchColumns[$x], 'LIKE', "%{$searchInput}%");
}
else {
$query->where($searchColumns[$x], $searchOperator, $searchInput);
}
}
});
}
return $query->paginate($request->per_page);
}
I'm having trouble when a user is not an admin. The goal is to get only those requests that belong to the user, but when I use the where clause, I get all the requests from the DB.
It was supposed to get all the requests only for an admin.
Thank you for the help!
public function index(){
$status = request('status', -1);
$paper_size = request('paper_size', -1);
if (auth()->user()->isAdmin()) {
$requests = Request::
where('paper_size', $paper_size)->orWhereRaw($paper_size. ' = -1')->
where('status', $status)->orWhereRaw($status. ' = -1')->
orderBy(
request('orderby') ? request('orderby') : 'created_at',
request('order') ? request('order') : 'DESC'
)->paginate(10);
$departments = Departament::All();
return view('Requests.index', compact('requests', 'departments'));
}
$requests = auth()->user()->requests()->
where('status', $status)->orWhereRaw($status. ' = -1')->
where('paper_size', $paper_size)->orWhereRaw($paper_size. ' = -1')->
orderBy(
request('orderby') ? request('orderby') : 'created_at',
request('order') ? request('order') : 'DESC'
)->paginate(10);
return view('Requests.index', compact('requests'));
}
UPDATE:
I can already list all user requests, but the status filter does not work.
Ps: the filter "paper_size" is working as expected
SOLVED:
Thanks to the whole community, and especially to #Sandeesh
public function index(){
request('status') == -1 || request('status') == null ?
$statusExists = false : $statusExists = true;
$status = request('status');
request('paper_size') == -1 || request('paper_size') == null ?
$paper_sizeExists = false : $paper_sizeExists = true;
$paper_size = request('paper_size');
$is_admin = auth()->user()->isAdmin();
$requests = Request::when($statusExists, function ($query) use ($status) {
return $query->where('status', $status);
})
->when($paper_sizeExists, function ($query) use ($paper_size) {
return $query->where('paper_size', $paper_size);
})
->when(!$is_admin, function ($query) {
return $query->where('owner_id', auth()->id());
})
->orderBy(request('orderby', 'created_at'), request('order', 'desc'))
->paginate(10);
if (!$is_admin) {
return view('Requests.index', compact('requests'));
}
$departments = Departament::all();
return view('Requests.index', compact('requests', 'departments'));
}
Wrap your where and orWhereRaw conditions together for a single column. Or use when instead of the workaround you apply with -1 = -1. I've also refactored the code for you.
public function index()
{
$status = request('status');
$paper_size = request('paper_size');
$is_admin = auth()->user()->isAdmin();
$requests = Request::when(!is_null($status), function ($query) use ($status) {
return $query->where('status', $status);
})
->when(!is_null($paper_size), function ($query) use ($paper_size) {
return $query->where('paper_size', $paper_size);
})
->when(!$is_admin, function ($query) {
return $query->where('owner_id', auth()->id());
})
->orderBy(request('orderby', 'created_at'), request('order', 'desc'))
->paginate(10);
if (!$is_admin) {
return view('Requests.index', compact('requests'));
}
$departments = Departament::all();
return view('Requests.index', compact('requests', 'departments'));
}
You would need to get the $user_id = Auth::id and then update the second query to have a where user_id = $user_id statement (I'm not sure which of those tables belongs to the user).
Try with:
$requests = Request::with('User')
->where('user_id',\Auth::user()->user_id)
->where('status', $status)
->orWhereRaw($status. ' = -1')
->where('paper_size', $paper_size)
->orWhereRaw($paper_size. ' = -1')
->orderBy(request('orderby') ? request('orderby') : 'created_at',
request('order') ? request('order') : 'DESC')->paginate(10);
I try to make a search engine for users. The search will be with multiple fields so as the user can be selecting whatever he want and get the result.
routes.php:
Route::get('search/{tag?}/{town?}/{education?}/{contract?}', 'DisplayJobs#getSearch');
DisplayJobs.php Controller
public function getSearch($tag = null, $town = null, $education = null, $contract = null)
{
//get already database values to send them to the form
$tags = \App\Tag::lists('name', 'id');
$contract = \App\Contract::lists('name', 'id');
$towns = \App\Town::lists('name', 'id');
$education = \App\Education::lists('name', 'id');
$tagQueryBuilder = Tag::query();
$townQueryBuilder = Town::query();
$educationQueryBuilder = Education::query();
$contractQueryBuilder = Contract::query();
if(Input::has('tag'))
{
$tagQueryBuilder->TagOfUser(Input::get('tag'));
}
if(Input::has('town'))
{
$townQueryBuilder->TownOfUser(Input::get('town'));
}
if(Input::has('education'))
{
$educationQueryBuilder->EducationOfUser(Input::get('education'));
}
if(Input::has('contact'))
{
$contractQueryBuilder->ContactOfUser(Input::get('contact'));
}
return view('main.search_jobs', compact('tags', 'towns', 'contract', 'education'));
}
If I try with each single query it works perfectly but I want to combined result data from all the queries or a way to query all the data at once.
In each model I have my query scope like this (Tag.php) Model:
public function jobs()
{
return $this->belongsToMany('App\Job');
}
public function scopeTagOfUser($query, $tag)
{
return $query->where('id', '=', $tag)->with('jobs');
}
After a lot of hours I found a solution. I will post it below so if anyone has the same problem can see one solution.
First I have delete all of the scope queries in the models and all of the work completed to the controller like bellow:
public function getSearch($tag = null, $town = null, $education = null, $contract = null)
{
//get already database values to send them to the form
$tags = \App\Tag::lists('name', 'id');
$towns = \App\Town::lists('name', 'id');
$contract = \App\Contract::lists('name', 'id');
$education = \App\Education::lists('name', 'id');
//get inputs from users
$getTagFromUser = Input::get('tag');
$getTownFromUser = Input::get('town');
$getContractFromUser = Input::get('contract');
$getEducationFromUser = Input::get('education');
$tagQuery = DB::table('jobs')
->join('job_tag', 'jobs.id', '=', 'job_tag.job_id')
->join('tags', 'job_tag.tag_id', '=', 'tags.id')
->where('tags.id', '=', $getTagFromUser);
$townQuery = DB::table('jobs')
->join('job_town', 'jobs.id', '=', 'job_town.job_id')
->join('towns', 'job_town.town_id', '=', 'towns.id')
->where('towns.id', '=', $getTownFromUser);
$contractQuery = DB::table('jobs')
->join('job_contract', 'jobs.id', '=', 'job_contract.job_id')
->join('contracts', 'job_contract.contract_id', '=', 'contracts.id')
->where('contracts.id', '=', $getContractFromUser);
$educationQuery = DB::table('jobs')
->join('job_education', 'jobs.id', '=', 'job_education.job_id')
->join('education', 'job_education.education_id', '=', 'education.id')
->where('education.id', '=', $getEducationFromUser);
$finalQuery = $tagQuery->union($townQuery)->union($contractQuery)->union($educationQuery)->get();
return view('main.search_jobs', compact('tags', 'towns', 'contract', 'education', 'finalQuery'));
}