Tag: PHP

Pecl: fixing “fatal error: ‘pcre2.h’ file not found”

When using pecl to install a PHP extension, I always got a “fatal error: ‘pcre2.h’ file not found” after PHP has been updated. The update was done using brew upgrade php. In my case, this happens when I try to install pcov using:

pecl install pcov

The output was:

In file included from /private/tmp/pear/temp/pcov/pcov.c:26:
/opt/homebrew/Cellar/php/8.2.2/include/php/ext/pcre/php_pcre.h:23:10: fatal error: 'pcre2.h' file not found
#include "pcre2.h"
         ^~~~~~~~~

To fix the issue, make sure you have pcre2 installed:

brew install pcre2

After this, create a symlink to the pcre2.h file:

ln -s /opt/homebrew/Cellar/pcre2/10.42/include/pcre2.h /opt/homebrew/Cellar/php/8.2.2/include/php/ext/pcre/pcre2.h

Make sure, to adjust the versions of pcre2 and php (or any other package where you got the error). In my case it’s PHP version 8.2.2 (see the error message) and pcre2 version 10.42.

After the symlink was created, the installation of pcov finished without errors:

Build process completed successfully
Installing '/opt/homebrew/Cellar/php/8.2.2/pecl/20220829/pcov.so'
install ok: channel://pecl.php.net/pcov-1.0.11
Extension pcov enabled in php.ini

Foto von Scott Rodgerson auf Unsplash.

 

PHP: Function utf8_decode() and utf8_encode() have been deprecated

The utf8_encode() and utf8_decode() functions in PHP are used for encoding and decoding strings between ISO-8859-1 (Latin-1) encoding and UTF-8 encoding.

While PHP’s standard library does include utf8_encode and utf8_decode functions, they are limited to converting between ISO-8859-1 (Latin-1) and UTF-8 encodings. It is important to note that these functions cannot be relied upon to detect and convert other character encodings, such as Windows-1252, UTF-16, and UTF-32, to UTF-8. Attempting to use these functions with arbitrary text can introduce bugs that may not produce any warnings or errors, but can result in unexpected and undesired outcomes.

Examples of common bugs that can occur include:

  • The Euro sign (character sequence \xE2\x82\xAC), when passed to utf8_encode function as utf8_encode("€") results in a a garbled (also called as “Mojibake”) text output of â¬.
  • The German Eszett character (ßcharacter sequence \xDF), when passed through utf8_encode("ß") results in Ã.

The utf8_encode and utf8_decode functions have been deprecated in PHP 8.2 due to their misleading function names, lack of error messages and warnings, and their inability to support character encodings other than ISO-8859-1.

As a result, using these functions in PHP 8.2 will emit a deprecation notice. It is recommended to use alternative functions or libraries that provide better support for handling different character encodings. These functions will be removed entirely in PHP 9.0, so it is important to migrate to alternative solutions as soon as possible to avoid compatibility issues in future versions of PHP.

utf8_encode('foo');

// Function utf8_encode() is deprecated in ... on line ...
uft8_decode('foo');

// Function uft8_decode() is deprecated in ... on line ...

Replacement for the deprecated functions

Instead, the PHP documentation recommends using the multibyte string functions that are part of the mbstring extension for handling multibyte encodings, including UTF-8. For example, the mb_convert_encoding() function can be used to convert strings between different character encodings, including to and from UTF-8.

Replacement for utf8_encode()

Here is an example of how to use mb_convert_encoding() to encode a string to UTF-8:

$string = "Some string with non-ASCII characters: é, ö, ü";
$utf8_string = mb_convert_encoding($string, 'UTF-8');

Replacement for utf8_decode()

And here is an example of how to use mb_convert_encoding() to decode an UTF-8 string:

$utf8_string = "Some UTF-8 encoded string: é, ö, ü";
$string = mb_convert_encoding($utf8_string, 'ISO-8859-1', 'UTF-8');

Source: https://php.watch/versions/8.2/utf8_encode-utf8_decode-deprecated

 

PHP: rounding a number and keeping the zeros after comma

In PHP you can use the round() method to round a double. This methods accepts a precision value as second parameter. Some examples:

echo round(3.1415926, 2); // "3.14"
echo round(3.1415926, 3); // "3.142"

When using round() on a value like 3.0000 the conversion to a string will result in just "3":

echo round(3.0000000, 2); // "3"

This is not wrong, but when you want to have a constant precision for different numbers, having an output of "3.00" is much more helpful.

To achieve this, you can use one of the following solutions.

number_format()

echo number_format(3.1415926, 2); // "3.14"

sprintf()

echo sprintf("%.2f", 3.1415926); // "3.14"

PHP: get version details from composer.json

Let’s say we have a composer.json file as follows:

{
    "name": "mixable/blog",
    "description": "mixable.blog",
    "homepage": "https://mixable.blog",
    "version": "4.0.1",
    "type": "project",
    "require": {
        "php": "^8.x",
        "vendor/package": "^4.3",
        ...
    }
}

