Laravel hasManyThrough polymorphic table not working - php

I've following relationship:
class Project extends Model
{
public function invitors()
{
return $this->hasMany(Invitation::class)
}
}
// User model
class User extends Model
{
public function invitations()
{
return $this->morphMany('App\Invitation', 'invitee');
}
}
// Business Model
class Business extends Model
{
public function invitations()
{
return $this->morphMany('App\Invitation', 'invitee');
}
}
// Invitation model
class Invitation extends Model
{
public function invitee()
{
return $this->morphTo();
}
public function project()
{
return $this->belongsTo(Project::class);
}
}
What I want is to get project invitors (users, and businesses). When I use from $project->invitors->invitee its not working.

In your example $project->invitors is a collection of Invitation instances, and it hasn't property invitee. You can use helper pluck to loop $project->invitors and get their invitees:
$invitees = $project->invitors->pluck('invitee');
As a response to the first comment:
to get specific attributes of fetched linked models ("invitee") you can specify accessors:
class Business extends Model
{
...
public function getInviteeNameAttribute() {
return $this->name;
}
}
class User extends Model
{
...
public function getInviteeNameAttribute() {
return $this->first_name . ' ' . $this->last_name;
}
}
...then get that attribute from invitee:
$invitees[0]->invitee_name
See https://laravel.com/docs/7.x/eloquent-mutators#defining-an-accessor

Related

How to get a single element with a model with relations Laravel

I have three models Driver Worker and Group. The models are like this:
class Group extends Model
{
.....
public function driver()
{
return $this->belongsTo('App\Driver');
}
public function worker()
{
return $this->belongsTo('App\Worker');
}
}
Drivers
class Driver extends Model
{
public function groups()
{
return $this->hasMany('App\Group');
}
}
Worker
class Workerextends Model
{
public function groups()
{
return $this->hasMany('App\Group');
}
}
But how can I get a single element with the relationships that I have defined in my models. I have this in my controller but I only get the first element of the table. I need to get the element with the id and also the relations.
public function show(Group $group)
{
return $group->with(['worker','driver'])->first();
}
try this
public function show(Group $group,$id){
$group = $group->where('id',$id)->with(['worker','driver'])->first();
return $group
}
in your Route
Route::get('/group/show/{id}', 'GroupController#show')->name('group.show');

Laravel Polymorphic Relations returns NULL

I've read many posts about this issue but none of them works for me. I have a 'ISA' relationship in my database. A person can be either a Patient or a Nurse:
class Person extends Model
{
protected $table = 'persons';
public function commentable()
{
return $this->morphTo();
}
}
class Patient extends Model
{
public function persons()
{
return $this->morphMany('App\Person', 'commentable');
}
}
class Nurse extends Model
{
public function persons()
{
return $this->morphMany('App\Person', 'commentable');
}
}
This is my tables and the data inside them:
And this is my Route:
Route::get('person', function () {
$person = Person::find(1)->commentable();
return json_decode(json_encode($person), true);
});
I get an empty array!
You have to access the relationship as a property:
$person = Person::find(1)->commentable;

Eloquent Relationships (Laravel 5.4)

