Laravel query builder advanced wheres AND, OR - mysql

$query = new TableA;
$query = $query->join('tableB', 'tableA.b_id', '=', 'tableB.id');
$query = $query->where('tableB.something', '=', '1');
$query = $query->where('tableA.something_else', '=', '2');
And it produces:
WHERE something=1 AND something_else=2 AND .. AND....
BUT now - I need this:
WHERE something=1 AND something_else=2 AND (city=city1 OR city=city2 OR city=city3) AND (country=country1 OR country=country2)
Any ideas?

Make use of Advanced Wheres. For your example, it'd be something like this:
->where(function ($query) {
$query->where('city', '=', city1)
->orWhere('city', '=', city2)
->orWhere('city', '=', city3);
})->where(function ($query) {
$query->where('country', '=', country1)
->orWhere('country', '=', country2);
});

Quick method. Read about raw expressions:
http://laravel.com/docs/queries#raw-expressions

Related

Laravel 8 How to join 2 tables and check if a value exists

I'm having trouble in querying 2 tables.
Basically I have a 'black_list' table with 2 columns 'user_id' and 'block_id', where 'user_id' is the current user and 'block_id' is the blocked user. The other table is 'users' where there are the information of the registered users.
In my site I have a page where users are searched, my problem is that if id1 blocked id2, when id2 searches id1 it should not be displayed, so in the table 'black_list' I will have these values ​​user_id = 1 and block_list = 2
I've tried so many ways, but I'm not succeeding, can you help me? Excuse my English
public function search(Request $request){
$id= Auth::id();
$query = $request->query('query');
$utentis = DB::table('black_lists')
->join('users', 'users.id', '=', 'users.id')
->where('users.id', '!=', $id)
->where('users.name', 'like', '%' . $query . '%')
->where('black_lists.user_id', '!=', 'users.id')
->orWhere('users.cognome', 'like', '%' . $query . '%')
->where('black_lists.user_id', '!=', 'users.id')
->where('users.id', '!=', $id)
->orWhere('users.username', 'like', '%' . $query . '%')
->where('black_lists.user_id', '!=', 'users.id')
->where('users.id', '!=', $id)
->select('users.id', 'users.name', 'users.fotoProfilo')
->get();
if ($utentis->count() > 0) {
return response()->json($utentis);
}
}
I assume you create a many-to-many relationship between users and black_list is a pivot table.
public function search(Request $request)
{
$id = $request->id;
return User::where('id', $id)
->whereDoesntHave('blocks', function($query) use ($id) {
$query->where('user_id', '!=', $id);
}),
]);
}
UPDATE
// User.php
public function blocks()
{
return $this
->belongsToMany(User::class, 'black_list', 'block_id', 'user_id')
->using(BlackList::class)
->withTimestamps();
}
Notes:
The column names may be in the wrong order because I always mix them. Look at the documentation for more info.
If you created a model for pivot table you need to add ->using(BlackList::class)
If you have BlackList.php, you need to extend it to Pivot rather than Model.
Thanks to both of you for the prompt reply. Unfortunately it returns me null with #gbalduzzi solution. I try to attach a screen of the tables.
The variable $id = Auth::id();
enter image description hereWhen I run the query, it should return me the user profile only if in the black_list table there is no user_id == "user id that blocked me" and block_id == $ id. Thanks again for your help.
Perfect works great, thanks so much for the help
public function search(Request $request)
{
$id= Auth::id();
$query = $request->query('query');
$utentis = User::where('users.id', '!=', $id)
->where(function ($filter) use ($query) {
$filter->where('users.name', 'like', '%' . $query . '%')
->orWhere('users.cognome', 'like', '%' . $query . '%')
->orWhere('users.username', 'like', '%' . $query . '%');
})
->whereDoesntHave('blocks', function ($query) use ($id) {
$query->where('black_lists.block_id','=', $id)
->where('black_lists.user_id','!=', 'users.id');
})
->select('users.id', 'users.name', 'users.fotoProfilo')
->get();
//Log::debug($utentis);
if ($utentis->count() > 0) {
return response()->json($utentis);
}
}

How can I use 'AS' in my count query?

How can I use AS in my count query?
Actually i want to result like { "count":"number" } for json result. I dont know what should i call this thing?
public function firstHourTrades(){
$user_id = Auth::user()->id;
$data = DB::table('finaltrade')
->join('exchanges', 'finaltrade.exchange_id', '=', 'exchanges.id')
->where('finaltrade.user_id', $user_id)
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '>=', DB::raw('exchanges.start_time'))
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '<=', DB::raw("ADDTIME(exchanges.start_time, '1:00:00')"))
->count();
return response()->json($data);
}
You could also do a raw select and manually assign the alias:
$data = DB::table('finaltrade')
->select(DB::raw('count(*) as count'))
->join('exchanges', 'finaltrade.exchange_id', '=', 'exchanges.id')
->where('finaltrade.user_id', $user_id)
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '>=', DB::raw('exchanges.start_time'))
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '<=', DB::raw("ADDTIME(exchanges.start_time, '1:00:00')"))
->get();

Join the same table with two different column laravel

