Laravel 5 - Defining Two Relationships Between Models - laravel

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'));
}

Related

How can I paginate Laravel's Eloquent's relationships' relationships?

I have two tables, users and profiles. A user has one profile. Also a user has referrals. The referrals are referenced by the column referrer_id in the users' table. So a user has a referrer, and a user can have many referrals.
Define a one-to-one relationship on the User's Model:
public function profile()
{
return $this->hasOne(Profile::class);
}
Define an inverse one-to-one relationship on the User's Model:
public function referrer()
{
return $this->belongsTo(User::class);
}
Define a one-to-many relationship on the User's Model:
public function referrals()
{
return $this->hasMany(User::class, 'referrer_id');
}
Define an inverse one-to-one or many relationship on the Profile's Model:
public function user()
{
return $this->belongsTo(User::class);
}
I wish to retrieve the user's profile, the user's referrals along with their profiles, and the referrals' referrals along with a count of each of the referrals' referrals.
The following Eloquent query works, but doesn't paginate:
namespace App\Http\Controllers;
class ReferralsController extends Controller
{
public function index(Request $request)
{
return $request->user()->loadMissing(['profile', 'referrals' => function ($query) {
$query->with(['profile', 'referrals'])->withCount('referrals');
}]);
}
}
I've tried to add ->paginate() to the query (on both as show below and also one or the other) but it doesn't work:
return $request->user()->loadMissing(['profile', 'referrals' => function ($query) {
$query->with(['profile', 'referrals'])->withCount('referrals')->paginate(2);
}])->paginate(2);
Adding it to the inner function doesn't do anything, and adding it to the main query just retrieves the entire users table.
EDIT
I've realized that adding ->paginate() to the inner function actually does limit the number of rows in the collection, but there is no Paginator instance anywhere, so I don't have access to any of the links to move pages.
Got it to work by doing it separately:
$profile = $request->user()->profile()
->firstOrFail();
$referralsPaginator = $request->user()->referrals()
->with('profile')
->withCount('referrals')
->paginate(2);

how to connect multiple tables with Laravel models

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();

Laravel one to one (polymorphic) not working only on specific model

I am facing a super weird issue.
I have 3 tables and their equivalent model:
App\User
public function company() {
return $this->morphTo();
}
App\Supplier
public function user() {
return $this->morphOne(User::class, 'company');
}
App\Company
public function users() {
return $this->morphMany(User::class, 'company');
}
For some reason the relationship on App\Supplier does not work, but all the other works normal, I can even get the supplier if I have the user:
$supplier = \App\Supplier::find(1);
$company = \App\Company::find(2);
$supplieruser = \App\User::find(1);
$supplier->user //THIS RETURN NULL
$company->users //return collection of users normally
$suppplieruser->company //returns an instance of supplier model
I have tried, changing the name of the relationship and nothing.
Any idea?
In case someone find this in the future... the relationship was not working because I had in my AppServiceProvider the following:
Relation::morphMap([
.....
'supplier_to_supplier' => 'App\Supplier',
.....
]);
It seems that registering it here will affect all the morphs from that model.

Laravel how to get only relation data

this is my User.php relation code
public function activities()
{
return $this->hasMany(Activities::class, 'builder');
}
and this is my query to get only relation data
return User::whereHas('activities', fn($query) => $query->where('user_id', 1))
->paginate();
but it returns only user data without appling any relation, and its pagination not get to use pluck
i have also tried this
User::where('username', request()->username)->has('activities')->paginate();
but i need only get relation data not user with relation, and i prefer do it with whereHas
You need to create reverse relation for Activities model:
class Activities extends Model
{
// ...
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}
And get all the activities using Activities builder:
$paginated = Acitivities::query()
->whereHas('user', static function(Builder $userQuery) {
$userQuery->where('name', request()->username); // Think about security!
})
->paginate();
Note: All the models must be named in singular (e.g. Activity, User, Product and etc.).

Laravel collection returning duplicate

Hi I am trying to return a Users Schedule where greater than or equal to todays date, or if that schedule contains a relation (ScheduledYard) that is not complete:
$schedules = Auth::user()
->schedules()
->where('due_at', '>=' , Carbon::now())
->orWhereHas('scheduledYards', function ($query) {
$query->where('completed', false);
})->get();
$schedules = $schedules->sortBy('due_at');
return ScheduleResource::collection($schedules);
This works perfectly fine, but for some reason it is duplicating this for each user it is attached to. i.e if 3 users have this schedule then it is returned 3 times for the Authenticated user.
User Model:
public function schedules()
{
return $this->belongsToMany('App\Models\Schedule');
}
Schedule Model:
public function users() {
return $this->belongsToMany('App\Models\User');
}
If I remove the orWhereHas() it will return a single object. What am I doing wrong here and how can I return a single object based on the requirements above?
In Schedule Model, you need to change the relationship type. i assuming its one to many relationship between users and schedules. in that case change users() to user() and method body as below.
public function user() {
return $this->belongsTo('App\Models\User');
}
In User model the correct relationship should be defined as:
public function schedules()
{
return $this->belongsTo('App\Models\Schedule');
}
Please try with distinct. For example,
public function schedules()
{
return $this->belongsToMany('App\Models\Schedule')->**distinct**();
}

Resources