I'm making a Laravel 5.4 application, but I'm having a hard time figuring out how I should structure my data with eloquent relationships.
This is my models and how I want them to be related:
School → Has classes, users and events
User → Can belong to a school. Can have classes and sessions (with cases)
Class → Belongs to a school. Has users and subjects. Can have homework
Subject → Belongs to a class
Session → Belongs to a user. Can have cases
Case → Belongs to a session
Event → Belongs to a school
Homework → Belongs to a class
How should I structure this with eloquent relation functions (belongsTo, hasMany and so on) in my Laravel 5.4 project?
Assuming Class, User and Event models has a property school_id and the primary key you ant to use is id of the respective model, your Class, User, Event and School models should look like as follow.
School
class School extends Model
{
public function users(){
return $this->hasMany('App\User');
}
public function classes(){
return $this->hasMany('App\Class');
}
public function sessions(){
return $this->hasMany('App\Session');
}
}
User
class User extends Model
{
public function school(){
return $this->belongsTo('App\School');
}
public function classes(){
return $this->hasMany('App\Class');
}
public function events(){
return $this->hasMany('App\Event');
}
}
Class
class Class extends Model
{
public function school(){
return $this->belongsTo('App\School');
}
public function users(){
return $this->hasMany('App\User');
}
public function subjects(){
return $this->hasMany('App\Subject');
}
public function homeworks(){
return $this->hasMany('App\Homework');
}
}
Event
class Class extends Model
{
public function school(){
return $this->belongsTo('App\School');
}
}
You can use these relationships to define queries with chaining capability. e.g. if you want to get all the events associated with a School that has a id property equals to $id you can write,
$events = App\School::find($id)->events;
Laravel Documentation explains it well
The correct way to do this is
SCHOOL
public function classes()
{
return $this->hasMany('App\Class');
}
public function users()
{
return $this->hasMany('App\User');
}
public function events()
{
return $this->hasMany('App\Event');
}
CLASS
public function school()
{
return $this->belongsTo('App\School');
}
public function subjects()
{
return $this->hasMany('App\Subject');
}
public function homeworks()
{
return $this->hasMany('App\Homework');
}
public function users()
{
return $this->belongsToMany('App\User','class_users','class_id','user_id');
// this should be many to many because users can also have many classes
}
USER
public function school()
{
return $this->belongsTo('App\School');
}
public function classes()
{
return $this->belongsToMany('App\Class','class_users','user_id','class_id');
// this should be many to many as explained to class
}
public function sessions()
{
return $this->belongsToMany('App\Session','session_users','user_id','session_id');
// like classes do, this should be many to many relationship because sessions can also have many users
}
SUBJECT
public function class()
{
return $this->belongsTo('App\Class');
}
SESSION
public function users()
{
return $this->belongsToMany('App\User','session_users','session_id','user_id');
// should be many to many as well
}
public function cases()
{
return $this->hasMany('App\Case');
}
CASE
public function session()
{
return $this->belongsTo('App\Session');
}
EVENT
public function school()
{
return $this->belongsTo('App\School');
}
HOMEWORK
public function class()
{
return $this->belongsTo('App\Class');
}
With the School model and underlying table created, it’s time to create the relation. Open the School model and create a public method named classes, users and events; inside it referencing the hasMany method:
School :
class School extends Model {
public function classes()
{
return $this->hasMany('App\Class');
}
public function users()
{
return $this->hasMany('App\User');
}
public function events()
{
return $this->hasMany('App\Event');
}
}
User :
class User extends Model {
public function school(){
return $this->belongsTo('App\School');
}
public function classes(){
return $this->hasMany('App\Class');
}
public function sessions(){
return $this->hasMany('App\Session');
}
}
Class :
class Class extends Model {
public function school(){
return $this->belongsTo('App\School');
}
public function users(){
return $this->hasMany('App\User');
}
public function subjects(){
return $this->hasMany('App\Subject');
}
public function homeworks(){
return $this->hasMany('App\Homework');
}
}
Subject :
class Subject extends Model {
public function class(){
return $this->belongsTo('App\Class');
}
}
Session:
class Session extends Model {
public function user(){
return $this->belongsTo('App\User');
}
public function cases(){
return $this->hasMany('App\Case');
}
}
Case :
class Case extends Model {
public function session(){
return $this->belongsTo('App\Session');
}
}
Event :
class Event extends Model {
public function school(){
return $this->belongsTo('App\School');
}
}
Homework:
class Homework extends Model {
public function class(){
return $this->belongsTo('App\Class');
}
}
For more details of hasMany relationship, Please check the link here : EasyLaravelBook

Chain of hasMany or hasManyThrough through N models

