Laravel Database Eloquent Relation queries for one model with multiple tables - laravel

I've defined a Model for multiple tables as seen here:
Laravel 4: can one model serve several DB tables?
I have many tables for the model Data:
data_2000
data_2001
...
And handle them in this model:
class Data extends \Eloquent {
public function __construct($year, array $attributes = array())
{
parent::__construct($attributes);
$this->table = 'data_' . $year;
}
public function country()
{
return $this->belongsTo('Country');
}
}
There's a One To Many relation with Country
class Country extends \Eloquent {
protected $table = 'countries';
public function data($year)
{
return $this->hasMany('Data('.$year.')');
}
public function region()
{
return $this->belongsTo('Region');
}
}
As I expected there's a missing argument if just return $this->hasMany('Data') so I tried $this->hasMany('Data('.$year.')') but of course it return an error of:
Class 'Data(2000)' not found
Is there a workaround to get all the Country->data from all the tables or just one table using eloquent's methods? Or should I just run multiple queries for all the years with a where('country_id', '=', $country->id)?
Thanks in advance, any ideas are appreciated.

Related

How to use where clause on multiple nested eager loading in Laravel 5.8.2

I have four tables that are having relationships form the first to the last where
users is a parent to village on applicant_id , Village to Cell on village_id , Cell to Sector on cell_id
and my eloquent query is as follows and it works perfectly without a where clause, when where clause is added I get an error:
Column not found: 1054 Unknown column 'applicant_id' in 'where clause'
// joins users , village ,cell and sector
$uvcsector = SectorApproval::with('Cell.Village.UserApplicant')
->where('applicant_id', 10)
-> get();
Models :
class Users extends Model
{
protected $table ="users";
public function VillageApplicant(){
return $this->hasMany(VillageApproval::class);
}
}
class VillageApproval extends Model
{
protected $table ="villageapplication";
// OnetoOne relationship inverse
public function UserApplicant()
{
return $this->belongsTo(Users::class, 'applicant_id');
}
// One Village application can be sent in one cell (OnetoOne)
public function Cell(){
return $this->hasOne(CellApproval::class);
}
}
class CellApproval extends Model
{
protected $table ="cellapplication";
// OnetoOne relationship inverse
public function Village()
{
return $this->belongsTo(VillageApproval::class, 'village_id');
}
// One Cell application can be sent in one sector (OnetoOne)
public function Sector(){
return $this->hasOne(SectorApproval::class);
}
}
class SectorApproval extends Model
{
protected $table ="sectorapplication";
// OnetoOne relationship inverse
public function Cell()
{
return $this->belongsTo(CellApproval::class, 'cell_id');
}
}
Use whereHas to search in the related tables.
$uvcsector = SectorApproval::with('Cell.Village.UserApplicant')
->whereHas('Cell.Village.UserApplicant', function($query) use ($id){
$query->where('applicant_id', $id);
})
-> get();
->where('village.application_id', 10)

Laravel hasMany relationship issue

