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;
}
}
Related
How do I create a query statement for the Laravel Search Filter feature?
I'd like to combine the Laravel search query into one.
Now there is a problem with this code. It is not a multi-conditions superposition. I want to unify this query into one and get results that satisfy all conditions. What should I do?
//펜팔 메인 페이지
public function index (Request $request){
//base Object
$penpals = $this->penpalModel->getUsers();
//name search
if (!empty($request->name)) {
$users = $this->userModel->where('name', 'like', '%' . $request->name . '%')->get();
if (!empty($users)) {
$penpals->whereIn('user_id', $users);
}
}
//gender search
if (!empty($request->gender) && $request->gender !== 'all') {
$penpals->leftJoin('users', 'penpals.user_id', '=', 'users.id')
->select('penpals.*', 'users.gender')
->where('users.gender', $request->gender);
}
//country search
if (!empty($request->country) && $request->country !== 'all') {
$penpals->leftJoin('users', 'penpals.user_id', '=', 'users.id')
->select('penpals.*', 'users.country')
->where(['users.country', $request->country]);
}
// goal name search
if (!empty($request->goal) && $request->goal !== 'all') {
$penpals = $this->penpalModel->where('goal_id',$request->goal)->latest();
}
//age search
if($request->ageMin || $request->ageMax){
$ageMin = floor($request->ageMin);
$ageMax = floor($request->ageMax);
$penpals = $this->penpalModel->leftJoin('users', 'penpals.user_id', '=', 'users.id')
->select('penpals.*', 'users.age')
->whereBetween('users.age', [$ageMin, $ageMax]);
}
$penpalsData = $penpals->orderBy('penpals.created_at','desc')->paginate(12);
$penpalsCount = count($penpalsData);
return view('penpal.index')->with([
'penpals' => $penpalsData,
'penpalsCount' => $penpalsCount
]);
}
You should add relation user to penpal model.
class Penpal extends Model {
...
public function user()
{
return $this->belongsTo(User::class);
}
...
}
Then you can use whereHas eloquent method:
public function index (Request $request){
//query builder
$query = $this->penpalModel->query();
//user fields
if(
$request->name ||
$request->ageMin ||
$request->ageMax ||
($request->gender && $request->gender !== 'all') ||
($request->country && $request->country !== 'all')
){
$query->whereHas('user', function($query) use ($request){
if($request->name){
$query->where('name', 'like', '%' . $request->name . '%');
}
if($request->gender && $request->gender !== 'all'){
$query->where('gender', $request->gender);
}
if($request->country && $request->country !== 'all'){
$query->where('country', $request->country);
}
if($request->ageMin){
$query->where('age', '>', floor($request->ageMin));
}
if($request->ageMax){
$query->where('age', '<', floor($request->ageMax));
}
})
}
//goal
if ($request->goal && $request->goal !== 'all') {
$query->where('goal_id', $request->goal);
}
$penpals = $query
->with('user')
->latest()
->paginate(12);
return view('penpal.index')->with([
'penpals' => $penpals,
'penpalsCount' => $penpals->count() //use $query->count() to get count of all results in db, not only in paginator collection
]);
}
Unfortunately, this solution is not 100% copy of your code/idea because it lose selects, but filtering will work right and you could access user of each penpal like this:
$penpal->user->name //in php
penpal.user.name //in js
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');
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'));
}