# CakePhp 4 - contain array of ids

**URL:** <https://discourse.cakephp.org/t/cakephp-4-contain-array-of-ids/10638>\
**Category:** Need Help\
**Tags:** help\
**Created:** [September 22, 2022, 1:29pm UTC](https://discourse.cakephp.org/t/cakephp-4-contain-array-of-ids/10638 "2022-09-22T13:29:15Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Drea58](https://avatars.discourse-cdn.com/v4/letter/d/e495f1/32.png) [@Drea58](https://discourse.cakephp.org/u/Drea58)\
**Post date:** [September 22, 2022, 1:29pm UTC](https://discourse.cakephp.org/t/cakephp-4-contain-array-of-ids/10638/1 "2022-09-22T13:29:15Z")

</div>

I’m trying to write a query with a contained relation and want to format the result.

Example:  
There’s an Author that hasMany Books.  
Now I want to find the author and contain his book- **IDs**.

The result format I want is:

```auto
$author = [
 id,
 firstname,
 lastname,
 books: [1,5,18,21]
]

```

I’m struggling how to write the query.  
Here’s what I tried (not working)

```auto
$this->Authors->findById(id)->contain([
     'Books' => function (Query $q) {
           return $q->formatResults(function ($results) {
                return $results->reduce(function($acc, $r){
                    $acc[] = $r->id;
                    return $acc;
                }, []);
           });
      },
])

```

The reducer collects the book ids.  
But I only get an empty result in books.

---

<div class="post-metadata">

**Author:** ![raul338](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/raul338/32/69_2.png) [@raul338](https://discourse.cakephp.org/u/raul338)\
**Post date:** [September 25, 2022, 4:11pm UTC](https://discourse.cakephp.org/t/cakephp-4-contain-array-of-ids/10638/2 "2022-09-25T16:11:44Z")

</div>

I belive its better to have the format results AFTER the contain. As the contain hasMany won’t have a way to match the two resultsets.

---

<div class="post-metadata">

**Author:** ![Zuluru](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/zuluru/32/1230_2.png) [@Zuluru](https://discourse.cakephp.org/u/Zuluru)\
**Post date:** [September 25, 2022, 10:53pm UTC](https://discourse.cakephp.org/t/cakephp-4-contain-array-of-ids/10638/3 "2022-09-25T22:53:32Z")

</div>

```auto
$author = $this->Authors->findById(id)->contain(['Books']);
$book_ids = collection($author->books)->extract('id')->toArray();

```

---

<div class="post-metadata">

**Author:** ![Drea58](https://avatars.discourse-cdn.com/v4/letter/d/e495f1/32.png) [@Drea58](https://discourse.cakephp.org/u/Drea58)\
**Post date:** [September 26, 2022, 7:10am UTC](https://discourse.cakephp.org/t/cakephp-4-contain-array-of-ids/10638/4 "2022-09-26T07:10:04Z")

</div>

Thanks, I didn’t use CakePhps collections at all until now.  
Isn’t that the same as the plain old:  
`$book_ids = array_map(function ($book) { return $book->id; }, $author->books);`  
?

Back then, when I started with cake 2, I discovered Hash:combine and used it.  
Until I noticed how absolutely inperformant it was compared to a simple for loop, that did the same.  
So now I’m a bit skeptical about fancy code snippets that already exist in simple php.  
Although I admit, with Collections the code is better to read.

---

<div class="post-metadata">

**Author:** ![Zuluru](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/zuluru/32/1230_2.png) [@Zuluru](https://discourse.cakephp.org/u/Zuluru)\
**Post date:** [September 26, 2022, 1:20pm UTC](https://discourse.cakephp.org/t/cakephp-4-contain-array-of-ids/10638/5 "2022-09-26T13:20:43Z")

</div>

Looks like that should do about the same, yes. I like collections, because they are very powerful and chainable, and I find it’s generally best for me to have my code consistent rather than fine-tune for performance in different situations.
