Getting a human readable version of the PHP error_reporting directive value

Published on 2021-08-20 • Modified on 2021-08-20

In this snippet, we see how to get a human-readable version of the PHP error_reporting directive value. The code is mainly extracted from the comments on the PHP documentation page, but I've cleaned it a little.


<?php

declare(strict_types=1);

// src/Controller/Snippet/Snippet160Trait.php

namespace App\Controller\Snippet;

/**
 * I am using a PHP trait to isolate each snippet in a file.
 * This code should be called from a Symfony controller extending AbstractController (as of Symfony 4.2)
 * or Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Services are injected in the main controller constructor.
 */
trait Snippet160Trait
{
    public function snippet160(): void
    {
        $errorReportingConstants = array_filter(get_defined_constants(true)['Core'] ?? [], static function ($constant): bool {
            return str_starts_with($constant, 'E_');
        }, ARRAY_FILTER_USE_KEY);

        $errorReporting = error_reporting();
        $errorReporting = $errorReporting === -1 || $errorReporting > E_ALL ? E_ALL : $errorReporting;

        echo sprintf("Error level (error_reporting()): %d\n", $errorReporting);
        $pot = 0;
        foreach (array_reverse(str_split(decbin($errorReporting))) as $bit) {
            if ((int) $bit === 1) {
                $idx = array_search(2 ** $pot, $errorReportingConstants, true);
                echo sprintf("%s (%d)\n", $idx, ($errorReportingConstants[(string) $idx]));
            }
            ++$pot;
        }

        // That's it! 😁
    }
}

 Run this snippet  ≪ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫  More on Stackoverflow   Read the doc  More on the web

<?php

declare(strict_types=1);

namespace App\Tests\Controller\Snippets;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

/**
 * @covers Snippet160Trait
 */
final class Snippet160Test extends KernelTestCase
{
    /**
     * @return iterable<int, array>
     */
    public function provideSnippet160(): iterable
    {
        yield [
            5, // = 1 + 4
            [
                'E_ERROR' => 1,
                'E_PARSE' => 4,
            ],
        ];

        yield [
            18646, // = 2 + 4 ... + 16384
            [
                'E_WARNING' => 2,
                'E_PARSE' => 4,
                'E_CORE_ERROR' => 16,
                'E_COMPILE_ERROR' => 64,
                'E_COMPILE_WARNING' => 128,
                'E_STRICT' => 2048,
                'E_USER_DEPRECATED' => 16384,
            ],
        ];
    }

    /**
     * @param array<string,int> $codes
     *
     * @dataProvider provideSnippet160
     *
     * @covers Snippet160Trait::snippet160
     */
    public function testSnippet160(int $errorReporting, array $codes): void
    {
        self::assertSame($this->getHumanVersion($errorReporting), $codes);
    }

    /**
     * @return array<string,int>
     */
    private function getHumanVersion(int $errorReporting): array
    {
        $codes = [];
        $errorReportingConstants = array_filter(get_defined_constants(true)['Core'] ?? [], static function ($constant): bool {
            return str_starts_with($constant, 'E_');
        }, ARRAY_FILTER_USE_KEY);
        $pot = 0;
        foreach (array_reverse(str_split(decbin($errorReporting))) as $bit) {
            if ((int) $bit === 1) {
                $idx = array_search(2 ** $pot, $errorReportingConstants, true);
                $codes[(string) $idx] = (int) $errorReportingConstants[(string) $idx];
            }
            ++$pot;
        }

        return $codes;
    }
}