I have Eloquent statement in Laravel 4.2 that looks like this
$user_message_block = Message::where('responder_id', '=', Auth::user()->id)
->where('user_id', '=', $user->id)->first();
Then if $user_message_block doesn't exist I also have to check for a reverse case scenario and I do it like this...
if(!$user_message_block){
$user_message_block = Message::where('responder_id', '=', Auth::user()->id)
->where('user_id', '=', $user->id)->first();
}
What I really would like to do is run a single query that checks for both scenarios at once..
In pseudo expression I need something like this:
$user_message_block = Message::where('responder_id', '=', Auth::user()->id,
'AND', 'user_id', '=', $user->id,
'OR', 'responder_id', '=', $user->id,
'AND', 'user_id', '=', Auth::user()->id)->first();
So basically I need to
SELECT Message where (responder_id=x AND user_id=y) OR where (responder_id=y AND user_id=x)
How could I do this using Eloquent. I am unable to find more about OR and AND statements used with Eloquent.
Thanks!
UPDATE:
After more looking I found that this seems to work (still testing a lot)
$user_message_block =
Message::where(['responder_id' => Auth::user()->id, 'user_id' => $user->id])
->orWhere(['user_id' => Auth::user()->id, 'responder_id' => $user->id])
->first();
OR
$user_message_block =
Message::where(['responder_id' => Auth::user()->id, 'user_id' => $user->id])
->orWhere(['user_id' => Auth::user()->id, 'responder_id' => $user->id])
->get();
Are there any drawbacks to this that I need to consider?
It may be very complicated to do in Eloquent but this does exactly what you need using Laravel's query builder without reverting to raw SQL.
DB::table('messages')
->where(function($query)
{
$query->where('responder_id', '=', 'x')
->where('user_id', '=', 'y');
})
->orWhere(function($query) {
$query->where('responder_id', '=', 'y')
->where('user_id', '=', 'x');
})
->get();
This is what I get from running a toSql() on it:
select * from `messages` where (`responder_id` = ? and `user_id` = ?) or (`responder_id` = ? and `user_id` = ?)
Try this to see if it works with Eloquent.
Message::where(function($query) {
$query->where('responder_id', '=', 'x')
->where('user_id', '=', 'y');
})->orWhere(function($query) {
$query->where('responder_id', '=', 'y')
->where('user_id', '=', 'x');
})->get();
It should work.
I credited Noah for the solution on account of providing a working solution and the effort he made in helping me out. I did end up using a different solution however..
$user_message_block =
Message::where(['responder_id' => 'x', 'user_id' => 'y'])
->orWhere(['user_id' => 'x', 'responder_id' => 'y'])
->get();
In my speciffic case I only need the first record found so this works for me
$user_message_block =
Message::where(['responder_id' => 'x', 'user_id' => 'y'])
->orWhere(['user_id' => 'x', 'responder_id' => 'y'])
->first();
Suffice it to say,, I found a solution similar to mine in phpacademy videos by Alex. And I stumbled upon this too Laravel eloquent SQL query with OR and AND with where clause
Related
I want to fetch count requests by status for each request
I use this code and it works, but I don't think it's correct
'requests_count' => Request::where('user_id', auth()->id())
->addSelect([
'active' => Request::selectRaw('count(id)')
->where('status', 'active')
->where('user_id', auth()->id())
])
->addSelect([
'pause' => Request::selectRaw('count(id)')
->where('status', 'pause')
->where('user_id', auth()->id())
])
->addSelect([
'pending' => Request::selectRaw('count(id)')
->where('status', 'pending')
->where('user_id', auth()->id())
])
->addSelect([
'unapproved' => Request::selectRaw('count(id)')
->where('status', 'unapproved')
->where('user_id', auth()->id())
])
->first()
Is there a better and more effective way?
This question already has answers here:
Laravel - Method Illuminate\\Support\\Collection::makeHidden does not exist
(4 answers)
Closed 1 year ago.
I want to hide the columns password & OTP ,that is included in $users result. Actually these 2 columns are part of the users table. My ultimate need is that i need to join 3 tables : users,location,user_technical_details and want to hide the password & OTP columns in the users table. Can use any methods. Through any methods, i want to attain this result I've tried many methods. Nothing works. How to solve this? Any suggestions..
Things i tried:
1)
$users = DB::table('users')
->join('location', 'users.id', '=', 'location.id')
->join('user_technical_details', 'users.id', '=', 'user_technical_details.id')
->get();
$d=$users->makeHidden(['password','OTP']);
return response()->json([
'message' => 'profile viewed successfully',
'data' => $d,
'statusCode' => 200,
'status' => 'success'],200);
This generates the error - Method Illuminate\\Support\\Collection::makeHidden does not exist
2)
$users = DB::table('users')
->join('location', 'users.id', '=', 'location.id')
->join('user_technical_details', 'users.id', '=', 'user_technical_details.id')
->get();
$exclude_columns=['password','OTP'];
$get_columns = array_diff($users, $exclude_columns)->get();
return response()->json([
'message' => 'profile viewed successfully',
'data' => $get_columns,
'statusCode' => 200,
'status' => 'success'],200);
3)
$users = DB::table('users')
->join('location', 'users.id', '=', 'location.id')
->join('user_technical_details', 'users.id', '=', 'user_technical_details.id')
->get();
$d=collect($users->toArray())->except(['password','OTP']);
return response()->json([
'message' => 'profile viewed successfully',
'data' => $d,
'statusCode' => 200,
'status' => 'success'],200);
4)
protected $hidden = ['password','OTP'];
5)
$users = DB::table('users')->exclude(['password','OTP','ph_OTP','email_OTP','user_access_token','remember_token'])
->join('location', 'users.id', '=', 'location.id')
->join('user_technical_details', 'users.id', '=', 'user_technical_details.id')
->get();
return response()->json([
'message' => 'profile viewed successfully',
'data' => $users,
'statusCode' => 200,
'status' => 'success'],200);
This generates the Error -Call to undefined method Illuminate\\Database\\Query\\Builder::exclude()
when you want to limit the attributes, such as passwords, that are included in your model's array or JSON representation. To do so, add a $hidden property to your model. In attributes that are listed in the $hidden property's array will not be included in the serialized representation of your model:
class User extends Model
{
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = ['password','OTP'];
}
now in your code you have to use User model instead of DB facade:
$users = User::query()
->join('location', 'users.id', '=', 'location.id')
->join('user_technical_details', 'users.id', '=', 'user_technical_details.id')
->get();
now, $users will not have the hidden attributes
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a bulk list of employees and their related information from other tables. I want to create a leave roster at once for all of them and also have an option to select a single employee and insert or update the respective roaster record. I have some codes here please assist how to accomplish that.
<?php
namespace App\Http\Controllers\Employee;
use App\LeaveSetting;
use App\Roaster;
use App\User;
use Carbon\Carbon;
use DB;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class LeaveRoasterController extends Controller
{
public function prepare(){
$employees = DB::table('users')
->leftJoin('job_details', 'users.id', '=', 'job_details.user_id')
->leftJoin('terminations', 'terminations.user_id', '=', 'users.id')
->leftJoin('departments', 'departments.id', '=','job_details.department')
->where('termination_status', '!=', 3)
->select('users.id AS employee_id', 'users.name AS name', 'departments.department AS department')
->orderBy('name', 'ASC')
->get();
return view('employee.roaster', compact('employees'));
}
public function submitRoaster(Request $request){
$roaster_exist = Roaster::all()->where('leave_year', '=', financial_year())->count();
if ($roaster_exist > 0){
DB::table('roasters')->where('leave_year', '=', financial_year())->delete();
}
foreach ($user_id = $request->user_id as $key => $value) {
if ($user_id[$key] != '') {
$from = $request->start_date[$key];
$end = $request->end_date[$key];
$data = [
'user_id' => $value,
'leave_year' => financial_year(),
'leave_setting_id' => 1,
'start_date' => $from,
'end_date' => $end,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()];
DB::table('roasters')->insert($data);
}
}
flash('You have submitted leave roaster successfully!');
return back();
}
Use updateOrInsert method...
$query = DB::table("roasters")
->updateOrInsert(
[
'id' => $update_id, // pass your update id else empty
],
[
'user_id' => $value,
'leave_year' => financial_year(),
'leave_setting_id' => 1,
'start_date' => $from,
'end_date' => $end,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
I have this query:
User::leftJoin('friends', function ($join) {
$join->on('friends.user_id_1', '=', 'users.id')
->orOn('friends.user_id_2', '=', 'users.id');
})
->where(function ($query) use ($myID) {
// Group orwhere functions so the query builder knows these belong together
$query->where([
'friends.user_id_1' => $myID,
'friends.accepted' => true
])
->orWhere([
'friends.user_id_2' => $myID,
'friends.accepted' => true
]);
})
->where('users.id', '!=', $myID) // Exclude the user with id $myID
->get();
https://stackoverflow.com/a/41832867/5437864
I want to use this query twice, but with a different where clause. Is it possible to reuse this query without copying the whole code? And if so, how?
I used the PHP clone keyword. I'm not sure if this is the best solution, but it helps. Any other suggestions are welcome.
$friends_query = User::leftJoin('friends', function ($join) {
$join->on('friends.user_id_1', '=', 'users.id')
->orOn('friends.user_id_2', '=', 'users.id');
})
->where(function ($query) use ($myID) {
// Group orwhere functions so the query builder knows these belong together
$query->where([
'friends.user_id_1' => $myID,
'friends.accepted' => true
])
->orWhere([
'friends.user_id_2' => $myID,
'friends.accepted' => true
]);
});
$friends_me = clone $friends_query;
$friends_me = $friends_me->where('users.id', '!=', $myID);
$friends_others = clone $friends_query;
$friends_others = $friends_others->where('users.id', '=', $myID);
$query = User::leftJoin('friends', function ($join) {
$join->on('friends.user_id_1', '=', 'users.id')
->orOn('friends.user_id_2', '=', 'users.id');
})
->where(function ($query) use ($myID) {
// Group orwhere functions so the query builder knows these belong together
$query->where([
'friends.user_id_1' => $myID,
'friends.accepted' => true
])
->orWhere([
'friends.user_id_2' => $myID,
'friends.accepted' => true
]);
});
Adding extra where to existing query
$query->where('users.id', '!=', $myID)
$query->get();
Check this link for another example
Example
I have the snippet of code, I want the the following query to pull all products associated with category, a belongs to many relationship.
That works, but even though I have declare a select, it still retrieves every column in product, i just want the four columns which I declare.
I look over and read the documentation at http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html
$Product= $categoryObj->find()->contain([
'Product' => function ($q) {
return $q
->select(['name', 'url', 'published', 'site_id'])
->where(['published' => 1, 'site_id' => 2]);
}
])
->where(['id'=> $id])
->toArray();
Try adding autoFields(false) after the select(). The code would be as follows:
$Product= $categoryObj->find()
->contain([
'Product' => function ($q) {
return $q
->select(['name', 'url', 'published', 'site_id'])
->autoFields(false)
->where(['published' => 1, 'site_id' => 2]);
}
])
->where(['id'=> $id])
->toArray();