How can I get all the submissions belongs to a particular user?
Trying this:
$user=User::find(1);
dd($user->submissions);
Throwing error:
Call to undefined method Illuminate\Database\Query\Builder::hasMany()
Will I have to loop through the models?
Here are the models:
class User extends Eloquent implements ConfideUserInterface, BillableInterface
{
public function categories()
{
return $this->hasMany('Category');
}
public function forms()
{
return $this->hasManyThrough('App\Models\Form', 'Category');
}
public function submissions()
{
return $this->hasMany('Category')->hasMany('Form')->hasMany('Submission');
}
}
class Category extends \Eloquent {
public function user()
{
return $this->belongsTo('User');
}
public function forms()
{
return $this->hasMany('App\Models\Form');
}
public function submissions()
{
return $this->hasManyThrough('Submission', 'App\Models\Form', 'id', 'form_id');
}
}
namespace App\Models;
class Form extends \Eloquent {
public function user()
{
return $this->category->user();
}
public function category()
{
return $this->belongsTo('Category');
}
public function submissions()
{
return $this->hasMany('Submission');
}
}
class Submission extends \Eloquent {
public function user()
{
return $this->form->category->user();
}
public function category()
{
return $this->form->category();
}
public function form()
{
return $this->belongsTo('App\Models\Form');
}
}
That doesn't really work that way with chaining relations...
What you can do, is this:
$submissions = Submission::whereHas('form.category.user', function($q){
$q->where('id', 1);
})->get();
Note that whereHas with nested relationships has only been added in the latest Laravel 4 release. Make sure to composer update.
If i'm not getting your question wrongly, you need to define relationship correctly.
According to laravel 4.2 you can use below kind of code to define relations:
class User extends \Eloquent implements ConfideUserInterface, BillableInterface{
//...
public function submissions(){
return $this->hasMany('Submission');
}
}
//...
class Submission extends \Eloquent {
public function user()
{
return $this->belongsTo('User');
}
//...
}
To further reading take a look at: http://laravel.com/docs/4.2/eloquent#relationships

Retrieving relationships of relationships using Eloquent in Laravel

I have a database with the following tables and relationships:
Advert 1-1 Car m-1 Model m-1 Brand
If I want to retrieve an Advert, I can simply use:
Advert::find(1);
If I want the details of the car, I could use:
Advert::find(1)->with('Car');
However, if I also want the detail of the Model (following the relationship with Car), what would the syntax be, the following doesn't work:
Advert::find(1)->with('Car')->with('Model');
Many thanks
It's in the official documentation under "Eager Loading"
Multiple relationships:
$books = Book::with('author', 'publisher')->get();
Nested relationships:
$books = Book::with('author.contacts')->get();
So for you:
Advert::with('Car.Model')->find(1);
First you need to create your relations,
<?php
class Advert extends Eloquent {
public function car()
{
return $this->belongsTo('Car');
}
}
class Car extends Eloquent {
public function model()
{
return $this->belongsTo('Model');
}
}
class Model extends Eloquent {
public function brand()
{
return $this->belongsTo('Brand');
}
public function cars()
{
return $this->hasMany('Car');
}
}
class Brand extends Eloquent {
public function models()
{
return $this->hasMany('Model');
}
}
Then you just have to access this way:
echo Advert::find(1)->car->model->brand->name;
But your table fields shoud be, because Laravel guess them that way:
id (for all tables)
car_id
model_id
brand_id
Or you'll have to specify them in the relationship.
Suppose you have 3 models region,city,hotels and to get all hotels with city and region then
Define relationship in them as follows:-
Hotel.php
class Hotel extends Model {
public function cities(){
return $this->hasMany(City::class);
}
public function city(){
return $this->belongsTo('App\City','city_id');
}
}
City.php
class City extends Model {
public function hotels(){
return $this->hasMany(Hotel::class);
}
public function regions(){
return $this->belongsTo('App\Region','region_id');
}
}
Region.php
class Region extends Model
{
public function cities(){
return $this->hasMany('App\City');
}
public function country(){
return $this->belongsTo('App\Country','country_id');
}
}
HotelController.php
public function getAllHotels(){
// get all hotes with city and region
$hotels = Hotel::with('city.regions')->get()->toArray();
}
will adding the relation function just ask for the relation needed
public function Car()
{
return $this->belongsTo(Car::class, 'car_id')->with('Model');
}
but if you want a nested relation just use the period in the with
Advert::with('Car.Model')->find(1);
but for multi-relation use the array
Advert::with('Car','Model')->find(1);

Categories