Eloquent $appends acts strangely in laravel 5.3 - laravel

am simply trying to include a new attribute to be available in the json response but for some reason am also getting the object relation as well.
// user model
protected $guarded = ['id'];
protected $appends = ['role_name'];
protected $hidden = ['remember_token', 'password'];
public function getRoleNameAttribute()
{
return $this->role->type;
}
public function role()
{
return $this->belongsTo(Role::class);
}
// role model
public function users()
{
return $this->hasMany(User::class);
}
when i use dd($user); i get
User {#303
#guarded: array:1 [
0 => "id"
]
#appends: array:1 [
0 => "role_name"
]
#hidden: array:2 [
0 => "remember_token"
1 => "password"
]
#connection: null
#table: null
#primaryKey: "id"
#keyType: "int"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:7 [
"name" => "testing"
"email" => "email#asd.com"
"password" => "$2y$10$fogQXhJZm5eoViM38pge1.BmNxY7IFl515zT83.Ks9Uj26kK9T6Im"
"role_id" => "83eee2e0-8939-48f7-9fbc-1c077e2265e5"
"id" => "a181fb4b-b65a-47b4-9c72-21ea15c6c5a6"
"updated_at" => "2017-01-30 20:23:52"
"created_at" => "2017-01-30 20:23:52"
]
#original: array:7 [
"name" => "testing"
"email" => "email#asd.com"
"password" => "$2y$10$fogQXhJZm5eoViM38pge1.BmNxY7IFl515zT83.Ks9Uj26kK9T6Im"
"role_id" => "83eee2e0-8939-48f7-9fbc-1c077e2265e5"
"id" => "a181fb4b-b65a-47b4-9c72-21ea15c6c5a6"
"updated_at" => "2017-01-30 20:23:52"
"created_at" => "2017-01-30 20:23:52"
]
...
}
and with return response()->json(compact('user')); instead i get
user: {
created_at: "2017-01-30 20:26:12"
email:"email#asd.com"
id:"4b83e031-e8c8-4050-963d-446cb383fb14"
name:"testing"
role:{
created_at:"2016-12-29 10:54:02"
id:"83eee2e0-8939-48f7-9fbc-1c077e2265e5"
type:"user"
updated_at:"2016-12-29 10:54:02"
}
role_id:"83eee2e0-8939-48f7-9fbc-1c077e2265e5"
role_name:"user"
updated_at:"2017-01-30 20:26:12"
}
but what i expect is to only have
user: {
created_at: "2017-01-30 20:26:12"
email:"email#asd.com"
id:"4b83e031-e8c8-4050-963d-446cb383fb14"
name:"testing"
role_id:"83eee2e0-8939-48f7-9fbc-1c077e2265e5"
role_name:"user"
updated_at:"2017-01-30 20:26:12"
}
so am not sure if this is the normal behavior or a bug or maybe am missing something ?
Laravel version 5.3.30

The reason why this is happening is the following
public function getRoleNameAttribute()
{
return $this->role->type;
}
The problem here is the when you say $this->role it will automatically attached the relationship to the model. In order to prevent this, you should simply be able to access the method directly, like $this->role().
public function getRoleNameAttribute()
{
return $this->role()->first()->type;
}

Related

laravel how to show one to many data in view (fetch ) in view

hello I'm trying to fetch one to many data in view like post with this feast comment shooed be show in view
iam able to get value in array now i what to show in view
my array controller
public function data($id)
{
$post= User::with(['Comments'=>function($query){
$query->first();
}])->find($id);
dd($post->toArray());
}
array data
array:53 [▼
"id" => 39
"name" => "KUMAR"
"post" => "hello word "
"created_at" => "2022-02-11T02:38:51.000000Z"
"updated_at" => "2022-02-11T10:05:26.000000Z"
"comments" => array:1 [▼
0 => array:13 [▼
"id" => 6
"user_id" => "39"
"comment" => "good post"
"created_at" => "2022-02-11T15:13:51.000000Z"
"updated_at" => "2022-02-11T15:13:51.000000Z"
]
]
]
my view Controller
public function data($id)
{
$post= User::with(['Comments'=>function($query){
$query->first();
}])->find($id);
return view('user.post',compact('post'));
}
So your User model already has this comments relationship
public function comments()
{
return $this->hasMany(Comment::class);
}
You can add this firstComment relatioship
public function firstComment()
{
return $this->hasOne(Comment::class)->oldest(); // or ->latest()
}
Then fetch your User this way
$post = User::with(['firstComment'])->find($id);
dump($post);
dd($post->firstComment);
Try this
public function data($id)
{
$post= User::wherehas('Comments', function($query){
$query->where('user_id',$id);
})->get();
return view('user.post',compact('post'));
}