I have a problem about table relationship in models. when I try to add hasMany relation there is an error popping up.
Call to undefined relationship [Plan100] on model [App\AllPlan].
This is the main table model places
protected $table = "places";
public $with = ["AllPlan"];
public function allplans()
{
return $this->hasMany("App\AllPlan");
}
And AllPlan table model
protected $table = "all_plans";
public function place()
{
return $this->belongsTo("App\Place");
}
No problem 'till here. I can see the AllPlan data inside the Places table on json response... But, the problem is popping up when I try to add hasMany relation into AllPlan table like below.
Now AllPlan table model looks like this.
protected $table = "all_plans";
public $with = [
"Plan100",
"Plan90",
];
public function place()
{
return $this->belongsTo("App\Place");
}
public function plan()
{
return $this->hasMany(
"App\Plan100",
"App\Plan90"
);
}
And the Plan100 table model look like this:
public function plan()
{
return $this->belongsTo("App\AllPlan");
}
But it's giving me an error. But I am not very sure where do I do wrong. Thank you.
Seems to me that you are trying to create two new relations, but this can't be done inside one function. Create two functions and refactor your code like this:
public function plan100()
{
return $this->hasMany(App\Plan100", 'foreign_key');
}
public function plan90()
{
return $this->hasMany(App\Plan90", 'foreign_key');
}

How can you use Eloquent to find related values two tables away and in a different database?

I am developing a system that extends an existing ERP system, and so is accessing two databases (both on the same MS SQL Server). I am trying to access items on the "Equipment" model (this is a table in the ERP database) through the "EquipmentInstance" model from the "EquipmentType" model (these two are in the new database). They are related as per this diagram:
The three models are as follows:
EquipmentType
namespace App;
use Illuminate\Database\Eloquent\Model;
class EquipmentType extends Model
{
protected $table = 'dbo.EquipmentType';
protected $connection = 'sqlsrv';
protected $primaryKey = 'EquipmentTypeID';
protected $fillable = [
'TypeName',
'ProductManager'
];
public function EquipmentInstance()
{
return $this->hasMany(EquipmentInstance::class,'EquipmentTypeID', 'EquipmentTypeID');
}
public function Equipment()
{
return $this->hasManyThrough(
Equipment::class,
EquipmentInstance::class,
'TypeID',
'PartNum',
'TypeID',
'PartNum'
);
}
}
EquipmentInstance
namespace App;
use Illuminate\Database\Eloquent\Model;
class EquipmentInstance extends Model
{
protected $table = 'dbo.EquipmentInstance';
protected $primaryKey = 'EquipmentID';
protected $keyType = 'string';
protected $connection = 'sqlsrv';
protected $fillable = [
'EquipmentID',
'EquipmentTypeID',
'PartNum'
];
public function Part()
{
return $this->belongsTo(Part::class,'PartNum','PartNum');
}
public function Equipment()
{
return $this->hasMany(Equipment::class,'PartNum', 'PartNum');
}
public function EquipmentType()
{
return $this->belongsTo(EquipmentType::class); /*,'EquipmentTypeID', 'EquipmentTypeID'*/
}
/* public function Attribute()
{
return $this->belongsTo(Equipment::class,'SerialNumber', 'JobNum');
}
public function TechNote()
{
return $this->belongsTo(Equipment::class,'SerialNumber', 'JobNum');
}*/
}
Equipment
namespace App;
use Illuminate\Database\Eloquent\Model;
class Equipment extends Model
{
protected $table = 'ERP.SerialNo';
public $timestamps = false;
protected $primaryKey = 'SerialNumber';
protected $keyType = 'string';
protected $connection = 'epicor';
public function Part()
{
return $this->belongsTo(Part::class,'PartNum','PartNum');
}
public function Customer()
{
return $this->belongsTo(Customer::class,'CustNum', 'CustNum');
}
public function Equipment()
{
return $this->belongsTo(Equipment::class,'SerialNumber', 'JobNum');
}
public function EquipmentInstance()
{
return $this->belongsTo(EquipmentInstance::class,'PartNum', 'PartNum');
}
}
On the EquipmentType Controller I am trying to get all of the Equipment through the EquipmentInstance so for each EquipmentInstance I can display all of the Equipments.
EquipmentType Controller
public function show(EquipmentType $EquipmentType)
{
$EquipmentInstance = $EquipmentType->EquipmentInstance()
->get();
$Equipments = $EquipmentType->EquipmentInstance()->Equipment()
->get();
return view('EquipmentType.show', compact('EquipmentType', 'EquipmentInstance', 'Equipments'));
}
The error message I get is
"BadMethodCallException
Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::Equipment()"
I believe the issue is that (my understanding is rocky) that Eloquent is trying to write one query to access both databases, which is failing. However I am not sure how to proceed.
Any help would be greatly received.
Richard
Update
I have implemented what gbalduzzi suggested in his answer, which almost worked, and I am sure the issue is with my blade implemtention. I have nested two forloops:
#foreach($EquipmentType->EquipmentInstance as $EquipmentInstance)
#foreach($Equipments as $Equipment)
<tr>
<td>{{$EquipmentInstance->PartNum}} - {{$EquipmentInstance->Part->PartDescription}}</td>
<td>{{$Equipment->SerialNumber}}</td>
<td>{{$Equipment->SNStatus}}</td>
<td>{{--{{$Equipment->Customer->LegalName}}--}}</td>
</tr>
#endforeach
#endforeach
Which is displaying the serial numbers (from the Equipment model) for the first EquipmentInstance only and repeating them for all EquipmentInstanced.
Update 2
I have proven that the issue is with first() in the suggested answer, as if I change this to last() the results change as you would expect (see update 1). So my question now is:
Is there an equivelant of first(), last() which is all() or every()?
The problem is not in your database configuration, but in the way you are calling the relationship. Instead of:
$Equipments = $EquipmentType->EquipmentInstance()->Equipment()
->get();
use:
$Equipments = $EquipmentType->EquipmentInstance->first()->Equipment()
->get();
Long answer
In Eloquent, you can use a relationship in 2 ways:
as a magic field (i.e. $EquipmentType->EquipmentInstance). In this case you get as a result an instance of the model EquipmentInstance (also, if you already queried it, it directly returns the value without executing a new query)
as an eloquent query (i.e. $EquipmentType->EquipmentInstance()). Using it as a function, you don't get the model but a RelationShip instance, that is basically an eloquent query and can be chained with other eloquent methods, such as where, orderBy, ecc
So, if you call $EquipmentType->EquipmentInstance()->Equipment() it throws an error because the eloquent query does NOT have the relationship Equipment().
On the other hand, $EquipmentType->EquipmentInstance->Equipment works because it calls Equipment on the actual model instance, that has the Equipment relationship properly defined.

Eloquent hasOne relationship Not working laravel 5.4

I am trying to keep a relationship between two tables in my database.
Users Table:
Id User_id Name
Contacts Table:
Id User_Id contacts
I am saving multiple contacts in the contacts table. Now i want to retrieve all the contacts saved to the User_ID. For that, i am trying to establish a hasOne relationship but i get a error for the following code can someone let me know what i am doing wrong? I am following the official documentation for this.
User model:
class users extends Model
{
protected $table = "users";
public function contacts()
{
return $this->hasOne('App\contacts','User_Id');
}
}
Contacts Model:
class contacts extends Model
{
public $table = "contacts";
public function Users(){
return $this->belongsTo('App\Users','User_id');
}
}
Controller:
public function eloquentget(){
$contacts = Users::find(1)->contacts->first();
return response()->json($contacts,200);
}
When i try this code in postman i get an Exception :
ErrorException
Trying to get property of non-object
What am i doing wrong? Any help will be appreciated.
Since you are saving multiple Contacts for any given User then you are using the wrong relation. You need to setup a One-Many relationship using hasMany().
class users extends Model
{
protected $table = "users";
public function contacts()
{
return $this->hasMany('App\contacts','User_Id','User_Id');
}
}
Try something like this
class users extends Model
{
protected $table = "users";
public function contacts()
{
return $this->hasMany('App\contacts','User_Id','User_Id');
}
}
And on your controller, You can use it like this
$contacts= User::find(1)->contacts; // it will return an array of collection
You don't need to use ->first(); because you already used relation hasOne
just use :
$contacts = Users::find(1)->contacts;
return response()->json($contacts,200);

Laravel query multiple tables using eloquent

hi sorry bit of a newbie here but I am have three tables users, profiles, friends. they all have the user_id fields within them and I want fetch all of the fields in one statement using Eloquent and not DB::statement and doing the table joins.
How can I achieve this?
Try this
use the User class and the with method that laravel has to query model relationships
$user = User::with(['profile', 'friend'])->get();
Ensure your models has the correct relationships as follows:
app/models/User.php
public function friend () {
return $this->hasMany('Friend');
}
public function profile () {
return $this->hasOne('Profile');
}
app/models/Profile.php
public function user() {
return $this->belongsTo('User');
}
app/models/Friend.php
public function user() {
return $this->belongsTo('User');
}
use some thing like this:
You should define relations in your models with hasOne, hasMany.
class Review extends Eloquent {
public function relatedGallery()
{
$this->hasOne('Gallery', 'foreign_id', 'local_id');
}
}
class Gallery extends Eloquent {
public function relatedReviews()
{
$this->hasMany('Review', 'foreign_id', 'local_id');
}
}
$gallery = Gallery::with('relatedReviews')->find($id);
Will bring the object Gallery with
$gallery->id
gallery->name
...
$gallery->relatedReviews // array containing the related Review Objects

Resources