Test multiple PHP exceptions

There are cases when you have a base exception class which is extended by other exceptions. For a package called User, you could have a UserException which is inherited by UserNotFoundException, UserPasswordException and so on.

The base exception of your package allows you to catch any thrown exception from inside the package.

So there’s a base exception, a specific one and the service using them:

class BaseException extends Exception
{
}

class NoItemsException extends BaseException
{
}

class Service
{
    /**
     * @param array $items
     * @throws NoItemsException
     */
    public function save(array $items)
    {
        if (count($items) === 0) {
            throw new NoItemsException('Nothing to save');
        }
    }
}

And you want to catch all package exceptions:

$service = new Service();
try {
    $service->save([]);
} catch (BaseException $e) {
    die($e->getMessage());
}

And a test for the case:

class ServiceTest extends TestCase
{
    /**
     * @expectedException NoItemsException
     */
    public function testSaveWithNoItems()
    {
        $service = new Service();
        $service->save([]);
    }
}

How do you make sure NoItemsException extends BaseException?
With the above test, if you change NoItemsException to extend Exception instead of BaseException, the test will still pass, but the behaviour won’t be the expected one, because you won’t be catching the exception anymore:

Fatal error: Uncaught NoItemsException: Nothing to save... in /src/Service.php on line 20

NoItemsException: Nothing to save... in /src/Service.php on line 20

Your test must explicitly test both exceptions:

class ServiceTest extends TestCase
{
    public function testSaveWithNoItems()
    {
        $service = new Service();

        try {
            $service->save([]);
            $this->fail('No exception thrown');
        } catch (\Exception $e) {
            $this->assertInstanceOf(BaseException::class, $e);
            $this->assertInstanceOf(NoItemsException::class, $e);
        }
    }
}

PHP unit testing with real coverage

If you really need to cover all your code by tests, watch out for your short if statements.

Given the following class:

<?php

class Person
{
    /**
     * @var string
     */
    private $gender;

    /**
     * @param string $gender
     */
    public function setGender(string $gender)
    {
        $this->gender = $gender;
    }

    /**
     * @return string
     */
    public function getTitle() : string
    {
        return $this->gender === 'f' ? 'Mrs.' : 'Mr.';
    }
}

And a PHP Unit test:

<?php

use PHPUnit\Framework\TestCase;

class PersonTest extends TestCase
{
    /**
     * @dataProvider gendersAndTitle
     * @param $gender
     * @param $expectedTitle
     */
    public function testTitle($gender, $expectedTitle)
    {
        $person = new Person();
        $person->setGender($gender);

        $title = $person->getTitle();
        $this->assertEquals($expectedTitle, $title);
    }

    public function gendersAndTitle() : array
    {
        return [
            ['f', 'Mrs.'],
        ];
    }
}

If you run the test with coverage, you get a 100% coverage. But the data provider has only data for the “f/Mrs.” case, so the else branch of the short if is not actually tested, though the tested code reached the line while running the test.

Update the getTitle method from Person class using the normal if statement:

public function getTitle() : string
{
    if ($this->gender === 'f') {
        return 'Mrs.';
    }

    return 'Mr.';
}

Execute the test again and you get 80% coverage.

Here’s a Dockerfile to quickly test it yourself:

FROM php:7.2-cli-alpine3.8

RUN apk add --update --no-cache make alpine-sdk autoconf && \
    pecl install xdebug && \
    docker-php-ext-enable xdebug && \
    apk del alpine-sdk autoconf && \
    wget -O phpunit https://phar.phpunit.de/phpunit-6.phar && chmod +x phpunit

WORKDIR /src

Save the Person class to Person.php file and the test to PersonTest.php.

docker build -t phpunit-coverage .
docker run --rm -ti -v $PWD:/src phpunit-coverage sh

./phpunit --bootstrap Person.php --coverage-html coverage --whitelist Person.php .

See the coverage directory (index.html) created after running the test.

Clean up when you’re done:

docker rmi phpunit-coverage

PHP performance increase from 5.6 to 7.2

I remember when PHP 7 was released. The first thing I did was a simple performance test. I don’t remember the script exactly, but it was similar to this:

<?php

$time = microtime(true);

$array = [];
for ($i = 0; $i < 10000; $i++) {
    if (!array_key_exists($i, $array)) {
        $array[$i] = [];
    }
    
    for ($j = 0; $j < 1000; $j++) {
        if (!array_key_exists($j, $array[$i])) {
            $array[$i][$j] = true;
        }
    }
}

echo sprintf(
    "Execution time: %f seconds\nMemory usage: %f MB\n\n",
    microtime(true) - $time,
    memory_get_usage(true) / 1042 / 1042
);

The results made me really happy. Continue reading PHP performance increase from 5.6 to 7.2

Playing with PHP extensions: building a map

I’ve ran into PHP-CPP, a C++ library which helps you build your own PHP extensions in an easier way than writing them from scratch. And I decided to play a little bit. It has good documentation and examples.

Installing is not always out of the box depending on the environment. I like to keep things clean on my working machines so I wanted to have everything in a Docker container, but I quickly ran into an issue installing the library. Fortunately, I’ve found a solution pretty fast.

The first idea that came into my mind was a simple map. Nothing special, I’m not bringing any improvements, I just wanted to convert the following into an extension. Continue reading Playing with PHP extensions: building a map