Laravel belongsto relations get property problem

I have belongsto relation:
class Yetkiliservis extends Model
{
protected $table = 'yetkiliservis';
protected $guarded=[];
public function bolge(){
return $this->belongsTo(Bolgeler::class);
}
}
when I convert the model to array everything is right. It shows relation.
$yetkiliservisler = Yetkiliservis::with('bolge')->get();
dd($yetkiliservisler[0]->toArray());
result :
array:22 [▼
"id" => 1
"vergi_no" => "1"
"yerel_adi" => "1"
"bolge" => array:6 [▼ <------------------------------------
"id" => 1
"bolge_adi" => "İSTANBUL"
"ad_soyad" => "istanbul"
"email" => "istanbul#mail.com"
"created_at" => "2020-04-24 15:53:31"
"updated_at" => "2020-04-24 15:53:31"
]
"yetkili_adi" => "1"
]
But when I try to get by the property it shows null.
$yetkiliservisler = Yetkiliservis::with('bolge')->get();
dd($yetkiliservisler[0]->getAttributes());
result :
array:22 [▼
"id" => 1
"vergi_no" => "1"
"yerel_adi" => "1"
"bolge" => null <--------------------------------
"yetkili_adi" => "1"
]
First you change the raname like this
public function bolges(){
return $this->hasMany(Bolge::class,'yetkiliservi_id','id');
}
After you execute this command
composer dump-autoload
Then first check php artisan tinker; relation is correct??
Then try this
$yetkiliservisler[0]->bolges;
Hope it will helpful for you

The "key" in Laravel eloquent relationship

I have 2 models: Invoice and InvoiceItems and these models are connected with invoice_id:
Schema::create('invoice_items', function (Blueprint $table) {
$table->bigInteger('invoice_id')->unsigned();
$table->foreign("invoice_id")->references('id')->on('invoices')->onDelete('cascade');
});
Invoice :
class Invoice extends Model
{
protected $fillable = [
'profile_id',
'invoice_number',
....
];
public function invoiceItems()
{
return $this->hasMany('App\InvoiceItem');
}
}
And InvoiceItems
class InvoiceItem extends Model
{
protected $guarded = [];
public function invoice()
{
return $this->belongsTo('App\Invoice');
}
}
When I want to get an invoice with it's invoice items using eloquent, I use the following code:
$invoice = Invoice::with('invoiceItems')->findOrFail($id);
now the output of dd($invoice->toArray()) is:
array:20 [▼
"id" => 14
"profile_id" => 13
"invoice_number" => null
....
"created_at" => "2020-05-05 09:21:46"
"updated_at" => "2020-05-09 12:09:14"
"invoice_items" => array:1 [▼
0 => array:10 [▼
"id" => 9
"invoice_id" => 14
"price" => "10000.00"
"created_at" => "2020-05-05 09:21:46"
"updated_at" => "2020-05-05 09:21:46"
]
]
]
till now everything looks great, but I'm confused! when I want to use $invoice->invoice_items it returns null while it exists in the top dd($invoice->toArray())!
On the other hand when I use $invoice->invoiceItems it works well!
now whats the reason of this difference?
Use $invoice->invoiceItems instead.
you can find it in the relationships attribute I think.
To array executes laravel logic, they choose to include everything as kebab_case to keep it consistent datawise, but I understand your confusion.

Strange Eloquent Behavior: Trying to get property 'name' of non-object while Object exist

