Laravel join query using Laravel eloquent - php

i have two tables 'users' and 'projects'
Table users
-----------------------------------
user_id | name | email | password |
-----------------------------------
1 |name1 |email1 | password1|
-----------------------------------
2 |name2 |email2 | password2|
Table projects
project_id |user_id | name |
--------------------------------------
1 | 1 | project_name1 |
-----------------------------------
2 | 1 | project_name2 |
There is no relation between these two tables but user_id in projects are the id from user table.
Normal Query
SELECT a.user_id,a.name AS username,b.name AS project_name FROM users a LEFT JOIN projects b ON a.user_id=b.user_id;
I want the same query execution in laravel eloquent.
Have searched in google got some idea about "with" function but not able to get the output.
Thanks.

This is the way you should use Eloquent:
create User.php
<?php
class User extends Eloquent
{
public function projects()
{
return $this->hasMany('Project');
}
}
create Project.php
<?php
class Project extends Eloquent
{
}
On controller, write this to get all users, with related projects inserted inside each users:
$users = User::with('projects')->all();
foreach($users as $user)
{
$project_of_this_user = $user->projects;
}

You can simply do as following,
DB::table('users')
->join('projects =', 'users.id', '=', 'posts.user_id')
->select('*')
->get();
For more details you can refer laravel Docs

This should be what you need:
DB::table('users')
->join('projects', 'projects.user_id', '=', 'users.user_id')
->select('users.user_id', 'users.name as username', 'projects.name as project_name')
->get();

I think, this one helps you out
DB::table('users')
->leftJoin('projects', 'users.user_id', '=', 'projects.user_id')
->select('users.user_id', 'users.name as username', 'projects.name as project_name')
->get();

Related

how join laravel tables to get non intersected data

in my Laravel app I have 3 tables : users, documents and type_documents, the user have multiple documents and document have one type_document
| Documents |
| -------- |
| id |
| file |
| type_document_id|
| user_id |
| type_documents |
| -------- |
| id |
| name |
| users |
| -------- |
| id |
| name |
| type_document_d|
I want select the types that are not used in documents table for the current user with eloquent
I try with this, but it give me the used type_documents :
$document_types = TypeDocument::leftJoin('docments' , function ($join) {
$join->on('type_documents.id', '=', 'douments.type_document_id')
->where('documents.user_id', auth()->id());
})
->applyFilters($request->all())
->latest()
->paginateData($limit);
I use Laravel version 8
Using Eloquent relation defined between TypeDocument::class and User::class like this:
TypeDocument.php
public function users()
{
return $this->belongsToMany(User::class, 'documents', 'type_document_id', 'user_id')->withPivot('file');
}
The you can easily get the type document not linked to a specific user like this
TypeDocument::whereDoesntHave('users', function($userQuery) {
$userQuery->where('users.id', '=', auth()->id());
})
->applyFilters($request->all())
->latest()
->paginateData($limit);
--------------EDIT--------------
IF you want to use two step relation, you can define it like this:
TypeDocument.php
public function documents()
{
return $this->hasMany(Document::class);
}
Document.php
public function user()
{
return $this->belongsTo(User::class);
}
And use the relations to query it like this:
TypeDocument::whereDoesntHave('documents.user', function($userQuery) {
$userQuery->where('users.id', '=', auth()->id());
})
->applyFilters($request->all())
->latest()
->paginateData($limit);
Have you tried whereNotExists() or whereNotIn() instead of leftJoin()?
eg:
<?php
// whereNotIn
$types = TypeDocument::whereNotIn('id', function($query) {
$query->select('type_document_id')
->from('documents')
->where('user_id', auth()->id);
})->get();
<?php
// whereNotExists
$types = TypeDocument::whereNotExists(function($query) {
$query->select(DB::raw(1))
->from('documents')
->whereRaw('type_documents.id = documents.type_document_id')
->where('user_id', '=', Auth::user()->id);
})->get();
<?php
// leftJoin
$types = TypeDocument::leftJoin('documents', function($join) {
$join->on('type_documents.id', '=', 'documents.type_document_id')
->where('user_id', '=', Auth::user()->id);
})->whereNull('documents.type_document_id')->get();
try any of these!
Check this solution
TypeDocument::whereNotIn('id', function($query){
$query->select('type_document_id')
->from(with(new Documents)->getTable())
->where('type_document_id', $query->id)
->where('user_id', auth()->id());
})->get();