Concurrency in PHP with Swoole

Swoole is a CLI server written in C as a PHP extension. It handles HTTP, TCP and socket servers, offering some really interesting features. The ones I’ve tested and I’m pretty excited about are related to concurrency.

The authors have implemented a concurrency model similar to Go‘s, using coroutines and channels for inter-process communication. It also has a memory map, atomic objects, locks, buffers, timers and others.

I’ve tested their 2.2 version found in PECL, but very recently they’ve release the 4.0.0 version. My enthusiasm suffered a little bit when they’ve introduced a pretty nasty bug with 4.0.0, but they were fast about fixing it, although a new version is not released at the time of writing (but you can compile from master branch).
It’s funny that one day everything was working as expected, and the other day I spent some time until I’ve figured they had just released a new version, and that was causing my issue. I had installed the extension without specifying the version, so a new install got me the latest one.

Below is a very small example of concurrency using routines and a channel. Continue reading Concurrency in PHP with Swoole

PHP backward compatibility

Could PHP 7 inherit Go’s philosophy of not introducing breaking changes in future versions? I’ve asked this myself today.

PHP is on a really nice path since version 7, with its courageous changes, and I believe more is yet to come. Because things must evolve, there were some incompatible changes from 5 to 7, and that’s great. And now that it’s more mature, I would like to see more stability and more of those hardcore changes that will keep the language in its good position.

Regarding this, something that I really wish for PHP 7 is to approach Go’s idea of not introducing incompatibilities with future versions. The programs should run flawless when upgrading PHP. It would be a great encouragement for everyone to safely upgrade as soon as a new version is released.

From PHP to Go

Besides being very powerful, Go is a clean language. It was easy to get started with it, despite it has some obvious major differences if coming from a language like PHP. I knew some of them, cause they’re specific to any compiled language, while in an interpreted one you have to work in order to get their benefits.

I got comfortable with them and even wished PHP had them. I’m not comparing the two languages by considering one to be better or worse, I’m only telling some differences that caught my eye, even if they are normal to be.

It got me happy about writing code in a very different way, putting aside some things that are normal in other contexts and I was used to. Continue reading From PHP to Go

Why I chose to build a framework at a 3-hour interview

I encourage the use of known frameworks over custom ones, but I decided not to use one when, at an interview, I had 3 hours to prove the technical aspects I’ve been talking about at the first encounter with the employer.

The task was simple: build a REST web service (using PHP and MySQL) and make some operations on a resource, and a small JavaScript client to interact with the service.

I felt that using a known framework for a basic task like this I couldn’t show too many principles I use when developing. It wasn’t the moment to build a production ready app, it was just to show I can DO what I KNOW.

So my 3-hour journey building a framework from scratch started. It had basic components like: Continue reading Why I chose to build a framework at a 3-hour interview

Types comparison and functions

PHP will let you change a variable’s type at any moment, and there’s nothing you can do about it. While you can use data structuresargument type declaration, and return type declaration to save a lot of damage, you can still change types.

<?php

declare(strict_types=1);

function showTypes(int $number) {
    echo gettype($number) . "\n"; //integer

    $number = "string";
    echo gettype($number) . "\n"; //string
}

showTypes(2);

In order to help this situation a little bit, I’m using the appropriate type comparison operators and functions:

<?php

$number = 1;

// OK
if ($number > 0) {}

// Not OK
if (!$number) {}
if ($number === '') {}
if (strlen($number) > 0) {}


$string = 'Lorem ipsum';

// OK
if ($string === '') {}
if (strlen($string) > 0) {}

// Not OK
if (!$string) {}


$list = [];

// OK
if (count($list) > 0) {}

// Not OK
if (!$list) {}


$bool = false;

// OK
if (true === $bool) {}
if (!$bool) {}

// Not OK
if ($bool == '') {}


$var = null; // if I know a var can be null

// OK
if (null === $var) {}
if (is_null($var)) {}

// Not OK
if (!$var) {}

As such, I’m being more specific about the type variables are holding. In clean code it’s faster to see what a variable holds, but in legacy systems you can see a variable hundreds of lines later after declaration, or you can get a value from a function with no return type or DocBlock.

Treat each variable as close as possible to its type.

Using data structures for types

Data types should be very specific. Anyone using a variable should know exactly what type it is, how it looks like (if it’s a structure). While for some languages it’s common sense and really enforced, others will let you mess with a variable’s type, no matter it’s a primitive, an object, an array.

I’m going to talk about data coming from JSON, databases or other sources, which can be represented into data structures.

In a language like Go, you map data into well defined structures.

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    ID int
    Age int
    Name string
}

func main() {
    string := `{
        "id":453,
        "age":26,
        "name":"John Doe"
    }`

    input := []byte(string)

    person := Person{}
    err := json.Unmarshal(input, &person)
    if err != nil {
        panic(err)
    }

    fmt.Println(person) // Person struct
    fmt.Println(person.ID) // integer
    fmt.Println(person.Age) // integer
    fmt.Println(person.Name) // string
}

You know exactly that you have an object of type Person, with integer ID, integer Age, and string Name. No need to check anything anywhere. If you mess up, you’ll know at compile time.

A dynamic typed language like PHP has a different approach. Continue reading Using data structures for types