I try these code in MySQl:
SELECT
A.*,
B.name,
C.name
FROM
eventlog_tbl as A
LEFT JOIN users B ON A.byuser=B.email
LEFT JOIN users C ON A.affectiveuser=C.email;
I try these in Laravel
return DB::table('eventlog_tbl')
->leftjoin('users', 'users.email', '=', 'eventlog_tbl.byuser')
->leftjoin('users', 'users.email', '=', 'eventlog_tbl.affectiveuser')
->select('eventlog_tbl.*','users.name','users.name')
->get();
How can i convert it to Laravel?
Try below code:
$res = DB::table('eventlog_tbl')
->leftjoin('users AS A', 'A.email', '=', 'eventlog_tbl.byuser')
->leftjoin('users AS B', 'B.email', '=', 'eventlog_tbl.affectiveuser')
->select('eventlog_tbl.*','A.name as byuser_name','B.name as affectiveuser_name')
->get();
print_r($res);
This is your query written using the Laravel query builder.
$events = DB::table('eventlog_tbl')
->select('eventlog_tbl.*', 'users_1.name', 'users_2.name')
->leftJoin('users AS users_1', 'users_1.email', '=', 'eventlog_tbl.byuser')
->leftJoin('users AS users_2', 'users_2.email', '=', 'eventlog_tbl.affectiveuser')
->get();
Edit:
$events = DB::table('eventlog_tbl')
->select('eventlog_tbl.*', 'users_1.name AS user_1', 'users_2.name AS user_2')
->leftJoin('users AS users_1', 'users_1.email', '=', 'eventlog_tbl.byuser')
->leftJoin('users AS users_2', 'users_2.email', '=', 'eventlog_tbl.affectiveuser')
->get();
The problem is that both name columns are called the same thing. As per the accepted answer, these will need to be aliased differently too.
Why don't you convert this to use relationships? I have probably got the relationships wrong, something like this:
class EventLog extends Model
{
public function byUser()
{
return $this->hasOne(User::class, 'byuser', 'id');
}
public function affectiveUser()
{
return $this->hasOne(User::class, 'affectiveuser', 'id');
}
}
And then
$event_log = EventLog::with(['byUser', 'affectiveUser')->all();
foreach ($event_log as $item) {
echo $item->byUser->email();
}

Comparing timestamp and Carbon::now()->toTimeString() without seconds

I am building a query which will be executed every minute when the daily_at time and the current time are equal. The daily_at variable is a timestamp of for example 10:05:33.
I want the where clause in the query to pass when the hour and minute are the same, but not the second else almost non will be executed. The where clause which I have now:
DB::table('restaurants')
->where('schedule', '=', $schedule)
->where('active', '=', 1)
->whereDate('start_at', '<=', Carbon::today())
->where('daily_at', '=', Carbon::now()->toTimeString())
.....
Could someone help me to adjust the where clause to ignore the seconds?
Try with:
DB::table('restaurants')
->where('schedule', '=', $schedule)
->where('active', '=', 1)
->whereDate('start_at', '<=', Carbon::today())
->where('daily_at', '=', Carbon::now()->format('H:i'))
One more way:
DB::table('restaurants')
->where('schedule', '=', $schedule)
->where('active', '=', 1)
->whereDate('start_at', '<=', Carbon::today())
->where('daily_at', '=', Carbon::createFromTime(Carbon::now()->hour,Carbon::now()->minute,00)->format('H:i:s'))
You can pass an extra argument to set timezone:
Carbon::createFromTime(Carbon::now()->hour,Carbon::now()->minute,00,'Example/Zone')->format('H:i:s')
I found the solution. You can use setSeconds(int $value) method:
Carbon::now()->setSeconds(0)->toTimeString()
DB::table('restaurants')
->where('schedule', '=', $schedule)
->where('active', '=', 1)
->whereDate('start_at', '<=', Carbon::today())
->where('daily_at', '=', Carbon::now('Y-m-d H:i')->toTimeString())
use this code
Can you please try with this way:
whereRaw(DATE_FORMAT(daily_at, "%H:%i") = Carbon::now()->format('H:i'))
So final query would be,
DB::table('restaurants')
->where('schedule', '=', $schedule)
->where('active', '=', 1)
->whereDate('start_at', '<=', Carbon::today())
->where('daily_at', '=', Carbon::now()->toTimeString())
->whereRaw(DATE_FORMAT(daily_at, "%H:%i") = Carbon::now()->format('H:i'))

Where clause on join query laravel 4.2

I have 2 tables 'users' and 'instantUsers'. I want to join them on users.id = instantUsers.user_id and want to add 2 where clauses on the resulting. I'm not getting how to do both. The query I'm using is -
DB::table('users')
->join('instantUsers', function($join) use ($userId) {
$join->on('users.id', '=', 'instantUsers.user_id');
})
->where('instantUsers.instantMode', '=', '1')
->where (function($query) use ($userId) {
$query->where('instantUsers.user_id', '!=', $userId);
})
->get();
You can try this one maybe this will help you:
DB::table('users as table1')->join('instantUsers as table2','table1.id','=','table2.fkId') ->where('table2.instantMode','=','1')->where('table2.user_id','!=',$userId)->get();
Your 'instantUsers.instantMode','=','1' expression can be done in a join, resulting in a better performance.
I would write it like this
DB::table('users')
->join('instantUsers', function($join) use ($userId) {
$join
->on('users.id', '=', 'instantUsers.user_id')
->on('instantUsers.instantMode', '=', 1);
})
->where('users.id', '!=', $userId)
->get();