If condition joined query in laravel - php

I have made a query in Laravel by joining 2 tables based on an IF condition.
I need to add a where query to filter data based on the material_id column from joined tables.
$transactions = DB::table('transactions')
->select('transactions.id', DB::raw("IF(transactions.is_sell = '1', advertisements.material_id, offerrequests.material_id) as material_id"))
->leftJoin('advertisements', function ($join) {
$join->on('advertisements.id', '=', 'transactions.post_id');
})
->leftJoin('offerrequests', function ($join) {
$join->on('offerrequests.id', '=', 'transactions.post_id');
});
I have tried the following and it is querying data with the requesting material_id from joined tables.
but also in the end i can see transaction values which are not similar to 'material_id' in the input.
I need to only get data which is exactly matches the same material id.
$transactions = $transactions->where(function ($query) use ($request) {
$query->where('advertisements.material_id', $request->material)
->orWhere('offerrequests.material_id', $request->material);
})->get();

try below ...Instead of orwhere try andWhere
$transactions = $transactions->where(function ($query) use ($request) {
$query->where('advertisements.material_id', $request->material)
->andWhere('offerrequests.material_id', $request->material);
})->get();
or
$transactions = $transactions ->where('advertisements.material_id', $request->material);
$transactions = $transactions ->where('offerrequests.material_id', $request->material);
$transactions = $transacions ->get();

Related

Get last record on GROUP BY using Laravel & MySql

I have two table (users and messages) .. I wrote a query to get all messages that users sent to me or I sent, using JOIN .. to get all the users I have contacted or they did.
as in the code below:
$users = Message::join('users', function ($join) {
$join->on('messages.sender_id', '=', 'users.id')
->orOn('messages.receiver_id', '=', 'users.id');
})
->where(function ($q) {
$q->where('messages.sender_id', Auth::user()->id)
->orWhere('messages.receiver_id', Auth::user()->id);
})
->orderBy('messages.created', 'desc')
->groupBy('users.id')
->paginate();
The problem here is when records grouped, I'm getting the old message not the new one according to its created_at .. So, I want to get the last record of the grouped records.
It seems like it would make more sense to make use of Eloquent's relationships here so that you can eager load the relationships instead of having to use join and group by:
$messages = Message::with('sender', 'receiver')
->where(function ($query) {
$query->where('sender_id', auth()->id())
->orWhere('receiver_id', auth()->id())
})
->orderByDesc('created') // is this meant to be 'created_at'?
->paginate();

How to use Eloquent model property in subquery?

I have two tables (users, posts) and I'm trying to order users according to recent post's date.
But unfortunately I couldn't find a way to use User model's firebase_id to use in subquery. I don't want to use raw query or DB directly if it's possible to use Eloquent for such query.
How can I use User model's firebase_id as subquery parameter?
Here is my non-working code to give an idea about what I try to do:
User::select('users.*', DB::raw("SELECT MAX(id) FROM posts WHERE posts.firebase_id = users.firebase_id as recent_post_date"))
->whereHas('posts', function ($q) {
$q->withCount('comments');
})
->with(['posts' => function ($q) {
$q->withCount('comments')
->orderBy('created_at', 'ASC');
}])
->orderBy('recent_post_date', 'DESC')
->get();
You can use selectSub to add a subquery.
Try the following
$recentPostQuery = Post::select('created_at')
->whereColumn('firebase_id', 'users.firebase_id')
->latest()
->limit(1)
->getQuery();
User::select('users.*')
->selectSub($recentPostQuery, 'recent_post_date')
->whereHas('posts', function ($q) {
$q->withCount('comments');
})
->with(['posts' => function ($q) {
$q->withCount('comments')
->orderBy('created_at', 'ASC');
}])
->orderBy('recent_post_date', 'DESC')
->get();
You can do with QueryBuilder and a join:
$users = DB::table('users')
->join('posts.firebase_id ', '=', 'users.firebase_id ')
->orderBy('posts.recent_post_date', 'DESC')
->get();
UPDATE
You asked for Eloquent. You can do it with whereHas.
$users = User::whereHas('posts', function (Builder $query) {
$query->orderBy('posts.recent_post_date', 'DESC');
})->get();

Combining inner join and where statements in Eloquent

