Pawooo's avatar

Retrieve value from HasMany relationship associative array

Laravel 10, Filament V2

How should I modify my partial or controller to be able to fetch a specific value from a relationship (in this case – "total")?

Controller

        $companies = Company::query()
            ->with(['achievements', 'members'])
            ->where('created_at', '!=', NULL)
            ->orderBy('created_at', 'desc')
            ->paginate();

Component (View)

 <div class="badge badge-outline">{{$company->members}} members</div>

dd($company->members)

Illuminate\Database\Eloquent\Collection {#2049 ▼ // resources/views/components/company.blade.php
  #items: array:1 [▼
    0 => App\Models\CompanyMembers {#2035 ▼
      #connection: "mysql"
      #table: "company_members"
      #primaryKey: "id"
      #keyType: "int"
      +incrementing: true
      #with: []
      #withCount: []
      +preventsLazyLoading: false
      #perPage: 15
      +exists: true
      +wasRecentlyCreated: false
      #escapeWhenCastingToString: false
      #attributes: array:11 [▼
        "id" => 1
        "company_id" => 2
        "total" => 10
        "members-20s" => null
        "members-30s" => null
        "members-40s" => null
        "members-50s" => null
        "members-60s" => null
        "daiku" => 0
        "created_at" => "2023-09-11 06:30:15"
        "updated_at" => "2023-09-11 06:30:15"
      ]
      #original: array:11 [▶]
      #changes: []
      #casts: []
      #classCastCache: []
      #attributeCastCache: []
      #dateFormat: null
      #appends: []
      #dispatchesEvents: []
      #observables: []
      #relations: []
      #touches: []
      +timestamps: true
      +usesUniqueIds: false
      #hidden: []
      #visible: []
      #fillable: array:8 [▶]
      #guarded: array:1 [▶]
    }
  ]
  #escapeWhenCastingToString: false
}

Writing it as members['total'] or members[0]->total or members->total or members->attributes->total returns undefined, I'm super confused.

Any help would be much appreciated :)

0 likes
7 replies
krisi_gjika's avatar

bases on your relations, one company can have many members. From which member should this total be taken from? What is the meaning of this total field on the member model?

Pawooo's avatar

@krisi_gjika Total stands for "how many people work at company XYZ"

Oh, I think I see my mistake now...

  1. In my Filament Dashboard, I can create many entries for one company that describe how many members it has of different age etc. (which is pointless, it should just be one entry)
  2. My model relationship for members is not HasOne, but HasMany, leading to having the value returned as a nested array (still, that should not be the reason why I can't access it with members[0]->total)

Let's replace members with, say, achievements.

One company can have lots of yearly entries about how it performed this year, I'll need to fetch the newest one and output a specific value (basically, same pattern).

As for the members, I guess I'll start by going back to Filament documentation to try and understand how do you create a single-entry page where /view and /edit routes are the same (probably this one https://filamentphp.com/docs/2.x/admin/resources/custom-pages)

krisi_gjika's avatar
Level 14

@Pawooo if you want to eager load the latest achievement, you can create a new relationship.

public function achievements(): HasMany
{
  return $this->hasMany('App\Model\Achievement');
}

public function latestAchievement(): HasOne
{
  return $this->hasOne('App\Model\Achievement')->latest();
}

now you can eager load the latest achievement for companies Company::query()->with(['latestAchievement'])

1 like
Pawooo's avatar

@krisi_gjika Thanks! I think now I understand the flow here.

UPD: It works! Now I only get the latest record as a single item

1 like
Pawooo's avatar

@krisi_gjika Sorry to disturb you, but how would you output/pluck $company->members->attributes->total based on controller/component structure above?

I tried to pluck a value members.total from Laravel collection in my controller, but something really weird is happening (paginate() throws an error or orderBy becomes non-existent)

krisi_gjika's avatar

@Pawooo I though you fixed the members relation to a HasOne as it's meant to be? you would just do $company->members->total

Pawooo's avatar

@krisi_gjika Sorry I missed your reply! I setup a custom page in Filament (migrated to V3) that allowed me to use HasOne as you proposed! Thanks again!

Please or to participate in this conversation.