Answers.Body: <p>I've found a workaround for now. It's not ideal and I feel like it will probably be too intensive at scale but, for my uses, it will work.</p>
  
  <p>Rather than using <code>select()</code> to reduce the data being returned from the initial query, I'm simply returning everything:</p>
  
  <pre><code>$related = Entry::find()
     -&gt;relatedTo($entry)
     -&gt;all();
  </code></pre>
  
  <p>I'm then looping over the returned object using <code>foreach()</code>, within which I'm dealing with the Matrix blocks in a seperate <code>foreach()</code>. At both levels I just pass back the data I want, something like this:</p>
  
  <pre><code>$reviews = [];
  foreach ($related as $relatedEntry) {
  
     // Condense matrix blocks
     $critiques = [];
  
     foreach($relatedEntry-&gt;critique as $block) {
        $critiques[] = array(
           'title' =&gt; $block-&gt;seriesTitle,
           'copy' =&gt; $block-&gt;review,
           'date' =&gt; $block-&gt;date,
           'viewCount' =&gt; $viewCount,
        );
     }
  
     $reviews[] = [
        'id' =&gt; $relatedEntry-&gt;id,
        'slug' =&gt; $relatedEntry-&gt;slug,
        'title' =&gt; $relatedEntry-&gt;title,
        'critiques' =&gt; $critiques,
     ];
  };
  
  </code></pre>
  
  <p>The output <code>$reviews[]</code> array is therefore equivalent to what I was doing with <code>select()</code> but not contains subarrays of my matrix field. Incidentally, I have managed to nest that one further with a SuperTable field within a matrix field. It needed another nested <code>foreach()</code> but it worked easily enough.</p>
  
  <p>Once you have all of that, you can just pass it back to the endpoint like normal, so the whole thing (with above sections of code collapsed) looks like this:</p>
  
  <pre><code>'api.json' =&gt; function() {
     return [
        'elementType' =&gt; Category::class,
        'criteria' =&gt; ['group' =&gt; 'series'],
        'paginate' =&gt; false,
        'transformer' =&gt; function(Category $entry) {
           $related = Entry::find()
              -&gt;relatedTo($entry)
              -&gt;all();
  
           // Loop over related entries to extract just the information wanted
           $reviews = [];
           foreach ($related as $relatedEntry) {
              {...}   
           };
  
           return [
              'id' =&gt; $entry-&gt;id,
              'slug' =&gt; $entry-&gt;slug,
              'title' =&gt; $entry-&gt;title,
              'reviews' =&gt; $reviews,
           ];
        }
     ];
  }
  </code></pre>
  
  <p>As I say, not ideal so I'm leaving this unanswered. If anyone has a more elegant solution I'd love to know.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-05-15T10:59:49.457Z
Answers.Text: It's been four years, so I'm marking this as the answer for now. Still open to better options.
Answers.UserDisplayName: theAdhocracy
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-06-04T10:54:17.680Z
Answers.LastActivityDate: 2020-06-04T10:54:17.680Z
Answers.UserDisplayName: theAdhocracy
Body: <p>I have an API endpoint set up for a category group. This currently provides some details of all entries that have been assigned that category (i.e. related entries). That works well for some high level details, but I now need to add support for a Matrix field that those related entries contain. Here's the current setup:</p>
  
  <pre><code>'series.json' =&gt; function() {
              return [
                  'elementType' =&gt; Category::class,
                  'criteria' =&gt; ['group' =&gt; 'series'],
                  'paginate' =&gt; false,
                  'transformer' =&gt; function(Category $entry) {
                      $entries = Entry::find()
                          -&gt;relatedTo($entry)
                          -&gt;select(['slug','title','field_rating AS rating','field_pageCopy AS desc','postDate AS date'])
                          -&gt;asArray()
                          -&gt;all();
  
                      $typeArray = array_map('strval', $entry-&gt;mediaType-&gt;all());
  
                      return [
                          'id' =&gt; $entry-&gt;id,
                          'slug' =&gt; $entry-&gt;slug,
                          'title' =&gt; $entry-&gt;title,
                          'type' =&gt; strtolower($typeArray[0]),
                          'desc' =&gt; $entry-&gt;blurb,
                          'entries' =&gt; $entries
                      ];
                  }
              ];
          }
  </code></pre>
  
  <p>However, if I try to add the Matrix field to the <code>select()</code> argument it doesn't work. If I remove <code>select()</code> I can see why: it isn't a listed field. If I remove <code>asArray()</code> then I can see all the relevant fields, but I can't limit the ones available, which is undesirable as it exposes a lot of excess information.</p>
  
  <p>I feel like their might be a better way to format my transformer to begin with, but I'm at a bit of a loss when it comes to the docs.</p>
  
