I want to get the related client name through a hasManyThrough relationship - php

I need to print on the view the name of the client that refers to the tasks of its projects through the interim relationship called projects.
I used a hasManyThrough relationship because I needed to get more information. Now I need to get the client name as described above.
Relationship defined in the Client model:
public function projects()
{
return $this->hasMany(Project::class);
}
public function tasks()
{
return $this->hasManyThrough(Task::class, Project::class);
}
Relationship defined in the Project model:
public function client()
{
return $this->belongsTo(Client::class);
}
public function tasks()
{
return $this->hasMany(Task::class);
}
Relationship defined in the Task model:
public function project()
{
return $this->belongsTo(Project::class);
}
I've tried this but can't get the client name
TaskController:
public function index($id = NULL)
{
$tasks = Task::all();
$project = Project::find($id)->load(['tasks']);
return view('task.index', compact('tasks','project'));
}
In the task view of that task I want to see the following line:
"List of tasks related projects to (client name)"
Anyone who can kindly help me?
clients
id - integer
name - string
projects
id - integer
client_id - integer
name - string
tasks
id - integer
project_id - integer
title - string

If I understood correctly, you need first to add a relationship on Task model:
public function client()
{
return $this->hasOneThrough(Client::class, Project::class);
}
this relationship will allow you to get the client to whom the project containing this task belongs to.
Then on your TaskController :
public function index($id = NULL)
{
$tasks = Task::with(['project', 'client'])->get();
$project = Project::find($id)->load(['tasks']);
return view('task.index', compact('tasks','project'));
}
Now the $tasks will have within them the project info + client info

Related

Laravel Eloquent: Inverse of Many To Many (Polymorphic)

Example copied from official Laravel Docs:
For example, a Post model and Video model could share a polymorphic relation to a Tag model. Using a many-to-many polymorphic relation in this situation would allow your application to have a single table of unique tags that may be associated with posts or videos. First, let's examine the table structure required to build this relationship:
posts
id - integer
name - string
videos
id - integer
name - string
tags
id - integer
name - string
taggables
tag_id - integer
taggable_id - integer
taggable_type - string
From a tag object I wanted to get all the videos and posts, to which that subjected tag belongs (in case of morphOne an morphMany I can do that by morphTo() method)
Laravel says, I need to define both the videos and posts methods in Tag model in order to define an inverse but I want a relation like taggables which will return the respected parent (whether it's Post or Video)
Reference
I need a similar thing like imageable (but it is polymorphic one to one and I need this kind of thing in many to many)
You can just use MorphOne/MorphMany in your pivot model.
https://laravel.com/docs/8.x/eloquent-relationships#defining-custom-intermediate-table-models
class Video extends Model
{
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable')->using(Taggable::class);
}
public function taggables()
{
return $this->morphMany(Taggable::class, 'taggable');
}
}
class Post extends Model
{
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable')->using(Taggable::class);
}
public function taggables()
{
return $this->morphMany(Taggable::class, 'taggable');
}
}
class Tag extends Model
{
public function posts()
{
return $this->morphedByMany(Post::class, 'taggable')->using(Taggable::class);
}
public function videos()
{
return $this->morphedByMany(Video::class, 'taggable')->using(Taggable::class);
}
public function taggables()
{
return $this->hasMany(Taggable::class/*, 'tag_id'*/)
}
}
use Illuminate\Database\Eloquent\Relations\MorphPivot;
class Taggable extends MorphPivot
{
public $incrementing = false; // this is the default value. Change if you need to.
public $guarded = []; // this is the default value. Change if you need to.
protected $table = 'taggables';
public function taggable()
{
return $this->morphTo();
}
public function tag()
{
return $this->belongsTo(Tag::class/*, 'tag_id'*/);
}
}

Loading values from many-to-many realtionship plus values from auto-generated table in Laravel

