Laravel 5 Eloquent hasMany relationship putting null into key field - laravel

I have an Artist model and an Item model.
class Artist extends Model {
protected $table = 'contactsdata';
protected $primaryKey = 'c_id';
public function artworks() {
return $this->hasMany('App\Item', 'c_id', 'c_id');
}
}
class Item extends Model {
protected $table = 'stock';
protected $primaryKey = 's_id';
}
In my ArtistsController I have this code:
public function show($id)
{
DB::enableQueryLog();
$artist = Artist::find($id);
$artworks = Artist::find($id)->artworks;
dd(DB::getQueryLog(), $artworks->toArray());
}
In the database there are many records qualifying to populate $artworks. But this is my dd() output:
array:2 [▼
0 => array:3 [▼
"query" => "select * from `contactsdata` where `contactsdata`.`c_id` = ? limit 1"
"bindings" => array:1 [▼
0 => "2242"
]
"time" => 2.59
]
1 => array:3 [▼
"query" => "select * from `stock` where `stock`.`c_id` is null"
"bindings" => []
"time" => 2.52
]
]
[]
For some reason the if field (c_id) is set to null for the second or relationship query. Any ideas? Help!

To achieve what you want, you should rather use here:
$artist = Artist::find($id);
$artworks = $artist->artworks;
instead of:
$artist = Artist::find($id);
$artworks = Artist::find($id)->artworks;

Thanks all. I have solved this myself. Eloquent relationship field names are case sensitive. For some reason my database table has all its fields (in its scheme) named in UPPER CASE. Once I changed the hasMany parameters to 'C_ID', 'C_ID' everything worked just fine.
So worth knowing that Eloquent relationship field names are CASE SENSITIVE.

Related

My array has only one item from pivot table