I have this function that returns a value in the DB:
public function getMetaValue($key)
I then created a function to read a data in the DB based off of the getMetaValue:
public function getFeatureByMeta($estate, $type)
{
$metaId = (int) $estate->getMetaValue($type);
$feature = Feature::where('id', $metaId)->first();
return $feature->name;
}
If I now return:
$this->getFeatureByMeta($estate, 'stato_immobile')
It throws
Trying to get property 'name' of non-object.
While if I dump-die the same exact thing it dumps the correct result:
dd($this->getFeatureByMeta($estate, 'stato_immobile'));
//Returns "Nuovo / In costruzione" which is the DB data `name` I need
If I take the function getFeatureByMeta and instead of Feature::where('id', $metaId) I hardcode the id value, the above error does not show up and I do get the correct item name:
public function getFeatureByMeta($estate, $type)
{
$feature = Feature::where('id', 54)->first();
return $feature->name;
}
And
public function getFeatureByMeta($estate, $type)
{
$metaId = (int) $estate->getMetaValue($type);
dd($metaId); //Returns 54
}
If I dd($feature) I do get the row I'm talking about:
App\Feature^ {#904
//...
#attributes: array:5 [
"id" => 57
"name" => "Da ristrutturare"
"category" => "stato_immobile"
"created_at" => "2019-09-16 12:15:13"
"updated_at" => "2019-09-16 12:15:13"
]
#original: array:5 [
"id" => 57
"name" => "Da ristrutturare"
"category" => "stato_immobile"
"created_at" => "2019-09-16 12:15:13"
"updated_at" => "2019-09-16 12:15:13"
]
#changes: []
//...
}
What can be causing this?
I made a video to make it more clear: https://streamable.com/5nsq4
For some reason I still don't understand the only solution I found is this:
public function getFeatureByMeta($estate, $type)
{
$feature = Feature::find($estate->getMetaValue($type));
if ($feature) {
return $feature->name;
}
}
Using the if returns the correct name attribute.
If you know why, please comment.

Laravel Eager Loading is Null with Polymorphic Relations

In my model I have:
//UserAddress.php
protected $with = ['address'];
public function address()
{
return $this->morphOne('App\Address', 'addressable');
}
//User.php
public function userAddress()
{
return $this->hasOne(UserAddress::class);
}
//Address.php
public function addressable()
{
return $this->morphTo();
}
But when I call dd(auth()->user()->userAddress)) The address realtionship is not loaded. It is still null.
#attributes: array:4 [
"id" => "1"
"user_id" => "1"
"created_at" => "2018-11-13 10:11:54"
"updated_at" => "2018-11-13 10:11:54"
]
#original: array:4 [
"id" => "1"
"user_id" => "1"
"created_at" => "2018-11-13 10:11:54"
"updated_at" => "2018-11-13 10:11:54"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [
"address" => null
]
#touches: []
+timestamps: true
However, with dd(auth()->user()->userAddress()->get())) the relationship is eager loaded.
What is the problem?
Edit
It is super weird. If I write auth()->user()->userAddress->address I get null (it should not be that). And when I remove protected $with = ['address']; auth()->user()->userAddress->address gets me the correct model.
I have similar issue. It is loading the related models, but under different key.
I got a pivot model called Skillable it has a morphTo relationship to get the related morphed model.
public function morphedModel(): MorphTo
{
return $this->morphTo('skillable');
}
That works fine without eager loading when used like that
echo $skillable->morphedModel->id; // return some id
However when using eager loading, the morphedModel prop is null.
Skillable::with('morphedModel')->get()->first()->morhphedModel; // returns null
Turns out the eager loading is working almost as expected, however the related (morphed) models are loaded under skillable relationship instead.
dump(Skillable::with('morphedModel')->get()->first());
returns
...
#relations: array:2 [▶
"morphedModel" => null
"skillable" => App\Models\Lesson {#2376 ▶
Not sure why though.. something with my relation definition I guess.
I had the same issue with a one-to-one relationship where the id field was a string. Everything worked until I eager-loaded the connecting table (user_address in you case).
In my case I'd forgotten to define public $incrementing = false; in the connecting table, and once I had added this everything worked.

Resources