Laravel foreign key relation - Unknown column in field list - php

I have Member and SkyMedRep models:
class SkyMedRep extends Model
{
protected $fillable = [
'id','rep_id',
];
public function members()
{
return $this->hasMany('App\Member');
}
}
class Member extends User
{
public function sky_med_rep()
{
return $this->belongsTo('App\SkyMedRep');
}
}
This is migration for Member:
public function up()
{
Schema::create('members', function (Blueprint $table) {
$table->increments('id');
$table->integer('sky_med_rep_id')->unsigned();
$table->timestamps();
});
Schema::table('members', function($table) {
$table->foreign('sky_med_rep_id')->references('id')- >on('sky_med_reps')->nullable(true);
});
}
Member model contains foreign key referencing SkyMedRep model.After defining such relationship, I am trying to assign object of SkyMedRep model to the object of Member model like:
$member->sky_med_rep = $sky_med_rep;
Here, $member is the object of Member model and $sky_med_rep is the object of SkyMedRep model.
When I try $member->save(), I am getting error "Unknown column 'sky_med_rep' in field list". It seems that sky_med_rep is not being able to treat as foreign key reference. Below is my code to save the data:
$member = new Member();
$member->sky_med_member_number = $request->input("sky_med_member")['member_number'];
$sky_med_rep = SkyMedRep::firstOrNew(['rep_id' => $request->input("sky_med_member")['rep_id']]);
$sky_med_rep->name = $request->input("sky_med_member")['name'];
$sky_med_rep->save();
$member->sky_med_rep = $sky_med_rep;
$member->save();

Instead of $member->sky_med_rep = $sky_med_rep; You should write $member->sky_med_rep->associate($sky_med_rep);.
Also have a look at http://www.php-fig.org/psr/psr-2/ coding style guide. Method names should be camelCase, not underscore.

Related

Handling mapping table in laravel eloquent