Tags: <plugin-elementapi><relatedto>
Title: Retrieve Matrix Field from Related Category in Element API
ThreadText: # Retrieve Matrix Field from Related Category in Element API
  
  (Asked by: username_0 on 2020-06-01)
  
  I have an API endpoint set up for a category group. This currently provides some details of all entries that have been assigned that category (i.e. related entries). That works well for some high level details, but I now need to add support for a Matrix field that those related entries contain. Here's the current setup:
  
  ```
  'series.json' => function() {
              return [
                  'elementType' => Category::class,
                  'criteria' => ['group' => 'series'],
                  'paginate' => false,
                  'transformer' => function(Category $entry) {
                      $entries = Entry::find()
                          ->relatedTo($entry)
                          ->select(['slug','title','field_rating AS rating','field_pageCopy AS desc','postDate AS date'])
                          ->asArray()
                          ->all();
  
                      $typeArray = array_map('strval', $entry->mediaType->all());
  
                      return [
                          'id' => $entry->id,
                          'slug' => $entry->slug,
                          'title' => $entry->title,
                          'type' => strtolower($typeArray[0]),
                          'desc' => $entry->blurb,
                          'entries' => $entries
                      ];
                  }
              ];
          }
  
  ```
  
  However, if I try to add the Matrix field to the `select()` argument it doesn't work. If I remove `select()` I can see why: it isn't a listed field. If I remove `asArray()` then I can see all the relevant fields, but I can't limit the ones available, which is undesirable as it exposes a lot of excess information.
  
  I feel like their might be a better way to format my transformer to begin with, but I'm at a bit of a loss when it comes to the docs.
  
  **Tags:** plugin-elementapi, relatedto
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2020-06-04. Score: 1 | Accepted answer
  
  I've found a workaround for now. It's not ideal and I feel like it will probably be too intensive at scale but, for my uses, it will work.
  
  Rather than using `select()` to reduce the data being returned from the initial query, I'm simply returning everything:
  
  ```
  $related = Entry::find()
     ->relatedTo($entry)
     ->all();
  
  ```
  
  I'm then looping over the returned object using `foreach()`, within which I'm dealing with the Matrix blocks in a seperate `foreach()`. At both levels I just pass back the data I want, something like this:
  
  ```
  $reviews = [];
  foreach ($related as $relatedEntry) {
  
     // Condense matrix blocks
     $critiques = [];
  
     foreach($relatedEntry->critique as $block) {
        $critiques[] = array(
           'title' => $block->seriesTitle,
           'copy' => $block->review,
           'date' => $block->date,
           'viewCount' => $viewCount,
        );
     }
  
     $reviews[] = [
        'id' => $relatedEntry->id,
        'slug' => $relatedEntry->slug,
        'title' => $relatedEntry->title,
        'critiques' => $critiques,
     ];
  };
  
  ```
  
  The output `$reviews[]` array is therefore equivalent to what I was doing with `select()` but not contains subarrays of my matrix field. Incidentally, I have managed to nest that one further with a SuperTable field within a matrix field. It needed another nested `foreach()` but it worked easily enough.
  
  Once you have all of that, you can just pass it back to the endpoint like normal, so the whole thing (with above sections of code collapsed) looks like this:
  
  ```
  'api.json' => function() {
     return [
        'elementType' => Category::class,
        'criteria' => ['group' => 'series'],
        'paginate' => false,
        'transformer' => function(Category $entry) {
           $related = Entry::find()
              ->relatedTo($entry)
              ->all();
  
           // Loop over related entries to extract just the information wanted
           $reviews = [];
           foreach ($related as $relatedEntry) {
              {...}   
           };
  
           return [
              'id' => $entry->id,
              'slug' => $entry->slug,
              'title' => $entry->title,
              'reviews' => $reviews,
           ];
        }
     ];
  }
  
  ```
  
  As I say, not ideal so I'm leaving this unanswered. If anyone has a more elegant solution I'd love to know.
  
  > **Comments:**
  > **username_0**: It's been four years, so I'm marking this as the answer for now. Still open to better options.  
  
  ---
  
  