With this code :
$evenements = Year::with(['evenements' => function($query) {
return $query->orderBy('mnemonique');
}])
->orderBy('id')
->get();
I get that:
5 => array:7 [▼
"id" => 62
"name" => "Congé"
"mnemonique" => "Congé"
"color" => "#bcbcbc"
"created_at" => "2021-07-13T14:16:04.000000Z"
"updated_at" => null
"pivot" => array:2 [▼
"year_id" => 1
"evenement_id" => 62
The problem is that pivot should have 10 items and not only 2 because the event 62 is in 5 years
This is the models code:
Events model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Evenement extends Model
{
protected $fillable = ['name','mnemonique','color'];
//DD 18/07/21 Une année peut avoir plusieurs events
public function years()
{
return $this->belongsToMany(Year::class, 'evenement_year', 'evenement_id', 'year_id');
}
}
Year model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Year extends Model
{
protected $fillable = ['name'];
public function evenements()
{
return $this->belongsToMany(Evenement::class, 'evenement_year', 'year_id', 'evenement_id');
}
}
This is the content of $query :
Illuminate\Database\Eloquent\Relations\BelongsToMany {#260 ▼
#table: "evenement_year"
#foreignPivotKey: "year_id"
#relatedPivotKey: "evenement_id"
#parentKey: "id"
#relatedKey: "id"
#relationName: "evenements"
#pivotColumns: []
#pivotWheres: []
#pivotWhereIns: []
#pivotWhereNulls: []
#pivotValues: []
+withTimestamps: false
#pivotCreatedAt: null
#pivotUpdatedAt: null
#using: null
#accessor: "pivot"
#query: Illuminate\Database\Eloquent\Builder {#1478 ▶}
#parent: App\Year {#1474 ▶}
#related: App\Evenement {#1475 ▶}
}
I don't know how to feed pivot array ? Do you have any idea ?
Thank you in advance.
You must specify extra columns in your relationship using withPivot; since I do not know your column names (cropped in image), I will just give an example:
class Year extends Model
{
protected $fillable = ['name'];
public function evenements()
{
return $this->belongsToMany(Evenement::class, 'evenement_year', 'year_id', 'evenement_id')
->withPivot(["someField1", "someFiled2"]);
}
}

Laravel - Select relation columns

I am trying to write a query which selects columns from a model then selects one column from a relationship table.
Team Model
public function members(){
return $this->hasManyThrough('App\User', 'App\Membership', 'team_id', 'id', 'id', 'user_id');
}
Member(user) model
public function skills()
{
return $this->belongsToMany('App\Skill');
}
Function
Query i have attempted but had no luck:
$members = $this->team->members()
->select('id', 'name')
->with(['skills' => function ($query) {
$query->select('name');
}])
->get();
dump of query
When i dump the query it returns just the data for the id and name columns from the team table but the skills relation returns back empty when i want it to return the name from that table.
#relations: array:1 [▼
"skills" => Illuminate\Database\Eloquent\Collection {#1657 ▼
#items: []
}
]
How would do i grab the name column from the skills relation table within this query?
To select column in relation you can use this :
->with('members.skills:id,name')
If you're not passing id attribute inside the with, the relation can't work
You need to add the id to the fields returned from the skills table. Otherwise Eloquent has no way to link the skill to the correct team.
->with(['skills' => function ($query) {
$query->select('id', 'name');
}])

How to change result of laravel relationship

I have an one to one relationship in laravel same as following:
public function Category()
{
return $this->belongsTo(Categories::class);
}
and run this eloquent query:
Product::with('category')->first();
this query return:
{
"name": "Green Book",
"category": {
"id": 1,
"name": "Book"
}
}
but I went this data:
{
"name": "Green Book",
"category": "Book"
}
Is it possible to do this without using a loop?
First of all it seems like you have a 1-X relationship which you are mistakenly using as a many to one. Your belongsTo should be hasOne since the your items have one category not the other way around.
You can use the $appends property to append a custom field and make it behave as though it's part of your model:
Rename your relationship and add a mutator and accessor:
public function categoryRelationship()
{
return $this->hasOne(Categories::class);
}
public function getCategoryAttribute() {
return $this->categoryRelationship->name;
}
public function setCategoryAttribute($value) {
$this->categoryRelationship->name = $value;
}
You can also choose to add an event to automatically save your relationship when the model is being saved to ensure it works transparently:
protected static function booted()
{
static::saving(function ($myModel) {
$myModel->categoryRelationship->save();
});
}
}
Finally you add the $appends property to ensure your new attribute is alwasy included in the model as though it's a native one.
protected $appends = [ 'category' ];
// This is so you don't end up also showing the relationship
protected $hidden = [ 'categoryRelationship' ];
You can use leftJoin
return \App\Product::leftJoin('categories', 'products.category_id', '=', 'categories.id')
->select('products.*', 'categories.title as category')->get();
According to Laravel Doc Eager Loading Specific Columns
You may use the following
Product::with('category:id,name')->first();
Or you may do it yourself :
$product = Product::with('category')->first();
$product->category = $product->category->name;
I get same result
so, i tried but didn't get right result.
how to change the result of laravel eloquent relation.
I found one way and used transformer.
we can change the result in transformer.
$result = Event::with(['eventType'])
->where('id', $id)
->where('user_id', auth()->user()->id)
->first();
return $this->trans->transform($result);
this is the result and i used transformer as follow.
public function transform(Event $Event)
{
return [
'id' => $Event->id,
'company_id' => $Event->company_id,
'calendar_id' => $Event->calendar_id,
'case_id' => $Event->case_id,
'user_id' => $Event->user_id,
'title' => $Event->title,
'description' => $Event->description,
'duration' => $Event->duration,
'alert_at' => $Event->alert_at,
'alert_email' => $Event->alert_email,
'email_sent' => $Event->email_sent,
'alert_popup' => $Event->alert_popup,
'popup_triggered' => $Event->popup_triggered,
'created_by' => $Event->created_by,
'completed' => $Event->completed,
'alert_offset' => $Event->alert_offset,
'icon' => $Event->icon,
'color' => $Event->color,
'snoozed' => $Event->snoozed,
'type_id' => $Event->type_id,
'datetime' => $Event->at,
'endtime' => $Event->end_time,
'event_type_name'=>$Event->eventType->name,
];
}
then, we can get right result. Focuse on 'event_type_name'=>$Event->eventType->name,
But i have one problem yet.
now, the result is only 1 row. it is just first().
but if i use get(), i can't use transformer.
of course, i can loop the result using foreach().
but i think it is not right way.
what is better way?
Please answer.

