Getting eloquent chaining to replicate join from mysql in Laravel - laravel

I am using a database mysql with a project table, an activity table and a user table.
A project has many activities and an activity is assigned to one person so I have the following links in my models:
Project model:
public function activities()
{
return $this->hasMany(\App\Activity::class, 'project_id');
}
Then I have
Activity model:
public function user()
{
return $this->belongsTo(\App\User::class, 'user_id');
}
I would like to get for a project, the list of users on it.
I can do
$project = App\Project::find(1);
$activities = $project->activities;
And this works, I get all the activities on this project.
I can do
$activity = App\Activity::find(43113);
$name = $activity->user->name;
But how can I get all the users name on a project?
I tried linking this but it is not working, it tells me I have a bad exception.
For example, this below doesn't work and generates an error:
$names = $project->activities->user;
or
$names = $project->activities->with('users');
I am on Laravel 7.10.

You can use with as below.
$project = App\Project::with('activities.user')->where('id',1)->first();
echo '<pre>';
print_r($project);
exit;
By using project you can get activities and per activities you've user.

Related

Laravel eloquent for four tables

I'm new to Laravel. I am developing a project. and in this project I have 4 tables related to each other
-Users
-Orders
-OrderParcels
-Situations
When listing the parcels of an order, I want to get the information of that order only once, the user information of that order once again, and list the parcels as a table under it. so far everything ok. but I also want to display the status of the parcels listed in the table as names. I couldn't add the 4th table to the query. do you have a suggestion? I'm putting pictures that explain the structure below.
My current working code is
$orderParcels = Orders::whereId($id)
->with('parcels')
->with('users:id,name')
->first();
and my 'orders' model has method
public function parcels(){
return $this->hasMany(OrderParcels::class);
}
public function users(){
return $this->hasOne(User::class,'id','affixer_id');
}
Note[edit]: I already know how to connect like this
$orderParcels = DB::table('order_parcels as op')
->leftjoin('orders as o','op.orders_id','o.id')
->leftjoin('users as u','o.affixer_id','u.id')
->leftjoin('situations as s','op.status','s.id')
->select('op.*','o.*','u.name','s.situations_name')
->where('op.orders_id',$id)->get();
but this is not working for me, for each parcels record it returns me orders and user info. I want once orders info and once user info.
Laravel provides an elegant way to manage relations between models. In your situation, the first step is to create all relations described in your schema :
1. Model Order
class User extends Model {
public function parcels()
{
return $this->hasMany(OrderParcels::class);
}
public function users()
{
return $this->hasOne(User::class,'id','affixer_id');
}
}
2. Model Parcel
class Parcel extends Model {
public function situations()
{
return $this->hasOne(Situation::class, ...);
}
}
Then, you can retrieve all desired informations simply like this :
// Retrieve all users of an order
$users = $order->users; // You get a Collection of User instances
// Retrieve all parcels of an order
$parcels = $order->parcels; // You get a Collection of User instances
// Retrieve the situation for a parcel
$situations = $parcel->situations // You get Situation instance
How it works ?
When you add a relation on your model, you can retrieve the result of this relation by using the property with the same name of the method. Laravel will automatically provide you those properties ! (e.g: parcels() method in your Order Model will generate $order->parcels property.
To finish, in this situation where you have nested relations (as describe in your schema), you should use with() method of your model to eager load all the nested relation of order model like this :
$orders = Orders::with(['users', 'parcels', 'parcels.situations'])->find($id)
I encourage you to read those stubs of Laravel documentation :
Define model relations
Eager loading
Laravel Collection
Good luck !
Use join to make a perfect relations between tables.
$output = Orders::join('users', 'users.id', '=', 'orders.user_id')
->join('order_parcels', 'order_parcels.id', '=', 'orders.parcel_id')
->join('situations', 'situation.id', '=', 'order_parcels.situation_id')
->select([
'orders.id AS order_id',
'users.id AS user_id',
'order.parcels.id AS parcel_id',
'and so on'
])
->where('some row', '=', 'some row or variable')->get();

Laravel Intermediate relations data error

Here is my RecentViewController file code:
$contents = RecentView::where('user_id', $loggedUser)
->with('posts')
->with('profile')
->paginate(12)->toArray();
and my RecentView model code is as follows:
public function posts()
{
return $this->hasOne('App\FeedPost', 'id', 'post_id');
}
public function profile()
{
return $this->belongsTo('App\Profile', 'user_id', 'id');
}
the data i receive after running this code shows logged in users details instead of posts users detaisl. how can i change retreiving posts users data instead of logged users data?
I guess you are trying to get the user of the post
In order to get posts users detail you need to move profile relation into Post model. I hope there's a user_id in posts table. then get profile relationship of post model with dot notation as follows
$contents = RecentView::where('user_id', $loggedUser)
->with('posts.profile')
->paginate(12)->toArray();

get user from belongsToMany relationships

I have a service model in October CMS.
In this model, I need to get postman's users (postman is user group) but I am receiving this error:
Trying to get property of non-object
This is my code
public function getPostmanIdOptions()
{
$groups = UserGroup::where('id','4')->lists('name', 'id');
$groups->users;
$list = [' ' => 'choose'] + $groups;
return $list;
}
At the moment, your lists() function will only return the name and the id of each user group. This is used to return thelselect options for the backend select (I am assuming).
What you need to do in this case is return the record based on its id which can be done using the find() eloquent method.
By doing this, the full UserGroup model will be returned, with it's relationships etc.
You're new code should look something like this:
...
$group = UserGroup::find(4);
$users = $group->users;
...
After retrieving the users, you can then using the lists() method if required to:
$list = $group->users->lists('name', 'id');

How to add data to additional column in pivot table in laravel

I'm trying to build an app in Laravel 5.3, I want to add additional column data in the pivot table. Following is my code:
My Users model:
public function relations()
{
return $this->belongsToMany('App\Plan')->withPivot('child');
}
My Plan model:
public function relations()
{
return $this->belongsToMany('App\User')->withPivot('child');
}
In my controller I'm fetching the user data from Auth::user(); and for plans and child element I'm getting through request. I want to store this to my pivot table. Following is the code which I tried in my controller:
$user = \Auth::user();
$plan_id = $request->plan_id;
$childid = $request->child_id;
$plan = App\Plan::find($plan_id);
$user->relations()->attach($plan, ['child' => $childid]);
Help me out in this.
You should use attach() like this:
$user->relations()->attach($plan_id, ['child' => $childid]);
Try the save method as:
$user->relations()->save($plan, ['child' => $childid]);
Docs
Both save and attach work. Just that attach will return null while save will return $user object when I try with tinker

How to query relationships in Laravel 4 with Eloquent?

Coming from CodeIgniter's Datamapper ORM I am still trying to get my head around Laravel's Eloquent ORM.
Given the fact that I have an ACCOUNT and a USER table (simplified):
ACCOUNT
- id
- name
USER
- id
- account_id
- username
One account has many users. One user belongs to one account. So we're dealing with a one-to-many relationship. Everything is already set-up in the models.
In CodeIgniter's Datamapper I would have done the following to get the user from any given ID and at the same time check if that user is related to the current account:
$u = new User();
$u->where('username', $username);
$u->where_related_account('id', $account_id);
$u->get();
if ( ! $u->exists()) exit; // or do something...
// otherwise continue to use the "$u" user object
This syntax is very logical and easy to understand. In Eloquent I have a hard time to achieve the same with a similar easy syntax. Does anyone have any suggestions?
Very simply (ignoring the relationship between the user and the account), it could just be:
$u = User::where('username', $username)
->where('account_id', $id)
->get();
That will return you your user's details.
Otherwise, assuming that you have your User and Account classes and DB tables are set up correctly (as per the Laravel docs), you should be able to just do:
$user_exists = Account::find($account_id)
->users()
->where("username", "=", $username)
->first()
->exists;
if ($user_exists)
{
doThings();
}
If you've correctly set up your models and database tables (as #msturdy said) you should actually be able to return your user account by simply going:
$user = User::whereUsername($username)
->first(); // or User::where('username', $username)->first();
if ($user) {
$account = $user->accounts()
->whereId($account_id)
->first(); // or $user->accounts()->where('id', $account_id)->first();
}
This gives you the ability to access the user and account models
you could even extend your User model to include the following methods:
class User extends Eloquent {
...
public static function byUsername($username) {
return static::whereUsername($username)->first();
}
public function getAccount($id) {
return $this->accounts()->whereId($id)->first();
}
...
}
and then simply go
$user = User::byUsername($username);
if ($user) {
$account = $user->getAccount($account_id);
}
which might be better for you if you are using the code in multiple controllers.

Resources