When using this file to manage the packages of an app, it might be necessary to check for the version of your app. This is possible by using the Composer class \Composer\InstalledVersions. The class provides different methods to access the details of the projects composer.json file.

Get details about the root package

Details about the root package are available through the getRootPackage() method:

$package = \Composer\InstalledVersions::getRootPackage();

This method returns an array with the following details:

name: string
version: string
reference: string
pretty_version: string
aliases: string[]
dev: bool
install_path: string
type: string

To get the apps version, you can use:

$version = \Composer\InstalledVersions::getRootPackage()['version'];

Get details about installed packages

There is a number of methods that provide additional information about the installed packages. Some examples:

Version of an installed package

$version = \Composer\InstalledVersions::getVersion('vendor/package');

Install path of an installed package

$installPath = \Composer\InstalledVersions::getInstallPath('vendor/package');

A detailed description of all methods is available at https://getcomposer.org/doc/07-runtime.md#installed-versions.

Photo by Ilya Pavlov on Unsplash

PHP: realpath() for non-existing path

The php method realpath() can transform the string format of a path into a real path. Means, a path string like:

/Users/mathias/data/../projects/website

will become:

/Users/mathias/projects/website

But this only works, if the path really exists. For non-existing paths, this function cannot be used. To get the same functionality, the following function can be used:

/**
 * Get normalized path, like realpath() for non-existing path or file
 *
 * @param string $path path to be normalized
 * @return false|string|string[]
 */
public function normalizePath(string $path)
{
    return array_reduce(explode('/', $path), function($a, $b) {
        if ($a === null) {
            $a = "/";
        }
        if ($b === "" || $b === ".") {
            return $a;
        }
        if ($b === "..") {
            return dirname($a);
        }

        return preg_replace("/\/+/", "/", "$a/$b");
    });
}

How to ignore PHP_CodeSniffer warning: Line exceeds 120 characters;

When using codesniffer to check your code, a lot of warnings might appear when the lines are too long:

----------------------------------------------------------------------
FOUND 0 ERRORS AND 4 WARNINGS AFFECTING 4 LINES
----------------------------------------------------------------------
  73 | WARNING | Line exceeds 120 characters; contains 162 characters
  75 | WARNING | Line exceeds 120 characters; contains 124 characters
 102 | WARNING | Line exceeds 120 characters; contains 168 characters
 108 | WARNING | Line exceeds 120 characters; contains 121 characters
----------------------------------------------------------------------

To ignore those warnings, we can add // phpcs:ignore as a comment to the end of a (too long) line. For example:

<?php
$message = 'This is my extreeeeeeeeeeeeeeeeeeeeeeeeeeeeeemly long message.'; // phpcs:ignore

Another posibility is to add the comment // @codingStandardsIgnoreLine on the line in question:

<?php
$message = 'This is my extreeeeeeeeeeeeeeeeeeeeeeeeeeeeeemly long message.'; // @codingStandardsIgnoreLine

If you want to ignore the warning for multiple lines in a file, you can add the following comments around the lines:

<?php
// @codingStandardsIgnoreStart
$message = 'This is my extreeeeeeeeeeeeeeeeeeeeeeeeeeeeeemly long message.';
// @codingStandardsIgnoreEnd

Another way to ignore the “Line exceeds” warning is to use phpcs.xml file and set the rule maxLineLength to the desired value:

<rule ref="PSR2.ControlStructures.ControlStructureSpacing">
    <properties>
        <property name="maxLineLength" value="120" />
    </properties>
</rule>

It’s worth noting that while ignoring warnings can be useful in some cases, it’s generally a better practice to address the underlying issues that are causing the warnings, as they can indicate potential problems in your code.

PNG – deactivate interlace to avoid ‘libpng warning: Interlace handling should be turned on when using png_read_image’

I stumbled appon a warning message that was thrown by PHP when handling images with GD lib (e.g. imagecreatefrompng()). The message shown was:

libpng warning: Interlace handling should be turned on when using png_read_image

This message even exists, when deactivating ‘interlace’ with the help of:

imageinterlace($img, false);

The point is that this message is not caused by any wrong php code, it is caused by the processed images itself. The only solution is to deactivate interlace for the processed image(s). This is possible with ImageMagick. To deactivate interlace on all images of a folder, the following command can be used:

magick mogrify -interlace none *.png

I used ImageMagick on macos and installed it with with HomeBrew:

brew install imagemagick

PHP ColorUtils

A neat collection of useful methods to convert colors between different color spaces is available on GitHub (MIT License). It can convert any values between RGB, HSL, CMYK, YUV and HEX colors.

I created a ready-to-use php class out of this method collection:

https://github.com/mixable/color-utils

Usage

The methods itself are mostly self-explaining. To use the class, just include the php file into your script and you are ready to go:

<?php
require('ColorUtils.php');

The methods itself are static, they can be used like:

$hex = '#ffcc00';
$rgb = ColorUtils::hex2rgb($hex);

Which results in an array with three values (red, blue, green) in $rgb:

// [0 => 255, 1 => 204, 2 => 0]

Photo by Kelli Tungay on Unsplash