BelongsTo return class - php

When I use belongsTo without default keys it won't connect..
My users table has user_id which is some rand and unique string that presents that user. My urls table has user_id and uri columns where user_id contains users table user_id.
In Url model I have:
public function user() {
return $this->belongsTo('App\User','user_id','user_id');
}
In User model I have:
public function uri() {
return $this->hasOne('App\Url', 'user_id', 'user_id')->first()->uri;
}
By using $user->uri() I get uri from urls table connected with user_id.
But when I use $url->user() I get return null or BelongsTo class inside laravel tinker.
Anyone know why?

Your User::uri() method is not a relationship method.
You are utilizing a relationship method inside of it, but you are querying it for the first result and returning the uri property.
Your Url::user() method IS a relationship method because you are actually returning a relationship (BelongsTo) instance. Eloquent relationships are used as follows:
// To get a related entity on a BelongsTo relationship, you access it as a property:
$url->user
// To query a relationship, you use it as a method:
$url->user()->where(...)->first();

Related

call relation in Pivot model

I try load relations like:
return $task->load('users', 'creator', 'attachments', 'messages.creator');
Relation 'users' many to many with some fields
user
id
name
...
task
id
name
...
task_user
user_id
task_id
task_status_id
my pivot model
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class TaskUser extends Pivot
{
public $incrementing = true;
public function status()
{
return $this->hasOne(TaskStatus::class);
}
}
How to correctly load 'status' relation?
If Laravel provided a way to pass Closures in pivots it wouldn't be hard at all however there are 2 solutions at the moment to load pivot relationships
1. Lazy eager load everything.
# App\Task.php
public function users()
{
return $this->belongsToMany(App\User::class)->using(App\TaskUser::class)->withPivot('task_status_id');
}
$task->load('users', ...);
$task->users->each(function ($user) {
$user->pivot->load('status');
});
The problem: This makes a query for each User related to Task. Unless you paginate your results, it's the classic N+1 problem.
2. Use hasMany and belongsTo instead.
Define $user->tasks_user relationship (User hasMany TaskUser)
Define $task->tasks_user relationship (Task hasMany TaskUser)
Define the inverse (TaskUser belongsTo User, TaskUser belongsTo Task)
Define the last task_user relationship (TaskUser hasOne TaskStatus) (looks like a belongsTo to me though)
Load relationships $task->load('task_user.user', 'task_user.status')
There's no real problem with this implementation besides not using belongsToMany.

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.

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

Trying to aggregate column values in eloquent

I have model called Organisation, which has a many to one relationship with a model called Client, it looks like this,
public function clients() {
return $this->hasMany('Client', 'owner_id')->orderBy('name', 'asc');
}
Client has a one to many relationship with projects that looks like this,
public function projects()
{
return $this->hasMany('Project');
}
The project model / table as a column called total_cost within an organisation I can gets it's clients, and then the clients projects, what I wanting to do is get the value of the client by aggregating all the clients projects total_cost entries, I am trying to do this with the following,
public function clientsValue() {
return $this->clients()->projects()->select(DB::raw("SUM(total_cost) as client_value"));
}
In my mind this getting the projects through the clients relationship and then running a select on the project model, however I am getting the following error,
Call to undefined method Illuminate\Database\Query\Builder::projects()
But I am not sure why as the clients has a projects relationship.
$this->clients() returns relation definition - object of class HasMany, not a Client object. HasMany class does not have a projects() method, that's why you're getting an error.
In order to calculate total clients value, you first need to define additional relation between organization and projects:
public function projects() {
return $this->hasManyThrough('Project', 'Client');
}
This will tell Eloquent how to fetch projects for given organization using intermediate Client model.
Once you have the relation you can call aggregate functions on it:
public function clientsValue() {
return $this->projects()->sum('total_cost');
}
You can read more about aggregate functions here: http://laravel.com/docs/5.1/queries#aggregates
You can read more about hasManyThrough relations here: http://laravel.com/docs/5.1/eloquent-relationships#has-many-through

Laravel 4 hasOne / belongsTo relationship

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

Categories