I am working on some kind of ambulance app and I need help on how to load relationship.
So, I have table appointment_statuses (and it is populated over the seeder because I need only 3 states - Done, In Progress, Not Performed), I have also the many-to-many relationship between the User model and Appointment model (appointment_user table which holds only IDs of both models) and now I am working on EMR system which means I can check all appointments that patient had in history.
Here is the image of the issue
So under "Status" I want to load name of that ID from appointment_statuses table instead to have only ID.
These tables have this structure:
Appointments
Status
These tables have these values:
Appointments table
Appointment statuses table
These are relations:
User:
public function role()
{
return $this->belongsTo(Role::class);
}
public function patient()
{
return $this->hasOne(Patient::class);
}
public function appointments()
{
return $this->belongsToMany(Appointment::class);
}
Appointment:
public function users()
{
return $this->belongsToMany(User::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class);
}
Appointment_Statuses:
public function patient()
{
return $this->belongsTo(Patient::class);
}
public function appointment()
{
return $this->belongsTo(Appointment::class);
}
Here is a controller which is responsible for emr:
After I have added to controller this:
$user = User::with(['appointments', 'appointments.appointmentStatus'])->where('id', $id)->firstOrFail();
I get this in frontend:
{{ dd($user->toArray()) }}
SOLUTION TO THIS ISSUE
For anyone in future who gets this kind of issue just check the convention about the naming of the foreign keys. In my example, it was the issue, and if you are not sure that your foreign key name is correct then just in the model provide more information like this:
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class,'appointment_statuses_id','id');
}
You can use nested relationship
$user=User::with(['appointments','appointments.appointmentStatus'])
->where('id',$id)
->first();
Also you have to modify relationship
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class,'appointment_statuses_id','id');
}
For anyone in future who gets this kind of issue just check the convention about the naming of the foreign keys. In my example, it was the issue, and if you are not sure that your foreign key name is correct then just in the model provide more information like this:
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class,'appointment_statuses_id','id');
}

Laravel 5.7 not returning new record when global scope applied

