PHP Tuples
Tags: php, go, discuss
Published: 2019-06-09 23:47:11

---
title: PHP Tuples
published: true
description: Let's talk about PHP Tuples and why exploring new languages is good for you.
tags: php, golang, devdiscuss
canonical_url: https://sasablagojevic.com/php-tuples
cover_image: https://sasablagojevic.com/img/front/tuple.jpg
---

<p>How do we call a gopher and an elephant dating? A tuple.&nbsp;</p>
<p>Wow, this makes no sense whatsoever...ok, we should move on now...</p>
<p>I've been working in <strong>golang</strong> for quite some time and I started to pick up some patterns subconsciously. Since golang has <a title="Golang - Multiple Return Values" href="https://gobyexample.com/multiple-return-values" target="_blank" rel="noopener">multiple return values</a>, which I find quite useful and am a big fan of, I started doing this more and more in <strong>php</strong>:</p>
```php
<?php

list($items, $count) = $contentRepository->getSlice($page, $perPage, $filters, $sorts);

// or the even sweeter shorthand syntax

[$items, $count] = $contentRepository->getSlice($page, $perPage, $filters, $sorts);
```
<p>What we are doing here is just destructuring the plain ole' integer indexed array, commonly know in more CS uppity circles as a&nbsp;<a title="Lists" href="https://en.wikipedia.org/wiki/List_(abstract_data_type)" target="_blank" rel="noopener">list</a>. But there is a downside to this approach, arrays are kinda like blackboxes, we don't have a clue what's in them, it could be anything. Let's take a look at&nbsp;<strong><em>getSlice</em>&nbsp;</strong>method signature to get a better understanding:</p>
```php
<?php

public function getSlice(int $page, int $perPage, array $filters = [], array $sorts = []): array;
{
    // something, something
    return [$items, 15];
}
```
<p>You see, we don't know what type the array's members will be and there is really no way to enforce it, so we could easily introduce some nasty bugs if we were to accidentally put some unexpected values.</p>
<p>We can tweak this approach a bit by adding&nbsp;<span style="text-decoration: underline;">doc blocks</span>&nbsp;to the method signature which will help our IDE and static analysis tools like <a title="PHPStan" href="https://github.com/phpstan/phpstan" target="_blank" rel="noopener">PHPStan</a> to know what values are expected:</p>
```php
<?php

/**
 * @return array<int,string>;
 **/
public function getTitleAndName(): array;
{
    return ["Supreme Overlord", "Sasa Blagojevic"];
}
```
<p>Wait, what? Why are we using a different example now? Well, this has its limitations as well, <span style="text-decoration: underline;">doc blocks</span> only add value if all the array's members are of the same type. In our first example that's not the case. So what do we do now?</p>
<h3>Say welcome to <strong>PHP Tuples</strong></h3>
```php
class Tuple implements ArrayAccess
{
    private $values;

    public function __construct(...$values)
    {
        $this->values = $values;
    }

    public final function offsetExists($offset)
    {
        return isset($this->value[$offset]);
    }

    public final function offsetGet($offset)
    {
        return isset($this->value[$offset]) ? $this->value[$offset] : null;
    }

    public final function offsetSet($offset, $value) {}

    public final function offsetUnset($offset) {}
}
```
<p>Let's dissect this code snippet a bit:</p>
<ul>
<li>We've implemented the <a title="PHP ArrayAccess Interface" href="https://www.php.net/manual/en/language.oop5.final.php" target="_blank" rel="noopener"><em>ArrayAccess</em></a> interface to make the objects of the class <em>Tuple</em> accessible as arrays</li>
<li>We've left the <em><strong>offsetSet</strong></em> and <em><strong>offsetUnset</strong></em> methods with empty bodies so that our tuples are immutable, we don't want to introduce bugs by accidentally mutating their state</li>
<li>We've made all the implemented methods <em><strong>final</strong></em> so other developers can't override them and break the underlying behaviour of our tuple, except the constructor</li>
</ul>
<p>This is going to be our generic tuple. To make things more strict and explicit we will make&nbsp;custom tuple classes on per case basis by extending our&nbsp;<em>Generic Tuple</em> class&nbsp;and adding types to the constructor:</p>
```php
<?php

class ContentSlice extends Tuple
{
    /**
     * ContentSlice constructor.
     * @param array<int, Content> $items
     * @param int $count
     */
    public function __construct(array $items, int $count)
    {
        parent::__construct($items, $count);
    }
}
```
<p>Let's apply this new found knowledge to our first example:</p>
```php
<?php

class ContentRepository 
{
    public function getSlice(int $page, int $perPage, array $filters = [], array $sorts = []): Tuple;
    {
        // something, something
        $items = [Content(), Content(), Content()];
        return new ContentSlice($items, 15);
    }
}
```
<p>Now if we were to put wrong values in the&nbsp;<em>ContentSlice</em> constructor the code would explode. So what we have achieved now is that we have both <span style="text-decoration: underline;">multiple return values</span> and <span style="text-decoration: underline;">explicit and strict code</span> like in golang.</p>
![Mind blown](https://media.giphy.com/media/xT0xeJpnrWC4XWblEk/giphy.gif)
<p>This is why learning new languages is great, you will stretch out your brain and force it to solve problems in a different way that is idiomatic to the new language. This new knowledge will then pay dividens in your main language when you start to apply all the cool concepts that you've subconsciously or conscioulsy picked up. This is a great way to hone your skills.</p>
<p>I had this random thought tonight and wanted to share this with you guys (my imaginary audience). I find this pretty cool and I'm probably going to try it out in a project to see how it fares in real world applications, what are your thoughts about <strong>PHP Tuples</strong>?</p>