Laravel 4 hasOne / belongsTo relationship - php

Get the feeling I'm being particularly dumb here but it's doing my nut in.
I have a candidate table with the country_id field as a foreign key to the countries table. A candidate has one linked country.
The Candidate model has a relationship defined as:
public function country()
{
return $this->belongsTo('App\Models\Country', 'country_id');
}
And the Country model has the following:
public function candidate()
{
return $this->hasMany('App\Models\Candidate');
}
On my listing page I'm using Candidate::with('country')->paginate(5) to provide a list of the Candidates on screen. When I come to display the country I use:
$candidate->country->country
But this returns the error:
Trying to get property of non-object
I can, however, use
$candidate->country['country']
Using var_dump on $candidate->country suggests that an object is returned, so why can't I access it as an object?
EDIT:
The candidates controller is namespaced to admin as follows:
namespace App\Controllers\Admin;
and as part of the declarations in the controller I have:
use App\Models\Candidate, App\Models\Manufacturer, App\Models\Make, App\Models\Country;
Each model is namespaced with
namespace App\Models
Have I even got the relationship set up correctly?
Thanks

Related

How to get foreign key's method used in Laravel Eloquent Relationships?

I have a problem with how to get the method name that was used in other models.
There is a list of models and some of them have used different method name on its relationship to other models.
For example, I have a model name of Member Rate Detail wherein it belongs to Member Rate model. The method that connects from Member Rate Detail to Member Rate is head() method.
Here is the sample code for head() method:
public function head()
{
return $this->belongsTo(MemberRate::class, 'member_rate_head_id')->withTrashed();
}
And for Customer Detail model it belongs to Customer model. And the connector method name that was used is group()
Here is the sample code for group():
public function group()
{
return $this->belongsTo(Customer::class, 'head_id', 'id')->withTrashed();
}
So the problem is I don't know if this model is using head() or group() or another method name.
Is there a Laravel Relationship concept way which can get a list or an array type of its foreign key's method used?
I'm expected to get the method name so that I can direct it to its instance class.
For example:
$memberRateDetail->getForeignMethod()->created_by;
**OR**
$customerDetail->getForeignMethod()->created_by;
Thank you so much!!!
No, there are not unless you declare them yourself.
Let's say you declare a method in your all your models where you declare the method for the class foreign relation. You can also implement it as an interface.
You can also just use code hinting if you have a good IDE, declaring a relation in PHP docs as * #property Collection head can help too.

Eloquent relation collection not returning by property accessor but does if I use relation()->get();

I'm having an issue with eloquent whereby when I call $unit->assets I am receiving an empty collection. But if I call $unit->assets()->get() - I receive a collection with the correct results.
According to the documentation my relations are defined correctly, which also seems apparent given that I get correct results when calling get() on the relationship object.
class Unit extends Model
{
protected $table = 'organisation_units';
public function assets()
{
return $this->hasMany(MediaElement::class, 'owner_id');
}
}
class MediaElement extends Model
{
protected $table = 'template_elements';
public function owner()
{
return $this->belongsTo(Unit::class, 'owner_id');
}
}
Table structure is
organisation_units
id | name
template_elements
id | owner_id | name | filename
Turns out the issue was the fact that I use "assets" as the relation method name. "assets" must be a reserved or already used keyword within models or something. Will update the post when I find out exactly why.
Also had the same issue with the method names "colors" and "templates".
The real issue here, was that I was storing my organisation unit in the session and when retrieving that from the session, the relations were already loaded.
Calling $model->fresh() before saving to the session sorted out the issue.
Thanks to those who attempted to help.

Laravel - belongsTo relationship in custom pivot model not working

