Laravel Eloquent - relation of relation - three model relationship - php

I am trying to convert the below DB query to an eloquent relation.
$device_barcodes = ["BSC0337", "BSC0503", "BSC0626"];
$devices = DB::table('devices')
->leftjoin('devices_repairs', 'devices_repairs.device_id', '=', 'devices.device_id')
->leftJoin('staff','staff.staff_id','devices_repairs.repair_damaged_by')
->whereIn('barcode', $device_barcodes)
->get();
So far I have the below, but I am struggling with the staff relation.
$devices = Devices::with('repairDetails')->whereIn('barcode', $device_barcodes)->get();
I've overcome this for now with the below, but this is not ideal.
foreach($devices as $device) {
$staff_name = Staff::find($device->repairDetails->repair_damaged_by);
$device->staff_name = $staff_name->staff_name;
}
I am hoping for something like:
$devices = Devices::with('repairDetails')->with('staffDetails')->whereIn('barcode', $device_barcodes)->get();
This way I can show the device details, the repair details and the staff name on my blade form.
So the basic issue is I am trying to relate three models together.
Devices is the top model, where I join with DevicesRepairs using the device_id primary and foreign keys. But for the Staff model I need to join devices_repairs.repair_damaged by to staff.staff_id.
Here are my models:
Devices:
class Devices extends Model
{
/**
* #var bool $timestamps Disable timestamps
*/
public $timestamps = false;
/**
* #var string $table Name of the db table
*/
protected $table = 'devices';
/**
* #var string $primaryKey Name of the primary key
*/
protected $primaryKey = 'device_id';
/**
* #var array $fillable The attributes that are mass assignable.
*/
protected $fillable = [
'status',
'order_reference',
'model',
'serial',
'imei',
'barcode',
'mobile_number',
'helpdesk_url_id',
'device_notes'
];
use Searchable;
function repairDetails() {
return $this->hasOne(DevicesRepairs::class, 'device_id');
}
function repairHistoryDetails() {
return $this->hasOne(DevicesRepairsHistory::class, 'device_id');
}
}
DevicesRepairs:
class DevicesRepairs extends Model
{
use HasFactory;
protected $table = 'devices_repairs';
protected $primaryKey = 'device_id';
public $timestamps = false;
protected $fillable = [
'device_id',
'repair_damanged_by',
'repair_damage_type',
'repair_date_received',
'repair_date_sent_for',
'repair_damage_notes',
'repairer_name',
'repair_is_user_damage',
'job_number',
'operator_date_received',
'operator_date_received_by',
'operator_date_sent',
'operator_sent_by',
'photo_id',
'photo_id_back'
];
function device() {
return $this->hasOne(Devices::class, 'device_id');
}
//This doesn't work - seems to return a random staff member.
function staffDetails() {
return $this->hasOne(Staff::class,'staff_id','repair_damaged_by');
}
}
Staff:
class Staff extends Model
{
use searchable;
/**
* #var bool $timestamps Disable timestamps
*/
public $timestamps = false;
/**
* #var string $table Name of the db table
*/
protected $table = 'staff';
/**
* #var string $primaryKey Name of the primary key
*/
protected $primaryKey = 'staff_id';
/**
* #var array $fillable The attributes that are mass assignable.
*/
protected $fillable = [
'staff_id',
'staff_name',
'manager_id',
'is_active',
'is_mdm_user',
'user_id',
];
}
My ultimate aim is to be able to return fields like this in my view:
{{$device->barcode}}
{{$device->repairDetails->repair_damage_notes}}
//The above work fine but not this:
{{$device->staffDetails->staff_name}}