I'm sure I'm missing something simple here but I am completely at a loss so any input would be greatly appreciated.
I have two models, User and Account with a many to many relationship with the model Channel. Accounts can be associated with multiple channels and users can also be associated with multiple channels. This has been created so that users can only access accounts that are associated with channels they are also associated with.
In order to do the filtering, I have applied a global scope to the account model so when I perform a query, it only returns accounts associated with the channels that the user is associated with. This works as intended for everything except newly created accounts.
If I call $account = Account::find($id) on a newly created account it returns null. If I drop the global scope it returns the account.
The only way I have found to fix the problem is if I sync the pivot table for the channel_user table and only include a single channel that is also associated with the account.
It feels like something is being cached somewhere but I'm not sure where to go from here. Please let me know what else you need to know
Account Model:
protected static function boot()
{
parent::boot();
static::addGlobalScope(new ChannelScope);
}
public function channels()
{
return $this->belongsToMany('App\Channel');
}
public function user()
{
return $this->belongsTo('App\User');
}
User Model:
public function accounts() {
return $this->hasMany('App\Account');
}
public function channels(){
return $this->belongsToMany( 'App\Channel' );
}
Channel Model:
public function accounts()
{
return $this->belongsToMany('App\Account');
}
public function users(){
return $this->belongsToMany('App\User');
}
Channel Scope:
public function apply(Builder $builder, Model $model)
{
$channels_ob = Auth::user()->channels;
$channels = array();
foreach ($channels_ob as $channel){
array_push($channels,$channel->id);
}
$builder->whereHas('channels', function ($q) use ($channels){
$q->where('channels.id','=', $channels);});
}
AccountController.php Store:
$account->save();
if (isset($request->chk_channels)){
foreach($request->chk_channels as $channel){
$ch = Channel::where('name',$channel)->get();
$ch_array[] = $ch[0]->id;
}
}
$account->channels()->sync($ch_array);
UserController.php update_channels:
public function update_channels(Request $request, $id)
{
$user = User::find($id);
if ($user->hasPermission('view_all_accounts')){
if (isset($request->chk_channels)){
foreach($request->chk_channels as $channel){
$ch = Channel::where('name',$channel)->get();
$ch_array[] = $ch[0]->id;
}
$user->channels()->sync($ch_array);
}
}
You can't have a column value equivalent to an array. You're building up an array of channels in your scope and then checking equivalency:
$q->where('channels.id','=', $channels);
Perhaps, you want whereIn:
$q->whereIn('channels.id', $channels);

How to join three tables with Laravel and keep data integrity

I am using Laravel 5.7 and now I am trying setup a relationship between three tables named:
Tickets (PK - TicketID, FK - CampusID)
Campus (PK - CampusID, FK - TechID)
User (PK - TechID)
I don't think I set up my models correctly as I am showing a ticket where the CampusID doesn't belong to the TechID. I am looking for a best practice on setting up Eloquent to keep the data integrity in place so I can prevent any abnormalities. As mentioned above the foreign key for Tickets should reference the Campus primary key, and Campus foreign key should reference the User primary key.
Here are my Models:
Ticket
protected $table='tickets';
public function user() {
return $this->belongsTo(User::class);
}
Campus
protected $table='campus';
public function user() {
return $this->belongsTo(User::class);
}
User
public function campus()
{
return $this->hasMany(Campus::class, 'TechID');
}
public function ticket()
{
return $this->hasMany(Ticket::class, 'AssignedTo');
}
Here is my controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
use App\Campus;
use App\Ticket;
class PagesController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
// Dashboard Page
public function index()
{
$user = Auth::user();
$campuses = Campus::where('TechID',$user->id)->pluck('CampusName');
$tickets = Ticket::all()->where('AssignedTo', $user->id);
return view('home')->with(['user' => $user,'campuses'=>$campuses,'tickets'=>$tickets]);
}
// Queue Page
public function Queue() {
return view('Pages.Queue');
}
// Reports Page
public function Reports() {
return view('Pages.Reports');
}
// Search Page
public function Search() {
return view('Pages.Search');
}
}
I think my models are fine, but my controller is probably where I made some mistakes. I've tried reading questions on here already, watching videos, and reading the Laravel docs, but nothing has really clicked with me yet. I really appreciate any and all help. Ideally it should cascade changes. So if I have a situation where I want to change what location a tech belongs to I could just make the change in the Campus table probably in the TechID column.
I would use Eager Loading.
public function index()
{
$user = User::with([
'campuses' => function($query) {
$query->select(['id', 'CampusName']);
},
'tickets'
])->where('id', Auth::id())->first();
$campuses = $user->campuses->pluck('CampusName');
$tickets = Ticket::all()->where('AssignedTo', $user->id);
return view('home')->with([
'user' => $user,
'campuses'=>$user->campuses->pluck('CampusName'),
'tickets'=>$user->tickets]);
}
EDIT
You need to update your User model.
public function campuses()
{
return $this->hasMany(Campus::class, 'TechID');
}
public function tickets()
{
return $this->hasMany(Ticket::class, 'AssignedTo');
}

`Trying to get property of non-object` using `hasManyThrough` relationship laravel 5

I am trying to develop a blog using Laravel 5 in which i have to show comment along with user on post.
Here is my database table schema.
User
id
name
Posts
id
post_content
user_id
Comments
id
comment
user_id
post_id
Here is my User Model
public function posts()
{
return $this->hasMany('App\Models\Posts');
}
public function comments(){
return $this->hasManyThrough('App\Models\Comments','App\Models\Posts');
}
Here is my Posts Model
public function user()
{
return $this->belongsTo('App\Models\User');
}
public function comments(){
return $this->hasMany('Ap\Models\Comments');
}
Here is my Comment Model
public function posts()
{
return $this->belongsTo('App\Models\Posts');
}
public function user(){
return $this->posts->name;
}
Here is my code how i am accessing user name
$comments = Comments::find(1);
$comment['comment'] = $comments->comment;
$comment['user_name'] = $comments->name;
$comment['post_id'] = $comments->posts->id;
may be i am not getting in right direction? if i am doing right then why it is not working.
In laravel 5 you do not call the model as you are doing. since the models are stored in the app folder just call like. Plus I think you need to define the relationship
class User extends Model {
public function phone()
{
return $this->hasOne('App\Phone');
}
}
class Phone extends Model {
public function user()
{
return $this->belongsTo('App\User');
}
}
$phone = Phone::find(1);
For the case of foreign keys and more regarding the Eloquent relationships in laravel 5 just follow the documentation on the laravel website. Make sure to look at dynamic properties of that are allowed by eloquent
http://laravel.com/docs/5.0/eloquent

Categories