Edit:
I dont think its the same issue as:
https://stackoverflow.com/questions/40022929/laravel-relationship-error-undefined-property-illuminate-database-eloquent-col
because in that issue hasMany relationship is used which returns an array but i used belongsTo which should return a certain object.
I have a database structure where i have a many to many relationship between users and companies table. For that i have a crossreference table company_user. Also each user has a certain role in a company so the crossreference table also has a role_id. The problem is that for some reason i get an exception when i try retrieve the role from the crossreference table.
Here is how i defined the relationship in Company model:
public function users() {
return $this->belongsToMany('App\User')->withPivot('role_id')->using('App\CompanyUser');
}
Now if i just try to get role_id from pivot everything works fine:
#foreach($company->users as $user)
{{$user->pivot->role_id}} // this displays correct role_id
#endforeach
But i also need the data of the role so i defined a relationship in my custom pivot. Here is the whole model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class CompanyUser extends Pivot
{
public function role()
{
return $this->belongsTo('App\Role');
}
}
And i tried to access it like this:
#foreach($company->users as $user)
{{$user->pivot->role()->id}}
#endforeach
But this gives me an exception:
Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$id
What am I missing?
try changing to
#foreach($company->users as $user)
{{$user->pivot->role->id}}
#endforeach
The exception itself gives you your answer.
Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$id
It's telling you you're trying to access the $id property on the belongs to builder instance and not the actual related model.
The difference is small but is worth understanding as it will make your laravel life much happier.
Access the relation builder: $user->role()
This will directly call the role() method and return exactly what you see in your definition. Accessing this method is handy for aggregate functions - things like getting the count of related records for HasMany or BelongsToMany relations. eg: $user->role()->count().
Access the related record: $user->role
This will actually retrieve the related record from the database and hydrate it for you, thus giving you the power of your related eloquent model and access to it's columns as properties. :D
You can see why/how this works by diving into Laravel's source and checking out the Illuminate\Database\Eloquent\Model class. Specifically the getAttribute() method.

Trouble understanding laravel eloquent models

It's been a some time since I've programmed with Laravel and I'm stumped by the relations I need in order to create a foreign key -link with 2 models.
I have a database where there's a table "company" containing companies, and I also have a table called "projects", which contains projects.
So the Projects- table contains a column called "employercompany" with a foreign key constraint to the company-table.
I'm trying to print out the company's name in a project page in laravel with
{{$project->employercompany->name}}
But keep getting "Trying to get property of non-object"
My model pages look like this:
//Company
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Company extends Model
{
public function projects()
{
return $this->hasMany('App\Projects', 'employercompany', 'id');
}
}
and
// Projects
namespace App;
use Illuminate\Database\Eloquent\Model;
class Projects extends Model
{
public function employercompany()
{
return $this->belongsTo('App\Company');
}
}
I know this is an easy problem but I just can't wrap my head around it
*****EDIT*****
I found the solution. Thanks Radical for providing some insight.
I ended up changing the employercompany column to company_id and, all the others as such too.
After that I fiddled around what I'm guessing fixed the thing was that I changed my database search query from
DB::table('projects')->get();
into
Project::all();
Don't know if that was the change needed but it sure feels like it was.
When defining a belongsTo relation like you have done, Laravel will try and 'guess' the keys you are using based on the class name. In this case, it will look for a column company_id on your Projects model since your model is called Company.
Like you have done for the projects() method on your Company model, you should tell Laravel that you are using the employercompany column to reference the Company model:
public function employercompany()
{
return $this->belongsTo('App\Company', 'employercompany');
}
For more information, see the relevant documentation here.
In addition, to make things easier, it might be worthwhile to try - if possible - to adhere to what Laravel 'expects' your database columns to be called, so situations like this are resolved automatically.
It should be like
$project = Project::find($id); //id of project
$compnany_name = ($project->employercompany()->get())->name;

Call to undefined method Illuminate\Database\Query\Builder::vehicles()

I have two models.
A "Vehicle" and a "Tenant".
They have following relationships with each other.
A Tenant hasMany vehicles. A vehicle belongsTo a single Tenant.
For Tenant.php:
public function vehicles()
{
return $this->hasMany('\App\Models\Vehicle');
}
For Vehicle.php:
public function tenant()
{
return $this->belongsTo('\App\Models\Tenant');
}
Executing this :
$this->user = $request->user();
$userTenant = $this->user->tenant();
$vehicle= $userTenant->vehicles()->first();
results in an error
Call to undefined method Illuminate\Database\Query\Builder::vehicles()
Pointing to this line :
$vehicle= $userTenant->vehicles()->first();
I am not so sure why is this happening =\
I can't see from your post what the relations are with a User, but the tenant() (with parentheses) probably returns a BelongsTo or other Relation instance that is being assigned to $userTenant. Try changing that line to a version without parentheses after tenant to get the Tenant Model instance instead:
$userTenant = $this->user->tenant;
Update from comments
when you call a relation as method, e.g.
$myModel->relation()
you get the corresponding relation class. When used as a getter, e.g.
$myModel->relation
it's essentially the same thing as calling
$myModel->relation()->get() for relations that target multiple models, or calling
$myModel->relation()->first() for relations that target a single model.
Checkout the docs for more info on relationship methods vs. dynamic properties

Categories