Laravel distinct on join one to many

I've found a couple of questions online similar to mine, but I can't seem to find a working answer.
I have 2 tables
USER
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
I need to be able to Join the 2 tables together but only get the most recent status column by date, like this
ID | FIRSTNAME | EMAIL_ADDRESS | STATUS_ID | STATUS | DATE
1 | Joe Bloggs | Joe#bloggs.com | 1 | 'In' | 2018-06-04 09:01:00
I need to be able to run extra query builder arguments like where, because the user has the ability to pass in filters and search parameters if they require, so to be able to use the status table columns in my query builder, i'm doing a join like this
$users = Users::join('status', 'status.user_id', '=', 'user.id')->distinct('user.id');
Which then allows me to pass in any search parameters if I need them
if(!empty($request->search)){
$param = $request->search;
$users = $users->where(function($query) use ($param){
$query->where('users.firstname', 'like', '%'.$param.'%')
->orWhere('users.email_address', 'like', '%'.$param.'%');
});
}
if(!empty($request->dateFrom)){
if(!empty($request->dateTo)){
$users = $users->whereRaw('DATE(status.date) BETWEEN ? AND ?', [$request->dateFrom, $request->dateTo]);
} else {
$users = $users->whereRaw('DATE(status.date) BETWEEN ? AND DATE(NOW())', [$request->dateFrom]);
}
}
Then run my get() at the end
if($method == 'paginate'){
$users = $users->paginate(10);
} else {
$users = $users->get();
}
This returns the following
ID | FIRSTNAME | EMAIL_ADDRESS | STATUS_ID | STATUS | DATE
1 | Joe Bloggs | Joe#bloggs.com | 1 | 'In' | 2018-06-04 09:01:00
2 | Joe Bloggs | Joe#bloggs.com | 1 | 'Out' | 2018-06-04 09:00:00
I need to be able to use the foreign table columns as arguments in my Where functions, but I need to only return 1 row per user. How do I run a join, but only return 1 row for each of my users?
To get latest record for each user you can use a self join for status table
select u.*,s.*
from user u
join status s on u.id = s.user_id
left join status s1 on s.user_id = s1.user_id
and s.date < s1.date
where s1.user_id is null
Using query builder you might rewrite it as
DB::table('user as u')
->select('u.*', 's.*')
->join('status as s', 'u.id ', '=', 's.user_id')
->leftJoin('status as s1', function ($join) {
$join->on('s.user_id', '=', 's1.user_id')
->whereRaw(DB::raw('s.date < s1.date'));
})
->whereNull('s1.user_id')
->get();
Laravel Eloquent select all rows with max created_at
Laravel - Get the last entry of each UID type
Laravel Eloquent group by most recent record
Since you are using Laravel lets make the solution a bit more understandable and easier:
First Lets create the models for each table:
class User extends Model
{
public $timestamps = false;
protected $fillable = [
'FIRSTNAME',
'EMAIL_ADDRESS'
];
public function status(){
return $this->hasMany(\App\Status::class);
}
}
Now lets create the Status Model:
class Status extends Model
{
public $timestamps = false;
protected $casts = [
'USER_ID' => 'int',
];
protected $fillable = [
'USER_ID',
'STATUS',
'DATE'
];
public function user()
{
return $this->belongsTo(\App\User::class);
}
}
Now you can use Eloquents like this:
$result=User::whereHas('Status', function($q){
$q->where('date', $current_date);
})->distinct('id')->get();
Hope it Helps!

Laravel 5.6 Eloquent ORM where join table

