Laravel - How to access attribute in whereHas clause?

Viewed 433

My entities are like:

  • RequesterType
  • Protocol
  • Flow
  • Document
  • DocumenType

The relations are like:

  • Protocol belongs to Requester Type.
  • Protocol has many flows.
  • Flow has many documents.
  • Documents belongs to Document Type.
  • Document Type belongs to Requester Type.

My needed query:

Select all Protocols that has Documents in the first Flow (let's say with sequence = 1) where has all required Document Types for his Requester Type (that's actually stored in Protocol).

For example, let's say that I have protocols with requester type 1 and want to check if all document types are present in their documents of first flow. To know all required document types simply query it from protocol requester type.

I started with:

$documentsTypesByRequester = DocumentType::groupBy('requester_id')
    ->get();

$protocols = Protocol::whereHas('flows', function ($flows) use ($documentsTypesByRequester) {
    return $flows->where('sequence', 1)
        ->whereHas('documents', function ($documents) use ($documentsTypesByRequester) {
            // Select all documents that has the same
            // requester id of protocol and all document types
            // are present...
            $requesterId = // How to access protocol requester id?
            $documentTypes = $documentsTypesByRequester[$requesterId];
            // ...
        });
});

I need to solve this with Eloquent not with Collection.

1 Answers

Seems like you are trying to get double duty out of ->whereHas() which I believe is only a constraint to limit your flows to those which have documents. Try starting with a ->where() call that encapsulates all of your matching logic, and use a simple ->whereHas('documents') and see how that works.

So something like this:

$documentsTypesByRequester = DocumentType::groupBy('requester_id')
->get();

$protocols = Protocol::whereHas('flows', function ($flows) use ($documentsTypesByRequester) {
    return $flows->where('sequence', 1)
        ->where('documents', function ($query) use ($documentsTypesByRequester) {
            // Put all of your logic for choosing a document here
            // ...
        })
    ->whereHas('documents');
});
Related