In my application, there will be multiple investors tagged for single purchase entry. So on loading a purchase entry, I should get all the investors associated.
In my controller,
return response()->json(GoldPurchase::with('investors')->get());
Mapping table schema,
Schema::create('gold_purchase_investor', function (Blueprint $table) {
$table->increments('id');
$table->integer('investor_id')->unsigned();
$table->integer('purchase_id')->unsigned();
$table->timestamps();
$table->foreign('investor_id')
->references('id')
->on('investors')
->onDelete('cascade');
$table->foreign('purchase_id')
->references('id')
->on('gold_purchases')
->onDelete('cascade');
});
Purchase model,
class GoldPurchase extends Model
{
public function investors() {
return $this->hasMany('App\GoldPurchaseInvestor');
}
}
Investor model,
class Investor extends Model
{
protected $fillable = ['name', 'address', 'mobile', 'email'];
public function purchases() {
return $this->hasMany('App\GoldPurchase');
}
}
PurchaseInvestor model,
class GoldPurchaseInvestor extends Model
{
protected $table = 'gold_purchase_investor';
public function purchase() {
return $this->belongsTo('App\GoldPurchase');
}
public function investor() {
return $this->belongsTo('App\Investor');
}
}
With this, I am getting error,
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'gold_purchase_investor.gold_purchase_id' in 'where clause' (SQL: select * from `gold_purchase_investor` where `gold_purchase_investor`.`gold_purchase_id` in (1))
You have to specify the custom foreign key:
public function investors() {
return $this->hasMany('App\GoldPurchaseInvestor', 'purchase_id');
}
But this is actually a case for a BelongsToMany relationship:
public function investors() {
return $this->belongsToMany('App\Investor', 'gold_purchase_investor', 'purchase_id');
}
From the Eloquent Relationship:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
$this->hasMany('App\Comment', 'foreign_key', 'local_key');
So try to write your foreign key and local key in the relationships
In your case I think it would be something like that:
class GoldPurchase extends Model`
{
public function investors() {
return $this->hasMany('App\GoldPurchaseInvestor', 'investor_id', 'id');
}
}
Use belongsToMany for many-to-many relationships.
GoldPurchase.php
class GoldPurchase extends Model{
public function investors() {
return $this->belongsToMany('App\Investor','gold_purchase_investor','purchase_id','investor_id');
}
}
Investor.php
class Investor extends Model{
protected $fillable = ['name', 'address', 'mobile', 'email'];
public function purchases() {
return $this->belongsToMany('App\GoldPurchase','gold_purchase_investor','investor_id','purchase_id');
}
}
You don't need a third model for pivot table at all.
GoldPurchaseInvestor is not at all needed.

Laravel 5.6 Eloquent Relationship not returning value

This is a section of Two of my related models in Laravel
class Employee extends Authenticatable
{
use Notifiable;
protected $primaryKey = 'employee_id';
public $incrementing = false;
public function branch(){
return $this->belongsTo('App\Branch');
}
public function orders(){
return $this->hasMany('App\Order');
}
}
class Branch extends Model
{
protected $primaryKey = 'branch_id';
public $incrementing = false;
public function employees(){
return $this->hasMany('App\Employee');
}
}
And these are the migrations of the above two models (up function only)
public function up()
{
Schema::create('branches', function (Blueprint $table) {
$table->string('branch_id')->unique();
$table->timestamps();
$table->primary('branch_id');
});
}
public function up()
{
Schema::create('employees', function (Blueprint $table) {
$table->string('employee_id')->unique();
$table->string('name');
$table->string('password');
$table->string('job');
$table->string('branch_id');
$table->foreign('branch_id')->references('branch_id')->on('branches')->onDelete('cascade');
$table->rememberToken();
$table->timestamps();
$table->primary('employee_id');
});
}
When I run php artisan tinker and test out the relationship, I get the following output:
>>> namespace App
>>> $emp = new Employee()
=> App\Employee {#778}
>>> $emp = $emp->find('CMB-EMP-001')
=> App\Employee {#787
employee_id: "CMB-EMP-001",
name: "FirstName LastName",
job: "Root",
branch_id: "CMB",
created_at: "2018-04-11 17:24:53",
updated_at: "2018-04-11 17:24:53",
}
>>> $emp->branch()->get()
=> Illuminate\Database\Eloquent\Collection {#775
all: [],
}
As you can see, it returns an empty array instead of the branch id of the employee. What have I done wrong?
EDIT:
>>> $emp->branch
=> null
You have to specify the foreign key:
class Employee extends Authenticatable
{
public function branch(){
return $this->belongsTo('App\Branch', 'branch_id');
}
}
And use $emp->branch instead of $emp->branch()->get().
Change your belongsTo() relationship
public function branch(){
return $this->belongsTo('App\Branch', 'branch_id', 'branch_id');
}
To build on Jonas's point, and to provide more clarity for future viewers:
The actual signature for defining a belongsTo relationship is
belongsTo(relatedEntity, foreignKey, ownerKey, relationModel)
At present, in your use of belongsTo, you're only defining which related entity you are defining a relationship with. What you need to do is provide details of the owner key (rather than the foreign key), so in your case:
return $this->belongsTo('App\Branch', 'branch_id', 'branch_id');
Why is this the case?
Laravel's default behaviour for determining which column to utilise is:
For the foreign key, take the related entity name and add the _id suffix. I.e. branch_id
For the owner key, default to using "id", since Laravel's convention is that a model's primary key should be called "id".
Given that in your migrations you've modified Laravel's default approach, by naming your primary key "branch_id" rather than just "id", you need to tell Laravel how to relate the two models.

Eloquent Multiple Foreign Keys from same table in two columns

I am having issues calling a departure ICAO and arrival ICAO from my schedules table. Laravel keeps giving me errors that my relationships are screwed up. Here is the code.
Schema::create('airports', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('city');
$table->string('country');
$table->string('iata');
$table->string('icao');
$table->double('lat');
$table->double('lon');
$table->longText('data')->nullable(); //JSON Data for All gate information for the system.
$table->softDeletes();
});
Schema::create('schedule_templates', function (Blueprint $table) {
$table->increments('id');
$table->string('code');
$table->string('flightnum');
$table->integer('depicao')->unsigned();
$table->foreign('depicao')->references('id')->on('airports')->onDelete('cascade');
$table->integer('arricao')->unsigned();
$table->foreign('arricao')->references('id')->on('airports')->onDelete('cascade');
$table->string('aircraft')->nullable();
$table->boolean('seasonal');
$table->date('startdate');
$table->date('enddate');
$table->time('deptime');
$table->time('arrtime');
$table->integer('type');
$table->boolean('enabled');
$table->text('defaults');
$table->timestamps();
$table->softDeletes();
});
Here are the Models
class ScheduleTemplate extends Model
{
public $table = "schedule_templates";
public function depicao()
{
return $this->hasOne('App\Models\Airport', 'depicao');
}
public function arricao()
{
return $this->hasOne('App\Models\Airport', 'arricao');
}
}
class Airport extends Model
{
//
public $timestamps = false;
public function schedules()
{
return $this->belongsToMany('App\ScheduleTemplate');
}
}
When I attempt to query using the following code, I get the error
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'vaos_airports.depicao' in 'where clause' (SQL: select * from vaos_airports where vaos_airports.depicao in (1))
$schedules = ScheduleTemplate::with('depicao')->with('arricao')->get();
The end goal is to pull the results into a table. Here is that code if interested.
#foreach($schedules as $s)
<tr>
<td>{{$s->code}}</td>
<td>{{$s->flightnum}}</td>
<td>{{$s->depicao()->name}}</td>
<td>{{$s->arricao()->name}}</td>
<td>{{$s->aircraft}}</td>
<td>{{$s->seasonal}}</td>
<td>{{$s->type}}</td>
</tr>
#endforeach
EDIT:
I fixed the relationship problem Apparently I had them swapped. Here are the updated Model classes
class ScheduleTemplate extends Model
{
public $table = "schedule_templates";
public function depicao()
{
return $this->belongsTo('App\Models\Airport', 'depicao');
}
public function arricao()
{
return $this->belongsTo('App\Models\Airport', 'arricao');
}
}
class Airport extends Model
{
//
public $timestamps = false;
public function schedules()
{
return $this->hasMany('App\ScheduleTemplate');
}
}
The error now lies in the view file. I will either get a BelongsTo error:
Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$name
or this if I have arricao or depicao without "()"
Trying to get property of non-object
The point is, that the second argument of a relationship should be the foreign key, and the second the local key.
From the docs:
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
So in your case, try this:
public function depicao()
{
return $this->hasOne('App\Models\Airport', 'id', 'depicao');
}
public function arricao()
{
return $this->hasOne('App\Models\Airport', 'id', 'arricao');
}
Update
The errors are thrown because you have the same column name for this relationship. In my opinion, two solutions:
Try to get the first object out of the relationship, like this. But note here: eager loading will not work!
<td>{{$s->depicao()->first()->name}}</td>
<td>{{$s->arricao()->first()->name}}</td>
Rename your relationships or the columns, so they don't overlap current column names. This is by far the best option.
For example, you could change the columns to depeciao_id and arricao_id, this also indicates that the columns are referenced to another table with corresponding ID, which is more descriptive.

One-To-One Eloquent Relationship functions

There is something I miss in the eloquent one-to-one relationship:
class MeetingTest extends Model
{
protected $table = 'meeting_tests';
public function meeting() {
return $this->belongsTo('App\Meeting','meeting_id','id');
}
public function observation() {
return $this->hasOne('App\Observation','meeting_test_id','id');
}
public function activity() {
return $this->hasOne('App\TestActivity','activity_id','id');
}
}
The Observation Class is
class Observation extends Model
{
protected $table = 'observations';
public function meetingTest() {
return $this->belongsTo('App\MeetingTest','meeting_test_id','id');
}
}
If I run php artisan tinker and
$mtn = App\MeetingTest::create();
$mtn->save();
$ob = App\Observation::create();
$ob->save;
$mtn->observation()->save($ob);
At this point inside the Observation record I can see the meeting_test_id filled with the correct id of the meetingTest, but if I try:
$mtn->observation
it gives me null; and in the Database there is no observation ID in the observation_id field;
this is the migration:
Schema::create('meeting_tests', function (Blueprint $table) {
$table->increments('id');
$table->integer('meeting_id')->unsigned();
$table->integer('observation_id')->unsigned()->nullable();
$table->integer('activity_id')->unsigned()->nullable();
$table->timestamps();
});
I don't understand what is not correct.
I can see observation_id and activity_id in your meeting_tests table, which makes records in this table the owned side of one-to-one/one-to-many relation. Therefore, both activity and observation relations in MeetingTest should return $this->belongsTo instead of $this->hasOne

foreign key not recognised in laravel 4.2

According to Dayle Rees
All foreign key columns follow a similar naming convention. The singular form of the related model appended with _id.
Consider this migration:
class CreateTables extends Migration {
// ...
public function up()
{
Schema::create('artists', function($table) {
$table->increments('id');
$table->string('name',64);
$table->timestamps();
});
Schema::create('albums', function($table) {
$table->increments('id');
$table->string('name',64);
$table->integer('artist_id')->unsigned();
$table->foreign('artist_id')->references('id')->on('artists');
$table->timestamps();
});
}
Here are my eloquent models:
<?php
// Artist model
class Artist extends Eloquent {
public function albums() {
return $this->hasMany('Album');
}
}
<?php
// Album model
class Album extends Eloquent {
public function artists() {
return $this->belongsTo('Artist');
}
}
I used them like this:
Route::get('/', function() {
$artist = new Artist;
$artist->name = "Morbid Angel";
$artist->save();
$album = new Album;
$album->name = "Altars of Madness";
$album->artists()->associate($artist);
$album->save();
return View::make('hello');
});
This does not seem to work, according to the logs:
[2015-06-09 06:01:12] production.ERROR: exception 'PDOException' with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'artists_id' in 'field list''
But I did not create a artists_id. What does this mean? Shouldn't laravel find artist_id because it should be singular followed by _id?
This was your problem. You have named your relation artists, but it should be artist. That's why it was looking for a column named artists_id.
You should define your relations as follow as it looks to me it is a One to Many.
In your Artists Model
public function albums()
{
return $this->hasMany('Album');
}
In your Albums Model
public function artist()
{
return $this->belongsTo('Artist');
}
Then try your code.
Route::get('/', function() {
$artist = new Artist;
$artist->name = "Morbid Angel";
$artist->save();
$album = new Album;
$album->name = "Altars of Madness";
$artist->albums()->save($album);
return View::make('hello');
});
In your artist model try return $this->hasMany('Album', 'artist_id');

Categories