How do I exclude an eager loaded query in Polymorphic Relations?

Lets say this is my table structure:
posts
id - integer
title - string
body - text
reviewed - boolean
videos
id - integer
title - string
url - string
profileContent
id - integer
user_id - integer
content_id - integer
content_type - string
Now I want to receive the contents of the user's profile:
$user->profileContents()
->latest()
->with(['content' => function ($query){
//I'm not sure how to do it
}])
->paginate(5);
How do I say that IF the column "reviewed" exists it should be true? But it does not matter if videos are reviewed or not.
Additional Informations:
profileContents() gives me all the contents of a user profile
public function profileContents()
{
return $this->hasManyThrough(ProfileContent::class, Profile::class);
}
and with('content') uses to morph to the specific models:
public function content()
{
return $this->morphTo();
}
Edit 1:
I'm a bit nearer to my goal. I used a GlobalScope to only show content that is reviewed.
In Post:
protected static function boot()
{
parent::boot();
static::addGlobalScope('reviewed', function (Builder $builder) {
$builder->where('reviewed', true);
});
}
But now I have the problem that I still cannot exclude an empty query. I show you the output:
//ProfileContent
array:2 [
0 => array:8 [
"id" => 1
"profile_id" => "1"
"content_id" => "1"
"content_type" => "App\Video"
"content" => "[some array values]"
]
1 => array:8 [
"id" => 2
"profile_id" => "1"
"content_id" => "1"
"content_type" => "App\Post"
"content" => null
]
]
How can I exclude the null array without losing the paginated data (output should be 5)
Review your question one more time u are accessing relationship and then trying to eagerload the relationship again. I am pretty sure this is what you want:
$user->contents()
->latest()
->with(['posts' => function ($query){
//here you add a query constrain on eagerload like:
$query->where('reviewed', true);
}])
->paginate(5);

Laravel: Check if Models have same relation

I have models: Partido and Coalicion related in a many to many relationship.
I need to know when two or more Coalicion has the same Partido related.
Hope I have explained myself.
Edit 1:
Model:
class Coalicion extends Model
{
public function partidos()
{
return $this->belongsToMany(Partido::class);
}
}
Let's say users selected some elements from a select input and I grabbed them in an array and send them to the controller.
...
public function example(Request $request)
{
$coaliciones = $request->coaliciones;
foreach ($coaliciones as $c) {
$coalicion = Coalicion::find($c);
# Here we have a list of Coalicion model in a loop
# Let's say the first iteration I can see the relationship
dump($c->partidos);
}
}
This for example give me the following answer at the browser:
Collection {#1 ▼
#items: array:2 [▼
0 => Partido {#271 ▶} #This is Partido with id 1
1 => Partido {#268 ▶}
]
}
Collection {#2 ▼
#items: array:3 [▼
0 => Partido {#279 ▶}
1 => Partido {#280 ▶}
2 => Partido {#283 ▶} #This is Partido with id 1
]
}
I need to know when the item 0 of the first Collection and the item 2 of the second Collection are the same.
I kinda found a way but I don't know if it's the correct or best approach.
In Coalicion model I add the following function:
public function partidosId()
{
return $this->partidos->pluck('id');
}
With this I can get only the id's from the relations, then in the controller I created an empty array() and fill it with all my ids with a foreach loop, then, finishing up I evaluated if the id's in the now filled array are unique, if the unique values are less than the length of the array then some models have the same relation (I don't know which but It's a start), e.g.:
public function example(Request $request)
{
$coaliciones = $request->coaliciones;
$allItems = [];
foreach ($coaliciones as $c) {
$coalicion = Coalicion::find($c);
$allItems = array_merge($allItems, $coalicion->partidosId()->toArray());
}
if (count(array_unique($allItems))<count($allItems)) {
dd("Duplicates");
}else{
dd("Uniques");
}
}
If anyone find a better way or a way to know which are the ones with the duplicate relation please let me know

Resources