how to connect multiple tables with Laravel models - laravel

I am using Laravel 7.
I want to retrieve all the users that are active and belong to Austria.
I would like to do that using laravel relationships.
There are three tables that should be connected through the models: countries, users and user_details.
Country.php:
public function user_details()
{
return $this->hasMany('App\UserDetail', 'citizenship_country_id', 'id');
}
User_detail.php:
public function country()
{
return $this->belongsTo('App\Country', 'citizenship_country_id', 'id');
}
public function user()
{
return $this->belongsTo('App\User', 'user_id', 'id');
}
User.php:
public function user_detail()
{
return $this->hasOne('App\UserDetail', 'user_id', 'id');
}
In the controller I used the following code to retrieve all austrian users that are active:
return Country::where('name', 'Austria')->first()->user_details()->first()->user()->where('active', '1')->get();
I should visualize two users but I get only one user. I suppose the error is the second first.
Can help?

Try This.
$users = User::whereHas('user_details.country', function ($query) {
$query->where('countries.name', "Austria");
})
->where("active",1)
->get();

Related

How would I edit the Laravel Nova indexQuery for a Resource to only show records through multiple relationships?

firstly thank you in advance.
I have the following Models , User , Location, Listing, Offer.
The relationships are:
User Model:
public function location()
{
return $this->hasOne(Location::class);
}
Location Model:
public function listings()
{
return $this->hasMany(Listing::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
Listing Model:
public function offers()
{
return $this->hasMany(Offer::class);
}
public function location()
{
return $this->belongsTo(Location::class);
}
Offer Model:
public function listing()
{
return $this->belongsTo(Listing::class);
}
In my Offer Resourse I would like to show only the offers that belongTo the listings that in turn belongsTo the location that in turn belongTo the authenticated user. I have tried the following.
public static function indexQuery(NovaRequest $request, $query)
{
$user = Auth::user();
if ($user->is_admin === 1){
return $query;
}elseif($user->is_admin === 0) {
return $user->location->listings->offers;
}
}
But get an error Property [offers] does not exist on this collection instance. Any assistance will be greatly appreciated.
I would try something like this.
More information here on querying relationship existence:
https://laravel.com/docs/9.x/eloquent-relationships#querying-relationship-existence
public static function indexQuery(NovaRequest $request, $query) {
$user = Auth::user();
if (!$user->is_admin) {
$query = $query->whereHas('listings.location.user', function ($builder) use ($user) {
return $builder->where('id', $user->id);
});
}
return $query;
}
The reason you are getting the "Property does not exist" error is due to you not pulling it from database.
Two alternative solutions include
Querying them separately: ...->listings()->offers()
Eager loading: ->with(['location.listings.offers']);

How to get users from a group, with a union between two relationships in laravel?

I want to recieve all users from a group.
The problem is in this group their are student users (with a pivot table) and normal users.
So i have to merge them together, but i still want to maintain all possibilities from eloquent.
I came to this:
dd($this->belongsToMany(User::class)->union($this->hasManyThrough(User::class,Student::class,'class_id','id','id','user_id'))->get());
But as result i get:
My database relationships
Users
- id
Group
- id
Students
- id
- user_id (fk to users)
- class_id (fk to groups)
User_Group
- user_id (fk to users)
- group_id (fk to groups)
User-model:
public function students()
{
return $this->hasMany(Student::class);
}
public function groups()
{
return $this->belongsToMany(Group::class);
}
Student-model
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function class()
{
return $this->belongsTo(Group::class, 'class_id');
}
Group-model
public function students()
{
return $this->hasMany(Student::class, 'class_id');
}
public function users()
{
return $this->belongsToMany(User::class);
}
public function members()
{
//this causes the problem!!
return $this->belongsToMany(User::class)->union($this->hasManyThrough(User::class,Student::class,'class_id','id','id','user_id'));
}
in User model relationship
public function group(){
return $this->belongsToMany(Group::class);
}
in Group model relationship
public function user(){
return $this->belongsToMany(User::class, 'user_group');
}
in Students model relationship
public function user(){
return $this->belongsToMany(User::class, 'user_id', 'id');
}
public function group(){
return $this->belongsToMany(Group::class, 'class_id', 'id');
}
you can call now
$users = User::whereHas('groups',function ($query){
$query->where('group_id',1);
})->get();
Sometimes you have two relations from one model to another, due pivot tables. In my example you could go from users to groups with the relation user_groups and the relation students. To get all users that belong to a certain group i need to call both relations. To solve this issue, i made use of Abdulmajeed's example to solve it. You can see the code below. Thanks for helping me out.
public function members()
{
return User::whereHas('groups', function($q)
{
$q->where('id',$this->id);
})->orWhereHas('students', function($q)
{
$q->where('class_id',$this->id);
});
}

Laravel One to Many relation with 2 primary keys

I've 2 tables
Users table
id
name
...
Chats table
id
from_id // fk - id on users, the user sent the message
to_id // fk - id on users, intended user
message_body
Now, I'm trying to set up One to Many relation where user has many chat messages but a chat message has two user. from and to user
How can I define this relationship?. I have to user eager loading.
I tried to use Compoships but it didn't work.
My code
User Model
public function chats() {
return $this->hasMany(Chat::class, ['from_id', 'to_id'], 'id');
}
Chat Model
public function user() {
return $this->belongsTo(User::class, ['from_id', 'to_id'], 'id');
}
public function chats() {
return $this->hasMany(Chat::class, 'from_id', 'id') + $this->hasMany(Chat::class,'to_id','id');
}
public function userFrom() {
return $this->belongsTo(User::class, 'from_id', 'id');
}
public function userTo() {
return $this->belongsTo(User::class, 'to_id', 'id');
}
Why don't you do something like that?
On your User model, set up two relationships like this:
public function chatsFrom() {
return $this->hasMany('App\Chat', 'from_id');
}
public function chatsTo() {
return $this->hasMany('App\Chat', 'to_id');
}
Then, on your Chat model, also set up two relationships, one to from and another to to, both referencing a User model. Like this:
public function fromUser() {
return $this->belongsTo('App\User', 'from_id');
}
public function toUser() {
return $this->belongsTo('App\User', 'to_id');
}
This way, you can access the relationships using something like this:
$user->chatsFrom();
$user->chatsTo();
$chat->fromUser();
$chat->toUser();

Eloquent Relationship. Has Many relation with different keys

Background
I have a model, Contract that belongs to the User model through two keys, user_id and recipient_id. How would I be able to query all the contracts for a user using $user->contracts keeping the two key into consideration.
\App\Contract model has this
$protected $fillable = [
...
'user_id',
'recipient_id',
...
];
public function user ()
{
return $this->belongsTo(User::class);
}
public function recipient()
{
return $this->belongsTo(User::class, 'recipient_id', 'id');
}
\App\User model has this
public function contracts ()
{
return $this->hasMany(Contract::class);
}
To get the user contracts, I have to do this
$contracts = Contract::where('user_id', $user->id)
->orWhere('recipient_id', $user->id)
->get();
What I would like is something like this. \App\Contract
public function user () {
return $this->belongsTo([User::class, User::class], ['user_id', 'recipient_id']);
}
I am aware of https://github.com/staudenmeir/eloquent-has-many-deep and it doesn't solve my problems.
How do I go about it?
I couldn't find a way, so, I ended doing this in ContractController.php
public function index()
{
$user = Auth::user();
if ($user->isAdmin()) {
return Contract::latest()->get();
}
$contracts = Contract::where('user_id', $user->id)
->orWhere('recipient_id', $user->id)
->get();
return $contracts;
}

Laravel 5 - Defining Two Relationships Between Models

I'm learning Laravel, and really OOP in general. I've followed several YouTube tutorial series, that teach you to create a blog in Laravel.
I'm building a task app for a brewery, and I'm trying to define the relationships between the users and the tasks. So I have two models: User.php and Task.php. I had no problem defining the user in a hasMany tasks relationship, and reciprocally, a task belongsTo a user. Where I'm confused is that I'd like to also have a user belong to the task as well. I have two MySQL columns, one with the heading of "user_id" and the other with "user_assigned_id". What I want is that a user has many tasks, but a task also has one assigned user, the idea being that the user that created the task might assign the task to another user. I've found several tutorials on creating relationships between three models, such as a user owning several messages, but only having one address, so I figured that I could just treat two models as if they were three models and connected the User model back to the Task model in a hasOne relationship, but I'm having a really hard time passing that through to the Controller and View.
Here is the relevant code in each file:
User.php
public function tasks()
{
return $this->hasMany('App\Task');
}
Task.php
public function user()
{
return $this->belongsTo('App\User');
}
// Added an user_assigned_id relationship
public function user_assigned()
{
return $this->hasOne('App\User', 'name', 'user_assigned_id');
}
DashboardController.php
public function index()
{
$user_id = auth()->user()->id;
$now = Carbon::now();
$tasks_assigned = Task::orderBy('date', 'asc')->whereDate('date', '>=', $now)->where('user_assigned_id', '=', $user_id)->user_assigned()->where('name', '=', 1)->get();
$tasks_created = Task::orderBy('date', 'asc')->whereDate('date', '>=', $now)->where('user_id', '=', $user_id)->get();
return view('dashboard')->with('tasks_assigned', $tasks_assigned)->with('tasks_created', $tasks_created);
}
I've gotten a bit turned around in the Controller, so I'm not sure if I messed something up there. Basically, I'm getting results from tasks owned by the logged in user, but not assigned to the logged in user.
You can just add a second relationship defined on your Task.php Model and assign a different agent based on user_assigned_id. You can manipulate it as expected via Eloquent.
Task.php
public function user() {
return $this->belongsTo('App\User');
}
public function assignedUser() {
return $this->belongsTo('App\User', 'user_assigned_id');
}
Then on DashboardController.php
$tasks_assigned = Task::orderBy('date', 'asc')->whereDate('date', '>=', $now)->where('user_assigned_id', '=', $user_id)->get();
should work
public function user()
{
return $this->belongsTo('App\User');
}
// Added an user_assigned_id relationship
public function assignee()
{
return $this->belongsTo('App\User', 'user_assigned_id');
}
The relationship is still a belongsTo, you just need to provide the column where the foreign key is held.
Other files:
User.php
public function ownedTasks()
{
return $this->hasMany('App\Task');
}
public function assignedTasks()
{
return $this->hasMany('App\Task', 'user_assigned_id');
}
Dashboard Controller
public function index()
{
$now = Carbon::now();
$tasks_assigned = Auth::user()->assignedTasks()->where('date', '>=', $now)->get();
$tasks_created = Auth::user()->ownedTasks()->where('date', '>=', $now)->get();
return view('dashboard')->with(compact('tasks_assigned', 'tasks_created'));
}

Resources