Retrieve custom fields from child of a child model in Laravel eloquent - laravel

I'm trying to retrieve custom fields from a model using the with() statement in Laravel. When I just get all fields the child object comes ok, but when I try to retrieve just some fields of this child abject it returns to me the following error:
Integrity constraint violation: 1052 Column 'id' in field list is ambiguous
below I'll show how I'm doing these queries.
When I execute the following query it works:
$cfps = CallForPaper::select('id', 'speech_id')->with([
'speech:id,title,description',
'speech.speakers'
])->get();
But when I execute the code below it returns the error which I have mentioned above.
$cfps = CallForPaper::select('id', 'speech_id')->with([
'speech:id,title,description',
'speech.speakers:id,name,email'
])->get();
Note: than only modification in this code is the line: 'speech.speakers:id,name,email'
in my model Speech, the speakers relationship is the following:
public function speakers()
{
return $this->belongsToMany(Speaker::class, 'speech_speaker');
}

You will need to define the table_name for the id's your are selecting:
$cfps = CallForPaper::select('id', 'speech_id')->with([
'speech:TABLE_NAME.id,title,description',
'speech.speakers:TABLE_NAME.id,name,email'
])->get();
you can also do the following, ie. rename the id:
$cfps = CallForPaper::select('id', 'speech_id')->with([
'speech:TABLE_NAME.id as speechID,title,description',
'speech.speakers:TABLE_NAME.id as speakerID,name,email'
])->get();

Related

How to know what columns are presents in a Eloquent query before to execute it in Laravel 5.5?

Im using Laravel 5.5 and I have and QueryBuilder object (from the "Illuminate/Database/Eloquent/Builder" class).
I want to set an orderBy sentence into my query, but only if this field is present and exists in the QueryBuilder object (as column in the select section sentence).
For example, there is an User model, with the following fields ['id', 'firtsname', 'lastname', 'username','description'].
This is my object:
Use App\User;
$query = User::query();
if ($request->input('sort') != null) {
$model_query->orderBy($request->input('sort'), 'ASC');
}
$users = $query->get();
When I execute it, works fine (if I send you consistent data, of course). But if I set a column what does not exists, it sends and exception. So, the question is, how I can get the columns to retrieve from my $query object? To validate it, and if it's presents, execute the ordening code.
To answer your question, you can get the presence status of a column using Schema::hasColumn()
if (Schema::hasColumn('users', $request->sort)) {
//
}
GOING FURTHER
Now this doesn't seem very efficient, and maybe potentially leak data. Better validating your sort input and accept only proper column names:
$request->validate(['sort' => 'in:column1,column2']);

Why does groupBy() work but Count() does not in laravel eloquent model function?

I need to get counts of all the records based on belongsToMany relationship. normally I can use groupBy() in a function inside the model. but if I use count() or withCount() inside a model function, i get the error as followed:
function code:
public function TaskCount(){
return $this->belongsToMany(User::class)->count();
}
Error message:
Symfony\Component\Debug\Exception\FatalThrowableError: Call to a member function addEagerConstraints() on int in file /Users/dragonar/Dev/iyw/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php on line 560
If I do the following...
public function TaskCount(){
return $this->belongsToMany(User::class)->Count();
}
//expected record is 4(int)
//output is 4(array) user records.
...it gives me data but like 4 records of the user instead of a number 4. The user data is useless. The only thing needed is totalCount for those records.
Relationship methods have to return Relation type objects. You are returning the result of a query, count() returns a number not the Relation object / Builder. Remove the count from that statement you are returning. Renamed the relationship tasks here.
public function tasks()
{
return $this->belongsToMany(User::class);
// this returns a Relation type object a BelongsToMany object
}
Where you need to use that relationship you can then use count:
$something->tasks()->count();
Or you can load the count of the relationship using loadCount:
$something->loadCount('tasks');
$something->tasks_count;
Or via eager loading for a collection:
$results = Something::withCount('tasks')->get();
foreach ($results as $model) {
echo $model->tasks_count;
}
If you really wanted to you could create an accessor to get the count as well, you just may want to avoid the N+1 issue by preloading the relationship and using the dynamic property to access it in the accessor.
These relation objects are Builders. When you called groupBy on it previously that is returning the Builder, it isn't executing the query. You can add where conditions and order by statements because they are just building the query, not executing it, they return the builder you are calling the method on.
Laravel 6.x Docs - Eloquent - Relationships - Counting Related Models withCount loadCount
Why not use: Task::all()->count(); ?
you can use the withCount method while calling relation like this
User::withCount('images')->get();
You can add get the data and just count it.
public function TaskCount(){
return $this->belongsToMany(User::class)->get()->count();
}
You can call it like
$taskCount = $task->TaskCount();