treat at as a pivot table, a many to many relation between devices and staff
class Devices extends Model
{
public function damagedBy()
{
return $this->belongsToMany(Staff::class, 'devices_repairs', 'device_id', 'repair_damaged_by');
}
So the query will be like
$device_barcodes = ["BSC0337", "BSC0503", "BSC0626"];
$devices = Devices::with('damagedBy')->whereIn('barcode', $device_barcodes)->get();

Related

laravel model relationships hasOne

I have two table, the first is accounts (User model) which is used for auth and the other is students (t_student model) which contains the students details such student id (S_ID)
I am trying to get the S_ID inside the controller in store function for the logged in user.
$application = new Application;
$application->A_ID= $request-> input('A_ID');
$application->S_ID= Auth()->User()->students()->S_ID;
$application->S_Justification= $request-> input('Justification');
$application->save();
return redirect('/Abstracts')->with ('success', 'application submitted' );
MY User model (accounts table)
class User extends Authenticatable{
protected $table = 'accounts';
protected $primaryKey = 'Account_ID';
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'email', 'password', 'Account_Type', 'name'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function abstracts(){
return $this ->hasMany('App\Project' , 'PI_ID');
}
public function academics(){
return $this ->hasOne('App\T_user', 'Account_ID');
}
public function students(){
return $this ->hasOne('App\t_student', 'Account_ID');
}}
my t_student model
class t_student extends Model{
protected $table = 't_student';
protected $primaryKey = 'S_ID';
public function account(){
return $this ->belongsTo('App\User', 'Account_ID');}
and I am getting this error
Undefined property: Illuminate\Database\Eloquent\Relations\HasOne::$S_ID
EDIT: The error I am getting is related to my controller
$application->S_ID= Auth()->User()->students()->S_ID;
and the reason is my relationship but I am not sure what is wrong about it
You should modify it:
$application->S_ID= Auth()->User()->students->S_ID;
In User model u must added the foregnkey to second parameter in hasOne func
so replace the Account_ID by S_ID
for ex :
// in user model
public function students()
{
return $this ->hasOne('App\t_student', 'S_ID');
}
// in ur controller romove the parentheses of students propriety

How to chain 3 laravel nested models

I am trying to chain 3 models together parent->child->child of child. So I can access it in an eloquent statement.
Parent Model:
class CertificationType extends Model
{
use SoftDeletes;
public $timestamps = true;
protected $table = 'certification_type';
protected $dates = ['deleted_at'];
protected $fillable = array('certification_type_name', 'fa_code', 'icon_image');
protected $hidden = ['created_at', 'updated_at',];
public function certification_type()
{
return $this->hasMany('App\Certification');
}
}
Child Model
class Certification extends Model
{
protected $table = 'certification';
public $timestamps = true;
use SoftDeletes;
protected $dates = ['deleted_at'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = array('certification_type_id', 'certification_name', 'certication_date', 'certification_license_number', 'certification_course_length', 'certification_course_description', 'certification_course_topics_list_id');
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'created_at', 'updated_at',
];
public function certification_type()
{
return $this->belongsTo('App\CertificationType',
'certification_type_id');
}
public function certification_course_topics_list()
{
return $this->hasMany('App\CertificationCourseTopicsList');
}
}
Child of Child Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class CertificationCourseTopicsList extends Model
{
protected $table = 'certification_topics_list';
public $timestamps = true;
use SoftDeletes;
protected $dates = ['deleted_at'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = array('certification_id', 'certification_topic_description');
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'created_at', 'updated_at',
];
public function certification_course_topics_list()
{
return $this->belongsToMany('App\Certification', 'certification_id');
}
}
The eloquent statement I am using is:
$CertificationTypes = App\CertificationType::orderBy('id',"asc")->with('certification_type')->get()->groupBy('id');
What I have accomplished is CertificationType has a child of Certifications attached in the query. What I need is the 2nd child to be in the query as well:
CertificationType::orderBy('id',"asc")->with('certification_type')->get()->groupBy('id')->with('certification')->get()->groupBy('id');
I also tried:
CertificationType::orderBy('id',"asc")->with('certification_type, certifications')->get()->groupBy('id');
That did not work: Call to undefined relationship [certification_type, certifications] on model [App\CertificationType].
Also tried:
CertificationType::orderBy('id',"asc")->with('certification_type', 'certifications')->get()->groupBy('id');
That did not work: Call to undefined relationship [certifications] on model [App\CertificationType].
Any help would be appreciated!
You need more order in code. I would make three models with proper relations as : belongsTo and hasMany. Then in each view you can use data from model with function of relation.
Example of proper model with relation:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('App\Comment');
}
}
Read more here, that will save your time: https://laravel.com/docs/5.5/eloquent-relationships#one-to-many