I am trying to convert the following database query to use Eloquent:
$orderitems = DB::table('order_items')
->join('orders', 'orders.id', '=', 'order_items.order_id')
->where('orders.status', 1)
->where('order_items.sku', $sku)
->select('order_items.*')
->get();
I've tried the following:
$orderitems = Item::where('sku', $sku)
->with(['order' => function ($query) {
$query->where('status', 0);
}])
->get();
but it seems to be bringing back more results than it should. I can see from using DB::getQueryLog that the order_items query is not joining with the orders table:
select * from `order_items` where `stock_code` = ? and `order_items`.`deleted_at` is null
Do I need to create a new relationship between orderitems and order and add the additional where into that?
Relationships:
Order hasMany Items
Item hasOne Order
Solution was to use Query Scopes https://laravel.com/docs/5.7/eloquent#query-scopes
In the controller:
$orderitems = Item::stock($sku)->paginate(10);
In the orderitems model:
public function scopeStock($query, $sku)
{
return $query->join('orders', function ($join) {
$join->on('orders.id', '=', 'order_items.order_id');
$join->where('orders.status', '=', 1);
})
->select('order_items.*', 'orders.order_date')
->where('order_items.sku', $sku);
}

Laravel Eloquent query get users from another model

I have another table called tableb and it has a user relationship defined through the user_id field.
I want to run a query against tableb where a certain date is within a certain range but then I want to grab the user table associated with that row but I only want it to grab the user if it's not been grabbed yet. I'm trying to do this all in 1 DB query. I have most of it done, but I'm having trouble with the unique part of it.
Here's what I have right now:
$tableB = TableB::select('users.*')
->join('users', 'tableb.user_id', '=', 'users.id')
->where('tableb.start_date', '>', date('Y-m-d'))
->get();
So right now I have 3 entries in tableB from the same user, and ideally I'd like to only get 1 entry for that user.
How would I go about doing this?
Since you're selecting only users data, just add a groupBy clause in your query.
$tableB = TableB::select('users.*')
->join('users', 'tableb.user_id', '=', 'users.id')
->where('tableb.start_date', '>', date('Y-m-d'))
->groupBy('users.id')
->get();
You should just add groupBy like this :
$tableB = TableB::select('users.*')
->join('users', 'tableb.user_id', '=', 'users.id')
->where('tableb.start_date', '>', date('Y-m-d'))
->groupBy('users.id')
->get
Try This Code
App/user.php
public function getrelation(){
return $this->hasMany('App\tableB', 'user_id');
}
In Your Controller
Controller.php
use App/user;
public funtion filterByDate(user $user)
{
$date = '2016-02-01';
$result = $user->WhereHas('getrelation', function ($query) use($date) {
$query->whereDate('tableb.start_date', '>', $date)
->first();
});
}

laravel belongsToMany Filter

I have three tables as below:
users
id|name|username|password
roles
id|name
users_roles
id|user_id|role_id
These tables communicate via belongsToMany.
I would like to find a way to select all data in “users” table except ones that their user value of "role_id" is 5 in table “users_roles”.
How can I do it?
You should use whereDoesntHave() to select models that don't have a related model meeting certain criteria:
$users = User::whereDoesntHave('roles', function($q){
$q->where('role_id', 5);
})->get();
Use Laravel's Query Builder:
<?php
$users = DB::table('users')
->leftJoin('users_roles', 'user.id', '=', 'users_roles.user_id')
->where('users_roles.role_id', '!=', 5)
->get();
http://laravel.com/docs/4.2/queries
Or using Eloquent directly:
<?php
$users = User::whereHas('users_roles', function($q)
{
$q->where('role_id', '!=', 5);
})->get();
http://laravel.com/docs/4.2/eloquent#querying-relations
<?php
$users = User::whereHas('roles', function($query) {
$query->where('id', '<>', 5);
})
->orHas('roles','<', 1)
->get();
I think the correct answer is:
User::whereHas('roles', function ($query) {
$query->whereId(5)
}, '=', 0)->get();
This code should send a query that checks if the role with id=5 is related to the user or not.
Edit
While I think this should work but the #lukasgeiter answer is preferable.
In the end both methods use the has() to count the related models by using a subquery in the db query where clause but when you use the whereDoesntHave() it specifies the operator < and the count 1 itself.
You can var_dump(DB::getQueryLog()) in App::after()'s callback to see the actual query.

Categories