Laravel wherenotexists returning null - php

I have the following piece of code
$not_paid = Tenant::where('property_id', $property_id)
->whereNotExists(function ($query) use ($property_id) {
$query->select('user_id')
->from('rent_paids');
})
->get();
which is supposed to get all the tenants in a certain property, look them up in the rent_paids table and return the users who are not in the rent_paids table, as follows:
tenants table
Id
user_id
property_id
1
1
1
2
2
1
3
3
1
rent_paids
Id
user_id
property_id
amount_paid
1
1
1
3000
I want to be able to return the users in the tenants table and not in the rent_paids table. In this case, users 2 and 3. But the above code returns an empty array.

You're missing the where clause to tie it back to the original table.
$not_paid = Tenant::where('property_id', $property_id)
->whereNotExists(function ($query) use ($property_id) {
$query->select('user_id')
->from('rent_paids')
->whereColumn('tenants.user_id', '=', 'rent_paids.user_id');
})
->get();

Related

Joining nested tables with conditions in MySQL and Laravel

I'm building an application on Laravel 7 where I'm having following models:
Company (table name companies)
id name created_at
1 Sample company 1 2018-09-17 17:47:03
Contracts (table name contract_awards)
id name company_id project_id created_at
1 Sample Project involved 1 1 2018-09-17 17:47:03
Project (table name projects)
id name state region
1 Sample Project 1 XYZ State ABC Region
Categories
id name
1 Residential
2 Commercial
categories_projects_table
id categories_id project_id
1 2 1
Currently I'm fetching the companies and project details, where in companies are being fetched with its own filters/parameters and projects are being fetched with its own filters/parameters, I'm able to join projects table and fetch the result as per condition but while applying categories filter I'm unable to fetch the data. I'm not sure if I'm doing it correct or not, my code is following:
Company::leftjoin('contract_awards', function ($join) {
$join->on('companies.id', '=', 'contract_awards.awarded_by');
})
->leftjoin('projects', function ($q) {
$q->on('contract_awards.project_id', '=', 'projects.id')
->when(request('state'), function ($q) {
$q->whereIn('state', collect(request('state')->pluck('id')));
})
->when(request('region'), function ($q) {
$q->whereIn('region', collect(request('region'))->pluck('id'));
})
->when(request('categories'), function ($q) {
$q->leftjoin('categories_projects_table', function($q) {
$q->on('projects.id', '=', 'categories_projects_table.project_id');
})
// currently checking with static IDs later will be changed to collect(request('categories'))->pluck('id')
->select('categories_projects_table.categories_id as project_categories_id')
->whereIn('project_categories_id', [1]);
});
})
->select('companies.*', 'projects.name as project_name', 'projects.area as project_area')
->paginate(15);
I mean to say that I want to filter projects with its category relation, Above code gives me error:
column not found: 1054 Unknown column 'project_categories_id' in 'on clause' (SQL: select count(*) as aggregate from companies left join contract_awards on companies.`id .........
Any better approach in executing this is most welcomed, thanks in advance.

How to get ID from table only if it contains multiple values needed, from different rows

I have a channel_members table containing channel_id, user_id. I need to get the channel_id if there are multiple rows using that same channel_id which contains multiple user_id that I will provide.
Example:
If there are 5 rows in the table
CHANNEL_ID | USER_ID
2 | 2
2 | 3
2 | 4
3 | 2
3 | 4
I need to get the channel_id which are being used by user_id 2, 3, and 4. So based in the table above that I provided. I should get channel_id 2.
I assume you have already defined your relations uisng models, As per your provided description, channel has many to many relation with user
class Channel extends Model
{
public function members()
{
return $this->belongsToMany('App\User', 'channel_members', 'channel_id', 'user_id');
}
}
Using eloquent realtions you can check existance of related models as
$channels = App\Channel::whereHas('members', function ($query) {
$query->where('id', '=', 2);
})->whereHas('members', function ($query) {
$query->where('id', '=', 3);
})->whereHas('members', function ($query) {
$query->where('id', '=', 4);
})->get();
Above will return you only channels who have associations with all 3 users based on supplied id
Querying Relationship Existence
SELECT CHANNEL_ID
FROM channel_members
WHERE USER_ID in (2,3,4)
GROUP BY CHANNEL_ID
HAVING COUNT(CHANNEL_ID) > 0

How to grab only latest update record from data table in Laravel 5.6?

I have following table name as projects like this structure,
id name adtype created_at updated_at
1 gobba 1 2018-02-25 2018-02-25
2 manna 0 2018-04-25 2018-04-25
3 alaya 1 2017-12-28 2017-12-28
I need grab only one result witch related to latest updated record and adtype == 1, I code following controller, for this,
public function showad()
{
$projects = Vehicle::with('uploads')
->where('adtype','=',1)
->latest('updated_at');
return view('vehicles.slider')->withProjects($projects);
but this working but not filtering latest updated records. how can correct this?
Try using ORDER BY and LIMIT:
$projects = Vehicle::with('uploads')
->where('adtype', '=', 1)
->orderBy('updated_at', 'desc')
->take(1)
->get();
This should correspond to the following raw MySQL query:
SELECT *
FROM uploads
WHERE adtype = 1
ORDER BY updated_at DESC
LIMIT 1;

Laravel filter based on has one relationship

I am pulling my hair out over this one, and I feel like I have tried every method!
Here is my problem.
I have 2 tables
USERS
ID | FIRSTNAME | EMAIL_ADDRESS
1 | Joe Bloggs | joe#bloggs.com
STATUS
ID | USER_ID | STATUS | DATE
1 | 1 | 'In' | 2018-06-04 09:01:00
2 | 1 | 'Out' | 2018-06-04 09:00:00
As you can see by the tables above, each user can have many status', but each user has to have 1 most recent status, which I am doing like this (please tell me if I am doing it wrong)
public function statusCurrent(){
return $this->hasOne('App\Status', 'user_id', 'id')->orderBy('date', 'desc')->limit(1);
}
I then a form on in my view, which passes filters to the controller via a $request.
I need to be able to use the filters, and apply them to the 1 most recent status. For example, if someone searches for the date 2018-06-04 09:00:00 and a user id 1, I need it to show NO RESULTS, because the 1 most recent record for that user does not match that date, but at the moment, it will just jump over the one most recent if it doesn't match, and get the next record that does.
I have tried what seems like every method, I have tried like this
$users = Users::with(['StatusCurrent' => function($query){
$query->where('status.status', 'In');
}])->get();
Which gets the correct most recent row, but then if i try status.status, 'out' instead, it just jumps over and gets record number 2 where the status is out.
I've also tried like this
$users = Users::has('StatusCurrent')->paginate(10);
if(!empty($request->statusIn)){
$users = $users->filter(function ($item){
$item = $item->statusCurrent->status == 'in';
return $item;
});
}
return $users;
Which works great but then the pagination breaks when trying to append any GET parameters for the filters.
Plain English
I need to be able to get the most recent status for the user, then once I have it, I need to be able to apply where statements/filters/arguments to it, and if they don't match, completely ignore that user.
You have to combine a JOIN with a subquery:
$users = User::select('users.*')
->join('status', 'users.id', 'status.user_id')
->where('status.status', 'in')
->where('status.id', function($query) {
$query->select('id')
->from('status')
->whereColumn('user_id', 'users.id')
->orderByDesc('date')
->limit(1);
})
->get();
You can get the ID first, then do your query with filters:
$status_id = Users::find($user_id)->statusCurrent()->id;
Now do the actual query, using $status_id in whereHas clause:
$users = Users::with('statusCurrent')
->whereHas('statusCurrent', function($query) use($status_id) {
$query->where('status.status', 'In')
->where('id',$status_id);
})->get();
The relationship should be like:
public function statusCurrent(){
return $this->hasOne('App\Status', 'user_id', 'id')->latestOfMany();}

How to get data from another table using ID from another table

I would like to get a data from a table to another table using it's primary key.
products_table:
id name type_id date_added
1 item1 2 1234
2 item2 2 5678
3 item3 1 0000
product_type_table:
id type_name
1 type1
2 type2
3 type3
I am querying the first table using this code:
Products::select('name','type_id')->where('id',$id)->get()
Now, how do I automatically get the type_name from the product_type_table using the type_id from the products_table?
As Jack Skeletron pointed out, the Laravel documentation has examples for joining 2 or multiple tables.
In your case
$products = DB::table('products_table')
->join('product_type_table', 'products_table.type_id', '=', 'product_type_table.type_id')
->select('products_table.name, products_table.type_id')
->where('id', $id)
->get();
you can use left join.
DB::table('product_type_table')
->leftJoin('products_table', 'product_type_table.id', '=', 'products_table.type_id ')->where('product_type_table.id',$id)
->get();
In Product Model add Below code for joining 2 tables:
use App\Models\ProductType;
public function type()
{
return $this->belongsTo(ProductType::class);
}
and change the line:
Products::select('name','type_id')->where('id',$id)->get()
to
Products::select('name','type_id')->with(['type' => function($q){
return $q->select('type_name');
}])->where('id',$id)->get()
Hope this works for you.

Categories