I am dealing with Eloquent ORM collections and query builders. I am trying to figure out how to join and use "where" in a collection, like in query builder.
For example, I have the following tables:
Users:
ID | Name | Last name
-------------------------
1 | Martin | Fernandez
2 | Some | User
Persons:
ID | Nick | User_ID | Active
----------------------------------
1 | Tincho | 1 | 1
Companies:
ID | Name | User_ID | Active
----------------------------------
1 | Maramal| 1 | 0
2 | Some | 2 | 1
This is an example, the tables I am working on have more than 30 columns each one. I want to select all the user that are active.
Usually I would do a query like:
SELECT *
FROM users
LEFT JOIN persons ON users.id = persons.user_id
LEFT join companies ON users.id = companies.user_id
WHERE persons.active = 1
OR companies.active = 1
That can be translated to Laravel Query Builder like:
DB::table('users')
->leftJoin('persons', 'users.id', '=', 'persons.user_id')
->leftJoin('companies', 'users.id', '=', 'companies.user_id')
->where('persons.active', 1)
->orWhere('companies.active', 1)
->get();
But what I want to use is a Laravel Eloquent ORM Collection, until now I am doing the following:
$users= User::orderBy('id',' desc')->get();
foreach($users as $k => $user) {
if($user->company && !$user->company->active || $user->person && !$user->person->active) {
unset($users[$k]);
}
... and here a lot of validations and unsets ...
}
But I know that at this point, I already grabbed all the users instead those who are active.
How would I achieve what I did with query builder within a collection? Thanks in advance.
This should do it:
$users = User::whereHas('companies', function($q) {
$q->where('active', true);
})->orWhereHas('persons', function($q) {
$q->where('active', true);
})->with(['companies', 'persons'])->orderBy('id', 'desc')->get();

Laravel 5: How to do a join query on a pivot table using Eloquent?

I have 2 tables in my Laravel application namely customers and stores. Customers can belong to many stores and stores can have many customers. There's a pivot table between them to store that relation.
Question is, how do I extract the list of customers for a given store using Eloquent? Is it possible? I am currently able to extract that using Laravel's Query Builder. Here is my code:
| customers | stores | customer_store |
-------------------------------------------
| id | id | customer_id |
| name | name | store_id |
| created_at| created_at | created_at |
| updated_at| updated_at | updated_at |
Customer Model:
public function stores(){
return $this->belongsToMany(Store::class)
->withPivot('customer_store', 'store_id')
->withTimestamps();
}
Store Model:
public function customers(){
return $this->belongsToMany(Customer::class)
->withPivot('customer_store', 'customer_id')
->withTimestamps();
}
DB Query (using Query Builder):
$customer = DB::select(SELECT customers.id, customers.name, customers.phone, customers.email, customers.location FROM customers LEFT JOIN customer_store on customers.id = customer_store.customer_id WHERE customer_store.store_id = $storeID);
Try this one:
public function result(Request $request) {
$storeId = $request->get('storeId');
$customers = Customer::whereHas('stores', function($query) use($storeId) {
$query->where('stores.id', $storeId);
})->get();
}
Try executing this...
$result = Customer::with('stores')->get();
Hope this helps.
To know more about Eloquent Relationship refer: https://laravel.com/docs/5.1/eloquent-relationships
Try below:
Here Customers is your model and $storeID is your store id. $storeID is outside of the scope of your callback. So you must use the use statement to pass them.
Customers::leftJoin('customer_store', function($join) use($storeID){
$join->on('customers.id', '=', 'customer_store.customer_id')
->where('customer_store.store_id','=', $storeID);
})
->whereNotNull('customer_store.store_id')//Not Null Filter
->get();
Hope this help you!

Laravel 4 Eloquent table join and where clause on multiple tables

Hi I'm using Laravel and Eloquent in order to store users, there profile and there assigned roles. My table structure is as follows;
users
id | username | email | password | created_at | updated_at
profiles
id | user_id | firstname | created_at | updated_at
roles
id | name
assigned_roles
id | user_id | role_id
I'm trying to select all users where there role name is equal to admin. But when I do the following I get an empty array:
return \User::with('profile')->join('assigned_roles', function ($join) {
$join->where('assigned_roles.user_id', '=', 'users.id');
})->get();
Any ideas what I'm doing wrong?
Also I am using Zizaco Entrust and Confide https://github.com/Zizaco/entrust/tree/1.0
In order to fetch users that have admin role you need to use Eloquent's whereHas() method:
$admins = \User::with('profile')
->whereHas('assigned_roles', function($query) {
$query->whereName('admin');
})
->get();
I assume you have assigned_roles relation defined. If not, add many-to-many relation between your users and roles:
public function assigned_roles() {
return $this->belongsToMany('\Your\Model\Namespace\Role', 'assigned_roles', 'user_id', 'role_id');
}

Categories