I am trying to map a relationship between the User and Order Model within Order Model.
An order has one project. The project has one team and the team has one owner/user
The relationship is four levels deep like following:
order > project > team > user
My database tables are as follows:
App\Order
id,
project_id
App\Project
id,
name,
team_id
App\Team
id
name
user_id
App\User
id
name
My Order Model:
class Order extends Model{
function customer(){
// trying to map the relationship here
}
}
I would like to access the customer like following:
$order = Order::find(1);
echo $order->customer->name;
Could you please tell me how to map the above-mentioned relationship?
You can get it by including joins in your query like:
$data = Order::select('orders.*')
->join('projects', 'orders.project_id', '=', 'products.id')
->join('teams', 'projects.projects_id', '=', 'teams.id')
->join('users', 'teams.teams_id', '=', 'users.id')
->get();
For Eloquent you can use this package.
You can define deeper relationships :
Order → belongsTo → Project → belongsTo → Team → belongsTo → User :
class Order extends Model
{
use \Znck\Eloquent\Traits\BelongsToThrough;
public function customer()
{
return $this->belongsToThrough('App\User', ['App\Team', 'App\Project']);
}
}
Another way would be to define a belongsTo in your model by adding joins to directly reach users table
class Order extends Model
{
public function customer()
{
return $this->belongsTo(Project::class, 'project_id')
->join('team as t', 't.id', '=', 'projects.team_id')
->join('users as u', 'u.id', '=', 't.user_id')
->select(['u.id as uid','u.name','projects.id']);
}
}
And then you can directly get the customer information from order object
$order = Order::find(1);
$order->customer->name;
OR
Via eager loding
$orders = Order::with('customer')->get();
Related
What I need is to count the number of vehicles created by each user, but the problem is that when I make the query for the relationship, it only brings up the users who have vehicles created, but I also need to show the users who do not have vehicles created.
public function clients()
{
$user_id = \Auth::user()->id;
$users = DB::table('users')
->join('mechanic_client', 'users.id', '=', 'mechanic_client.user_id')
->where('mechanic_client.mechanic_id', '=', $user_id)
->select('users.id', 'users.name', 'users.email', 'users.password', 'users.url', 'users.cant_vehicle');
$vehicles = DB::table('vehicles')
->joinSub($users, 'users', function ($join) {
$join->on('vehicles.user_id', '=', 'users.id');
})->select('users.id',
'users.name',
'users.email',
'users.password',
'users.url',
DB::raw('count(*) as total'))
->groupBy('user_id')->get();
return $vehicles
}
what i get
id
name
email
vehicles
65
name1
name1#name1
5
66
name2
name2#name2
1
67
name3
name3#name3
6
These are the users who have vehicles created, but what I need is to show all the independent users who have or do not have vehicles and also count the vehicles of each user.
It's never the best option to use the raw DB:: query builder in Laravel. This could be very easily achieved with Eloquent approaches. Laravel has withCount() for counting relationships, described here. For check if mechanicClint exists, you can use has() method, that check if the relationship exists.
User::has('mechanicClients')
->withCount('vehicles');
This requires you to define the class and relationship. In Users.php.
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Models\Vehicle;
class User extends Authenticatable
{
public function vehicles()
{
return $this->hasMany(Vehicle::class);
}
public function mechanicClients()
{
return $this->hasMany(MechanicClient::class);
}
}
And define the Vehicle.php and MechanicClient.php models.
use Illuminate\Database\Eloquent\Model;
class Vehicle extends Model
{
}
class MechanicClient extends Model
{
}
I have a two models that have a many-to-many relationship, with some addtional fields on the pivot table:
Shift table:
------------
id - uuid
date - date
address - string
...
Employee table:
---------------
id - uuid
first_name - string
...
shift_employee table:
---------------------
id - integer
shift_id - uuid
employee_id - uuid
hours_worked - integer
...
Now, I'm making a Lens in Laravel Nova, and I want to use the query object to check if any of the instances on shift_employee related to a specific shift has a value bigger than 0 for hours_worked on the shift_employee table.
My first idea is to somehow use whereHas assuming that the Shift model has a relationship employees, like this:
$query->whereHas('employees' function ($q) {
$q->where('hours_worked', '>', 0);
});
But... this is not working... There are shifts with more than 0 hours_worked for certain employees and this query string is not working for me. How would I do this?
First make sure your models are modeled correctly. If they are, you can access any attribute of an intermediate table with the pivot attribute as below:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
/**
* The users that belong to the role.
*/
public function users()
{
return $this->belongsToMany('App\User');
}
}
exemple :
$user = App\User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
In your case, try :
$employee = Employee::with('Shift');
foreach($employee as $e){
$employeeHw[] = $e->shift_employee->where('hours_worked', '>', 0)->get();
}
I'm also new to laverel, so I'm not absolutely sure it works, but in theory: P
Usually in these cases I use the query bilder with join which I find easier
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.*', 'contacts.phone', 'orders.price')
->get();
I'm stuck with a problem where I have to sort / order a collection of models by their relationship's data.
I've got it setup like this:
Models:
User, Team, TeamUser, Role
The TeamUser model is a pivot model / table (containing user_id and team_id.
If it's worth mentioning I am also using spatie/laravel-permissions for the roles.
How would I go forth when I want to sort the users in a team by their role.name?
I'm talking about the users() relation in the Team model (see further down for code sample).
Some users have the role team-leader and most have the role team-seller. I've tried doing a ordinary ..->sortBy('role.name') but that doesn't seem to work. Thanks in advance if anyone could help me out.
User.php
/**
* Team relation
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function team()
{
return $this->belongsToMany('App\Team', 'team_users', 'user_id', 'team_id');
}
Team.php
/**
* User relation
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users()
{
return $this->belongsToMany('App\User', 'team_users', 'team_id', 'user_id')->withTimestamps();
}
if you want to order the result based on nested relation column, you must use a chain of joins:
$values = Team::query()
->leftJoin('users', 'users.team_id', '=', 'teams.id')
->leftJoin('model_has_roles', function ($join) {
$join->on('model_has_roles.model_id', '=', 'users.id')
->where('model_has_roles.model_type', '=', 'app\Models\User');
})
->leftJoin('roles', 'roles.id', '=', 'model_has_roles.role_id')
->orderBy('roles.name')
->get();
i have tried it, it work just fine.
please note that if you want to order by multiple columns you could add 'orderBy' clause as much as you want:
->orderBy('roles.name', 'DESC')->orderby('teams.name', 'ASC') //... ext
I have the usual users, groups and group_user tables. I know the raw SQL that I want:
SELECT group_user.group_id, users.* FROM users
INNER JOIN group_user ON users.id = group_user.user_id
WHERE group_user.group_id IN
(SELECT group_id FROM group_user WHERE user_id=?)
ORDER BY group_user.group_id;
where ? is replaced current user's id.
but, I want to use Eloquent (outside of laravel) for this. I have tried using a User model with a groups method
public function groups() {
return $this->belongsToMany('\Smawt\User\Group');
}
and a Membership model with a users method
public function users($group_id) {
return $this->where('group_id', '=', $group_id)->get();
}
and then I loop through the groups and then loop through all its members. Finally, I append all the data to get one $users object at the end, to pass through to my view.
$thisMembership = new Membership;
$myGroups = $app->auth->groups;
$users = [];
foreach ($myGroups as $myGroup) {
foreach ($thisMembership->users($myGroup->id) as $myUser) {
$thisUser = $app->user->where('id', '=', $myUser->user_id)->first();
$thisUser->group_id = $myGroup->id;
array_push($users, $thisUser);
}
}
Then in my view I loop through my $users as normal. Although this method works, it will not be very efficient as I am unable to work out how to use Eager Loading with it.
Is there a simpler more 'Eloquent' way of getting an object of users who are in the same group as the current user? I don't want just want a list, or an array, as I want to use the other methods defined in my user model.
I have been able to construct the following Eloquent query, although I am not sure this is the 'best' way:
$users = User::join('group_user', 'users.id', '=', 'group_user.user_id')
->whereIn('group_user.group_id', function($query) {
$query->select('group_id')
->from('group_user')
->where('group_user.user_id', '=', $_SESSION['user_id']);
})->orderBy('group_id', 'asc')
->get();
The Eloquent way for the relationship and use of it:
Tables: users, groups
Models: User Group
Pivot Table: group_user (id, user_id, group_id)
In User Model:
public function groups()
{
// pivot table name and related field
// names are optional here in this case
return $this->belongsToMany('Group');
}
In Group Model:
public function users()
{
// pivot table name and related field
// names are optional here in this case
return $this->belongsToMany('User');
}
Use Case (Example):
$usersWithGroup = User::with('groups')->find(1); // or get()
$groupWithUsers = Group::with('users')->find(1); // or get()
For more information check Eloquent section on documentation.
Update:
If user belongsto any group
$usersWithGroup = User::has('groups')->with('groups')->find(1);
Also using if a user belongs to specific group:
$someGroup = 'general';
$usersWithGroup = User::whereHas('groups', function($q) use($someGroup) {
$q->where('group_name', $someGroup);
})
->with('groups')->find(1);
I have four tables
**Articles table**
id
title
body
owner_id
category_id
**Favorite articles table**
id
user_id
article_id
**User table**
id
user_name
user_type
**Category table**
id
category_name
How to get list of favorite articles (article_name,owner_name,category_name) which related to currently logged user from db using laravel eloquent?
Is it possible to do it in single line request? e.g.:
$articles_data=Auth::user()->favorite_articles->article...
EDIT
For the moment i have to use statement below:
$articles_data = FavoriteArticle::where('user_id', Auth::id())->join('articles', 'articles.id', '=', 'favorite_articles.article.id')
->join('users', 'users.id', '=', 'favorite_articles.user_id')
->join('categories', 'categories.id', '=', 'articles.id')
->get()
Which looks a bit complicated and doesn't use eloquent relations.
Completing #zippo_ answer, in the Controller you must reference what tables you want, e.g.
User.php
use Article;
public function article()
{
return $this->hasOne('App\Article');
}
and in the e.g. UserController.php
$user = User::with('article')->get();
EDIT:
if you want to relate User to Article.Category, after create a relation with user and article
Article.php
use Category;
public function category()
{
return $this->hasOne('App\Category');
}
e.g. UserController.php
$user_articles_categories = User::with('article.category')->get();
You can take advantage of laravel eager loading, which are also called as Eloquent relationships.
Eloquent relationships are defined as functions on your Eloquent model classes.
Eg. In Article Model
public function article()
{
return $this->hasOne('App\Model\Category');
}
In this way, you need to define all the relationships in the respective Model classes.
for more info: http://laravel.com/docs/5.1/eloquent-relationships