Display relationship of relationship in response - laravel

My stack is - Laravel, React, Vite. I have a relationship:
$messages = $user->profile->messages
and it works correctly, but messages have relationship with user. Propably it sound difficult but it's simple.
Profile contains more details about user and profile has relationsin hasMany for Messages. It's simple. But I need to display messages with username (this is in Username model). How I said Messages have an relationship with User model but it's not in my response.
public function user() {
return $this->belongsTo(User::class);
}
If I want to display only data from model with relationship I could use with, for example:
Book::with('author')->get()
But in this case it didn't work. For example
$user->profile->messages->with('user')
It display me the error
Method Illuminate\Database\Eloquent\Collection::with does not exist.
My question is - how could I add relationship (to user) to this query so that I can see that relationship in the response?
$user->profile->messages

not sure what query you are using, but you can write something like this if you wish which should work assuming that the messages and user relationships are correctly defined
$user = User::with(['profile',
'profile.messages',
'profile.messages.user:id,username'])
->where(//some condition)->get()

Related

How to search for all associations in a relationship tree in Laravel?

I'm having a problem. I have tables that relate:
internal_clients->subsidiaries->departments->job_titles->users
I also have their respective models.
My doubt is:
How do I get all the data associated with users from the top of the tree (internal_clients)
?
I'm trying to follow the Laravel documentation using hasManyThrough.
However, in the documentation it explains only how to do it in a chain of three tables. They teach how to place an intermediate table (model) as the second parameter of the hasManyThrough method (BaseClasse::class, IntermediaryClass::class).
However, in my case that has several tables between users and internal_clients, how would I do this? What would be the intermediate table?
I would like to make a query that returns the user's internal_client, subsidiary, department and jobTitle (associated with users).
I'm trying to do it this way:
Model InternalClient
public function users()
{
return $this->hasManyThrough(User::class, InternalClient::class);
}
Controller UserController
public function allRelations($internalClientId)
{
$internalClient = InternalClient::find($internalClientId);
$users = $internalClient->users;
return response()->json($users, 201);
}
The InternalClient id arrives at the controller above.
When I access the route, the error below is returned:
In short: I would like to know if there is a way to get all the data (from all tables that are in this hierarchical tree) that are associated with the User.
I couldn't find an answer on the Stackoverflow PT-BR.
Thank you!

Query hasMany relation with slug instead of id?

I'm trying to query a category and all of its channels based on a slug.
Works
\App\Category::find(1)->channels()->get();
Doesn't Work
\App\Category::where('slug','animals')->channels()->get()
BadMethodCallException with message 'Method Illuminate/Database/Query/Builder::channels does not exist.'
Relationship on Category Model
public function channels()
{
return $this->hasMany(Channel::class,'category_id');
}
Assuming that you correctly have your slug field set-up in migration and model attributes (It looks like so from the Exception message).
Doing
\App\Category::find(1)->channels()->get();
is under the hood equivalent to
\App\Category::where('category_id', 1)->first()->channels()->get();
So what you are requiring, is to get the categories to actually execute the query and then be able to retrieve the channels from the hydrated model.
\App\Category::where('slug', 'animals')->first()->channels()->get();
should work as well as
\App\Category::where('slug', 'animals')->first()->channels; // calling as attribute will perform the get() on the relationship
Also take note that you may take advantage of other methods like with() for eager loading the relationship, first() to perform a get and ensure you take only one instance, and calling the relationship as attribute as shown above. Refer to the docs
there are so many possible answer in your question .. be more specific .. but here's the list of sample queries that may help you ..
GETTING ALL THE CATEGORY WITH ITS CHANNELS WHERE CATEGORY SLUG = ANIMAL
Category::with(['channels'])->where('slug', 'animal')->get();
GETTING ALL THE CATEGORY WITH ITS CHANNELS WHERE HAS A CHANNEL SLUG = ANIMAL
Category::with(['channels'])->whereHas('channels'=>function($q){
$q->where('slug','animal');
})->get();
GETTING ALL THE CATEGORY WITH ONLY CHANNELS THAT HAS A SLUG = ANIMAL
Category::with(['channels'=>function($q){
$q->where('slug','animal');
}])->get();

Laravel get related data from 3 tables

I have three tables: users, emails,attachments. User table is connected with emails by user_id. Emails table is connected with attachments by email_id.
My question is: How should I make it look eloquent in laravel to get all users their emails and their attachments? (I know how get all user and they emails but I don't know how to add attachments.)
Depending on your database relationship,you may declare a relationship method in your Email model, for example:
// One to One (If Email has only one attachment)
public function attachment()
{
return $this->hasOne(Attachment::class);
}
Otherwise:
// One to Many (If Email contains more than one attachment)
public function attachments()
{
return $this->hasMany(Attachment::class);
}
To retrieve the related attachment(s) from Email model when reading a user using id, you may try something like this:
$user = User::with('email.attachment')->find(1); // For One-to-One
$user = User::with('email.attachments')->find(1); // For One-to-Many
Hope you've already declared the relationship method in the User model for Email model using the method name email.
Note: make sure, you have used right namespace for models. It may work if you've done everything right and followed the Laravel convention, otherwise do some research. Also check the documentation.

Laravel Method [hasMany] does not exist

I have 2 controllers and models:
User Controller & Model
Hero Controller & Model
Each user can have unlimited heroes - it means that the relationship between them is one to many.
In my UserController I created the following method:
/**
* Get the heroes of the user.
*/
public function heroes()
{
return $this->hasMany(Hero::Class);
}
while in my HeroController I created this method:
/**
* Get the user that owns the hero.
*/
public function user()
{
return $this->belongsTo(User::class)
}
Added this to my routes file:
Route::get('userHeroes', 'UserController#heroes');
and it returns this error:
{"error":{"message":"Method [hasMany] does not exist.","status_code":500}}
What could have gone wrong.. ?
The controller is just a delegate between the request and the return data - you tell it that you want something, it figures out what you want, and then it calls the appropriate places to get something to return.
The hasMany() and belongsTo() methods, on the other hand, are logic specifically related to the Hero and User models, on the other hand.
What you need is to move the heroes() method to your User model, because a user can have many heroes. Also need the user() method to your Hero model, because a hero belongs to a user.
Then you put an action call in a controller. Let's say, for instance, that you have a UserController which has an getHeroes() method. That might look like this:
public function getHeroes() {
$user = auth()->user();
$heroes = $user->heroes;
return $heroes;
}
And that will format it to JSON. Just an example.
But you might want to read a tutorial or two about this, since it's fairly basic stuff and it's good to get a good handle on early on. Please don't take that the wrong way - we're happy to help if you run into problems, I just think you might need a stronger foundation. The screencasts at Laracasts are highly recommended for this purpose.
it must be declared in models, not in controllers, hasMany() is a method in eloquent models.
hasMany and belongsTo methods are eloquent class methods.
And we inherit eloquent in our model so that we can use the eloquent methods functionality.
In order to use the relation, you have to define the relation method in respective model class and then you can call from controller.
Please refer the documentation Eloquent relationship documentation
Hope i have cleared your doubt.
Thanks

Create multiple objects from api post in laravel

Im at a bit of a loss. I have an api that will create a user upon a request. This is done no problem.
I also want to create another controller action or add to my current action the ability to create an address for the same user.
Is there an easy way to do this? Or should I stick to the
$user = new User(Input::all());
$user->save();
$address = new Address(Input::all());
$address->save();
You should set up relationships between your User and Address model - http://laravel.com/docs/eloquent#relationships and use associate/sync() to connect the dots.
This is a relationship problem. An address to a user will most likely be One-to-One (i.e., each Userhas a unique Address). A User might have an Address, but an Address must have a User. So in essence, the Address belongs to User.
Create two tables users and addresss, and add user_id to the address table as a column.
Then you define your relationships:
// In your User.php model
public function address()
{
return $this->hasOne('Address');
}
// In your Address.php model
public function user()
{
return $this->belongsTo('User');
}
Note when you use the correct notation, you can just define the model name, and not specify the pivot column. That is why I have defined the class addresss with an extra 's' to make it plural. I personally don't care about the spelling and rather Laravel take care of everything. Otherwise read the documentation on how to define the pivot column
Then you can use associate easily:
$user = new User();
// Fill $user however you want
$address = new Address();
// Fill $address however you want
$user->associate($address);
$user->save();
I was able to figure it out!
I wound up utilizing the Ardent package to help me validate my models before they hit the save method.
if my models didnt validate i will return all the errors to the user.
If they did validate my models would be created.
As for the association I am using the has many relation ship on the User and belongs to on the Address.
I used the following to save the address to the user
$address = $user->address()->save($address);
however I could only preform this after the initial user object was saved.
Thanks for all the responses guys they lead me in the right direction!

Resources