0

In the current application, there is a model Part and a model Supplier. Every Part has a Supplier.

    public function supplier()
    {
        return $this->belongsTo(Supplier::class);
    }

I added an accessor to get the name of the supplier.

If i return the whole dataset, i get the supplier:

    public function getSupplierNameAttribute()
    {
        return $this->supplier;
    }
    "supplierName": {
        "id": 1,
        "uuid": "37e3a715-09d3-4fac-ae88-8f12e63fe79c",
        "name": "Laserteam",
        "street": "8602 Dessie Tunnel",
        "zip": "15869",
        "city": "New Clementview",
        "email_send_type": null,
        "active": 0,
        "created_at": "2020-01-09 09:46:02",
        "updated_at": "2020-01-09 09:46:02",
        "deleted_at": null,
        "action": "",
        "activeLabel": "<span class='badge badge-secondary'>Inaktiv<\/span>"
    },

If i try to get only the name (what I need finally), there is an error:

    public function getSupplierNameAttribute()
    {
        return $this->supplier->name;
    }
ErrorException: Trying to get property 'name' of non-object in file /gopanel/sites/7industry_net/public/7time/app/Models/Part/PartAttribute.php on line 48

If i try in this way, it works:

    public function getSupplierNameAttribute()
    {
        return $this->supplier['name'];
    }

Why does return $this->supplier->name; not work?

halfer
  • 19,824
  • 17
  • 99
  • 186
Peter
  • 655
  • 1
  • 14
  • 37
  • just an idea , but try it with adding also the foreignKey on the relationship function. : return $this->belongsTo(Supplier::class,'foreignKey'); – Roland Allla Jan 09 '20 at 11:08
  • Looks like it should work. Are you sure you don't have a `toArray` anywhere? Or that you used to have it somewhere and haven't reloaded tinker yet (if you're working in tinker)? – D Malan Jan 09 '20 at 11:11
  • seems silly but try `$g = $this->supplier;` then `return $g->name` if that fails `dd($g);` before the return and see what is in side. – Bobby Axe Jan 09 '20 at 11:14

3 Answers3

1

It's hard to say what could be the problem here, but:

  1. Make sure you don't have supplier in casts for your model
  2. Make sure you don't use supplier for database column name or you don't make somewhere something this

    $this->supplier = $this->supplier->toArray();
    

It seems supplier property somewhere becomes array that's why one notation works but the other doesn't.

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
0

I’m not really sure what’s going on there; if you have a supplier relation then accessing the property should lazy-load the relationship.

Alternatively, you could try this syntax:

public function getSupplierNameAttribute()
{
    $this->loadMissing('supplier');

    return $this->getRelation('supplier')->name;
}

However, I’d avoid defining accessors like this. It can lead to N+1 problems if you say, retrieve a collection of parts and then call $part->supplier_name on each one without eager-loading the supplier relationship.

Personally, if I’m accessing attributing on relations that I prefer to do it through the relation (i.e. $part->supplier->name) so any relations I need to eager load are shown to me.

Martin Bean
  • 38,379
  • 25
  • 128
  • 201
  • 1
    I use the datatable from webix. Therefore i need the supplierName on the first level. Perhaps i will do it later with a api resource. – Peter Jan 09 '20 at 11:22
-1

Try this code

public function getSupplierNameAttribute()
{
    return $this->supplier->name ?? 'supplier not exists';
}
Davit Zeynalyan
  • 8,418
  • 5
  • 30
  • 55
  • 1
    I had one `Part` without `supplier_id`. So the code works but I has to ask first, if a supplier relation exists. – Peter Jan 09 '20 at 11:20
  • @Peter But how it solves your question? You wrote in question that for every record you have supplier, so it doesn't help I believe. It only hides problem but doesn't solve it. – Marcin Nabiałek Jan 09 '20 at 11:22
  • It was my mistake that i believed that every part has a supplier. That was the basic error! – Peter Jan 09 '20 at 11:26