Laravel Eloquent hasOne returns empty - php

I have two tables named 'works' and 'slides' as well as two classes that extend Eloquent named 'Work' and 'Slide'.
Inside my 'works' table I have a 'id' column, a 'title' column, a 'description' column and a 'image' column and inside my 'slides' table I have a composite key using a foreign key with two columns named 'id' and 'work_id'.
This is how my database relationship looks:
This is the code for my Slide class:
class Slide extends Eloquent {
public $timestamps = false;
public function workId() {
return $this->hasOne('work', 'work_id', 'id');
}
}
And this is the code for my Work class:
class Work extends Eloquent {
public $timestamps = false;
}
Inside my index page I am trying to get a Work object by calling the 'workId()' method inside my Slide object however it returns empty with this code:
$slides = Slide::all();
$works = new \Illuminate\Database\Eloquent\Collection;
foreach ($slides as $slide) {
$works->push($slide->workId());
}
printf($works);
However, if I replace the '$slide->workId()' call with:
Work::find($slide->work_id)
then it finds the row with no problem.
What should I do to get the function to return the Work object rather than calling Work::find()?

Slide belongs to Work because the foreign key to works is inside the slides table. You're also using the incorrect naming for the relationship function and incorrect syntax for the hasOne.
You need to use:
class Slide extends Eloquent {
public $timestamps = false;
public function work() {
return $this->belongsTo('Work');
//or return $this->belongsTo('Work', 'work_id', 'id');
}
}
To get the Work that belongs to a Slide: $slide->work
Note: you use "association()" for belongsTo, not "push()"

Related

Laravel 6 eager loading using with() on a belongsTo relationship is only *sometimes* returning null

I am working on a project where we have a model for a service provider, the type of care provided, and the status:
Provider:
class Provider extends Model
{
protected $table = 'providers';
public function status() {
return $this->belongsTo('App\Status');
}
public function caretype() {
return $this->belongsTo('App\CareType', 'id');
}
}
CareType:
class CareType extends Model
{
protected $table = 'type_of_care';
public function providers() {
return $this->hasMany('App\Providers', 'type_of_care_id');
}
public function category() {
return $this->belongsTo('App\CareCategory');
}
}
Status:
class Status extends Model
{
protected $table = 'status';
public function providers() {
return $this->hasMany('App\Providers');
}
}
On the my SearchController (the controller that processes search requests for providers), the show() function using eager loading retrieves the caretype perfectly. But on the search() function that lists the collection of search results, the caretype is always listed as null.
I don't understand why it would be working in one function but not the other, especially when the code to eager load is exactly the same in both functions:
public function search(Request $request)
{
$validated = $request->validate([
//I removed the validation code for this post
]);
$providers = Provider::with(['status', 'caretype'])->get();
return view('search.results', ['providers' => $providers]);
}
public function show($id)
{
$single_provider = Provider::with(['status', 'caretype'])->where('id', $id)->first();
return view('search.details', ['provider' => $single_provider]);
}
Any help in this would be appreciated. I know that the model and relationship foreign keys are properly defined because the show() function is able to get the caretype just fine.
nope. your relationship and foreign keys are not correct. as from the doc
Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with a _ followed by the name of the primary key column. However, if the foreign key on the Child model is not like that, you may pass a custom key name as the second argument to the belongsTo method.
you are passing the id column as the foreign key in Provider model's caretype ralation but your foreign key is type_of_care_id. so you are getting some results when the id matches but if not, you are getting null. change your relationship code to
public function caretype()
{
return $this->belongsTo('App\CareType', 'type_of_care_id');
}
now again from the doc
If your parent model does not use id as its primary key, or you wish to join the child model to a different column, you may pass a third argument to the belongsTo method specifying your parent table's custom key.
in your case id is the primary key. so you don't have to pass the third parameter. just update the primary key reference and everything will work perfectly.

How to get only one note from relation belongsToMany?

I just have a table that has relation belongsToMany, BUT it was a mistake by developer so I can not change this structure SO I need to get only first(). However, when I take only first it return empty array but I need in object
$animals = Cat::query()->with(['types' => function($query) {
$query->first(); //wrong
}])
So how I can get only first? Because I need to order by this field and I can't because it is array
you can do this in two ways:
1- using hasOne relation:
class Cat {
public function firstType() {
return $this->hasOne(Type::class, 'type_id', 'id')->latest();
}
}
2- using staudenmeir/eloquent-eager-limit
after installing it you can write:
class Cat extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
public function firstType() {
return $this->hasMany(Type::class, 'type_id', 'id')->latest()->limit(1);
}
}
class Type extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
// ......
}
the advantage of HasEagerLimit trait is that you can limit the result not only to one but any number you want ...
now you can write:
$animals = Cat::query()->with('firstType');
You can add a attribute getter and set up into appends attribute. follow bellow example:
class Cat {
protected $appends = ['type'];
public function getTypeAttribute() {
// return the first element from your array of the belongsToMany relationship if it exists
return isset($this->types[0])? $this->types[0] : null;
}
}
That's important to remember this method will bring just one type. If you want to get the same type everytime, you create a diferente table where the cat table has the type_id column.
obs: Sorry for my english, it's still in working progress.