LARAVEL hasManyThrough still using the ID as foreign key

Hi trying to get the rest day of a country. But I am getting error.
Basically here is the structure
Employee
has SITE,
Site
has REGION,
Region
has REST DAY
I have declared this on my Employee Model
public function restdays()
{
return $this->hasManyThrough('App\ref_restdays', 'App\ref_gacomsit', 'region', 'region');
}
But I get this error
[Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Conversion failed when converting the varchar value 'RUAE' to data type int. (SQL: select [ref_restdays].*, [ref_gacomsit].[region] from [ref_restdays] inner join [ref_gacomsit] on [ref_gacomsit].[id] = [ref_restdays].[region] where [ref_gacomsit].[region] in (855))
Apparently it using still the ID of my site masterfile where as I have declared to use the REGION foreign key.
Can anyone explain where is my mistake is? Appreciate for your help.
Turns out I don't need to use hasManyThrough. I've just declared hasMany on my site masterfile like so:
public function restdays()
{
return $this->hasMany( 'App\ref_restdays', 'region', 'region');
}
then I just use the nested eager loading on my query using dot syntax.
here is my final query, on the last line I just reference site.restdays to get the list of restdays.
$employees = hr_employee::select(
'hr_employee.id',
'empno',
'first_name',
'family_name',
'empstatus',
'empstatus_eff_date',
'contcatg_code',
'post_title_code',
'cs',
'group_initial_joined',
'returned_date',
'mcat2',
'othours1',
'othours2',
'othours3'
)
->where([
['empno','=',$empno]
])
->with(['catg', 'post', 'site.restdays'])
->get();

laravel relations error Trying to get property of non-object

I'm trying to retrieve data from two tables and in order using a hasMany relationship. i.e
Public childModel (){
return $this->hasMany(childModel);
}
In the view when I run the foreach loop:
foreach($parentModel as $parentModel)
or
foreach($parentModel->childModel as $childModel)
then
{{parentModel->childModel}}
I get json printed on my screen just fine (including the column I want to output.)
When I try
`{{parentModel->childModel->column}}`
I get "Trying to get property of non-object"
Figured it out. I was making a 'where' statments when i initialized the parentModel variable, that 'where' statement rejected the table in the childModel. Only found out after running tests.

Laravel 5 eager loading, select column from eloquent relationship

I am trying to
1. select `DOS`,`name`,`fin`,`ins_type` from events table.
2. site_name from sites table
3. client_name from clients table
but unable to access site_name, client_name column in select statement
->select('DOS','name','fin','ins_type')
How to add these columns site.site_name, client.client_name in above select statement.
Eloquent query is
$events = Event::with([
'site'=>function($q){
$q->select('site_id','site_name','client_id');
},
'site.client'=>function($q2){
$q2->select('client_id','client_name');
}])
->select('DOS','name','fin','ins_type')
->get();
How about this?
$events = Event::with([
'site'=>function($q){
$q->with(['client'=>function($qq){
$qq->select('client_id','client_name');
}])->select('site_id','site_name','client_id');
}])
->select('DOS','name','fin','ins_type')
->get();
I found a simple solution from the comment section in here. It is possible to put the column selection in the model. So in your case, your Event model could be something like this.
public function site()
{
return $this->belongsTo('App\Site')->select('id', 'name', 'client_id');
}
Then, in your controller you simply call the function.
$events = Event::with('site')->get();
I haven't tried how this goes with the nested eager loading though.
I myself got a little problem with these also until i discover that you need to add the foreign key to the select statement inside the "with" closure.
the column that relates "client" to "site" and "site" to "Event"

Resources