How to access other related model data in Laravel?

I am creating a user profile page and I want to retrieve the data from my User model and UserProfile model. But I have a problem in getting the result. Here's what I did:
User model
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'username',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/*
public function isAdmin() {
return $this->admin;
}
*/
public function profile() {
return $this->hasOne('App\UserProfile');
}
}
UserProfile model
class UserProfile extends Model
{
protected $table = 'user_profile';
protected $fillable = [
'phone',
'address'
];
public function user() {
return $this->belongsTo('App\User');
}
}
Then I access the relation in my ProfileController
public function getProfile($username) {
$user = User::with('user_profile')->where('username', $username)->get();
dd($user);
}
And I got this error:
Call to undefined relationship [user_profile] on model [App\User].
The user_profile is my table name
Use proper relationship name:
$user = User::with('profile')->where('username', $username)->first();
Also, in this case you should use the first() method to get an user object.

Join 2 tables in Eloquent Laravel 5.2 - How to retrieve all data from both two tables?

I have two tables
1.
Game Console
-- console_id
-- console_name
2.
Game Labels
-- game_label_id
-- console_id (foreign key)
-- title
-- description
-- image
-- created
GameConsole Model
namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;
class GameConsole extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
public $timestamps = false;
protected $table = 'console';
protected $fillable = array('console_name', 'description', 'created');
protected $primaryKey = 'console_id';
public function labels()
{
return $this->hasMany('App\Http\Models\GameLabel','console_id');
}
}
GameLabel Model
namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;
class GameLabel extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
public $timestamps = false;
protected $table = 'game_label';
protected $fillable = array('game_label_id','console_id', 'title','description','image', 'release_date','status','created');
protected $primaryKey = 'game_label_id';
public function console()
{
return $this->belongsTo('App\Http\Models\GameConsole','console_id');
}
}
I write this query to get all game labels with console_name
GameLabel::with('console')->get();
But I am only getting records from game_label table, not from console table.
Can any body please tell me that what query I have to write to get all records?
Please don't suggest me about query builder joins. I don't want to use that.
namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;
class GameLabel extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
public $timestamps = false;
protected $table = 'game_label';
protected $fillable = array('game_label_id','console_id', 'title','description','image', 'release_date','status','created');
protected $primaryKey = 'game_label_id';
public function console()
{
return $this->belongsTo('App\Http\Models\GameConsole', 'console_id', 'console_id');
}
}
in belongs to first console_id represent Game Console table id and and second console_id represent game_label table console_id
now in controller
GameLabel::with('console')->get();
i think all data will be availbale in array under console key
Yes, its under console key. I found the solution.
the console name was not getting in the view so get the console name in view like this
foreach($game_label as $getGameLabel){
echo $getGameLabel->console->console_name;
}

Laravel 4 - Undefined Property when retrieving a field value which belongsTo another table

I'm trying to get the 'name' field of the 'users' table in my Articles (REST) controller.
These are my models:
// models/Article.php
class Article extends Eloquent {
protected $fillable = [];
protected $table = 'articles';
public function user(){
return $this->belongsTo('User','user_id');
}
public function upload(){
return $this->has_one('Upload');
}
}
// models/User.php
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $fillable = array('email','password','name');
public function articles(){
return $this->hasMany('Article','user_id');
}
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
public function getAuthPassword()
{
return $this->password;
}
public function getReminderEmail()
{
return $this->email;
}
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
}
// controllers/ArticlesController.php
class ArticlesController extends \BaseController {
public function index() // GET (all)
{
$articles = Article::all();
foreach ($articles as $article) {
// ** ERROR ** Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$id
var_dump("title: ".$article->titulo." | user: ".$article->user()->id .' | email: '.$article->user()->email );
}
}
// other functions [....]
}
So..How can I get the fields from 'users' table properly?? I've been searching in the Laravel doc and this web and... I haven't' found the error :(
I've set up the database relationships on the migrations files and I've checked out the mysql databases relations diagram and everything is ok.
Have you checked the keys properly. belongsTo's second parameter should be the local key whereas hasMany's second parameter is the foreign key.

Categories