How to retrieve all data from three tables according to groupby of second table's field value using Laravel eloquent query?

I have three models with some methods like
1.Employee Model
class Employee extends Model
{
protected $fillable = [
'employee_no','card_no','inactivedate', 'activedate', 'status',
];
public function office(){
return $this->hasOne(EmployeeOffice::class);
}
public function section(){
return $this->belongsTo('App\Hrm\Section');
}
}
2.EmployeeOffice Model
class EmployeeOffice extends Model
{
$fillable = ['employee_id','section_id','line_id','join_date','gross','confirm_date'];
public function employee(){
return $this->belongsTo(Employee::class);
}
public function section(){
return $this->belongsTo('App\Hrm\Section');
}
}
3.Section model....
class Section extends Model
{
protected $fillable = ['name','description','status'];
//
}
i need all inactive employee information according to the employee inactive date(from employee model) as well as their all office information from EmployeeOffice model and must be groupBy according to section_id which is (section_id as foreign key) available in EmployeeOffice model.
For that i have to go with some condition like ..
Employee::where('inactivedate','like','%'.$date.'%');
*And need all data from office and employee table
*need section name and grouped by as section name from section model
***please suggest me how can i solve this problem ***
Try this:
$data = Section::with(
array(
'employeeOffice' => function(
$query->with(
'employees' => function(
$query->where('employees.inactivatedate', 'like', '%'.$date.'%'
)
)
)
)
)
->get();
This should give you an array to every section_id. In this array are the employeeOffices (1:n-Relationship). The second query with with will fetch for each employeeOffice the employee who sits in it.
But if you defined the relationships right, this should do the trick to:
Section::with('EmployeeOffice.Employee')->get();
Nested Eager Loading
I have solved my problem by this...
if(Input::has('start') && Input::has('end')){
$start = Carbon::parse(Input::get('start'))->startOfDay();
$end = Carbon::parse(Input::get('end'))->endOfDay();
$start = $start->format('Y-m-d');
$end = $end->format('Y-m-d');
EmployeeOffice::query()->whereHas('employee',function ($query) use ($start,$end){
$query->whereBetween('inactivedate',[$start, $end])->where('status',0);
})->paginate()->groupBy('section_id');
}

Laravel 5 – get particular many to many relation based on model and related model ID

I've got Tag and Attendee Eloquent models, they are in many-to-many relation. Pivot table has also two more attributes – value_int and value_string. My Attendee model looks like this:
class Attendee extends Model
{
public $timestamps = false;
protected $fillable = [
'event_id'
];
public function tags() {
return $this->belongsToMany('App\Models\Tag', 'attendee_tag', 'attendee_id', 'tag_id')
->withPivot(['value_string', 'value_int']);
}
public function scoreTagValue($tag_id) {
return $this->tags->where('tag_id', '=', $tag_id)->first();
}
}
What I want is to obtain pivot values based on Attendee model and variable tag_id, so I've written scoreTagValue function, but it always returns null and I don't know why :( I'm calling it this way:
$attendee->scoreTagValue($tag_id). Thanks for your help :)
You need to access the relation, not the property:
public function scoreTagValue($tag_id) {
return $this->tags()->where('tag_id', '=', $tag_id)->first();
}
Also, according to the docs, withPivot() does not take an array, so:
->withPivot('value_string', 'value_int');

hasMany returns null

I'm on laravel 4.2, trying to get an objects associative relation yet for some reason I am getting null.
Models:
class Keg extends Eloquent {
protected $fillable = ['beer_distribution_id', 'status', 'keg_size'];
public function beer_distribution()
{
return $this->belongsTo('BeerDistribution');
}
}
class BeerDistribution extends Eloquent {
protected $fillable = ['beer_id', 'distributor_id'];
public function kegs()
{
return $this->hasMany('Keg');
}
}
My Query:
$distirbution = Keg::find($tap->keg_id)->beer_distribution
This query returns null: I know the keg object is found and I know that the object has the beer_distribution_id.
I tried specifying the foreign key in the model like so:
class Keg extends Eloquent {
protected $fillable = ['beer_distribution_id', 'status', 'keg_size'];
public function beer_distribution()
{
return $this->belongsTo('BeerDistribution', 'beer_distribution_id');
}
}
I thought that might be necessary since the Model is camel case.
I know this is super simple, and I am in fact querying many relations succesfully through out my application, but for some reason this one is not working. Any thoughts on what I might be missing?
The problem is the function name of the relationship. Laravel expects it to be in camel case: beerDistribution().
Change that and you should be good. (You don't have to specify the foreign key, Laravel will convert camelCase to snake_case)

Categories