【PHP】PHP8.3リリース

  • 2023年11月24日
  • PHP

 PHP8.3がリリースされました。PHP8.3のEOLは2026-11-23です。PHP8.0のEOLは2023-11-26と差し迫っています。おすすめのリリース内容のまとめが次リンクです。

PHP: PHP 8.3.0 Release Announcement
【PHP8.3】PHP8.3の新機能 #PHP – Qiita

 移行ガイドは次です。

PHP: PHP 8.2.x から PHP 8.3.x への移行 – Manual
 

 私的に気になった点を紹介します

mb_str_pad

PHP: mb_str_pad – Manual

 マルチバイト文字の文字列埋めがやりやすくなりました。以前は次のようにバイト長と文字列長が合わなかったため、str_padをそのまま日本語に使うと不具合の原因となりました。次のように使えます。

<?php

$char = 'あ';
$padded = str_pad($char, 6, 'い', STR_PAD_LEFT);
var_dump($padded); // string(6) "いあ"

$padded = mb_str_pad($char, 6, 'い', STR_PAD_LEFT);
var_dump($padded);
// string(18) "いいいいいあ"

$padded = mb_str_pad($char, 6, '👨🏻‍🦱', STR_PAD_RIGHT);
// string(22) "あ👨🏻‍🦱👨"

 ひらがなについていい感じに動いています。注意点として通常のマルチバイト文字対応のみで絵文字などの合字に使えない点があります。絵文字に使うと上記の顔文字の様に崩れます。絵文字に使う場合はgrapheme_strlenを元に自前でstr_pad相当を実装することになります。
PHP: grapheme_strlen – Manual

文字列からクラス定数を取得

 次のようにクラス名::{任意の文字列}というコードでクラス定数を得られるようになりました。

<?php

class Foo
{
    const PHP = 'PHP 8.3';
}

$searchableConstant = 'PHP';

var_dump(Foo::{$searchableConstant});
// string(7) "PHP 8.3"

 特筆すべきはこれによりEnumが使いやすくなったことです。以前は次のように書いていましたが、

enum State: string
{
    case INIT      = '初期';
    case COMPLETED = '完了';
    public static function find(string $key): ?self
    {
        return match ($key) {
            'INIT'      => self::INIT,
            'COMPLETED' => self::COMPLETED,
            default     => null,
        };
    }
}
$key = 'INIT';
echo State::find($key)->value;// 初期

// あるいは

trait Findable
{
    /**
     * foreach で線形探索するパターンです。
     */
    public static function findByForeach(string $key): ?static
    {
        foreach(static::cases() as $enum) {
            if($enum->name === $key) {
                return $enum;
            }
        }
 
        return null;
    }
}
 
enum State: string
{
    use Findable;
 
    case INIT = '初期';
    case COMPLETED = '完了';
 
}
 
$key = 'INIT';
echo State::findByForeach($key)->value;// 初期

 PHP8.3からは次のように書けます。

<?php

enum State: string
{
    case INIT = '初期';
    case COMPLETED = '完了';
}
// 存在するものを読むときは今までより大分楽になりました。
$key = 'INIT';
var_dump(State::{$key}->value);// string(6) "初期"
// 存在しない場合に null を返すのはちょっと手間です。
// これは State::{$key} 時点で Fatal error: Uncaught Error: Undefined constant が発生するためです。
// ?? で存在しないなら null としたいのですが、そうしてもエラーが発生します。
// もし存在しない場合はnullを返すようにするのであれば、次のような関数を用意するのが良さそうです。
$key = 'NOT_EXIST';
$getter = function(string $enum, $key) {
    try {
        return $enum::{$key}->value;
    } catch (\Throwable $e) {
        return null;
    }
};
var_dump($getter(State::class,$key));// NULL

 その場でPHPの機能だけで書けるようになるため扱いやすく、しかも高速です。

ランダム文字列生成

PHP: Random\Randomizer::getBytesFromString – Manual
 ランダムな文字列を生成する機能がPHP組み込みの関数に追加されました。random_bytesをbase64して切り詰めたり伸ばしたりや外部ライブラリを使ったりする必要がなくなりました。あくまでバイト単位でのランダムなため日本語にたいしてそのまま使うべきではありません。

<?php
// @see https://www.php.net/manual/ja/random-randomizer.getbytesfromstring.php
// $randomDomainについてのコードは ↑ から引用しました。

// A \Random\Engine may be passed for seeding,
// the default is the secure engine.
$randomizer = new \Random\Randomizer();

$randomDomain = sprintf(
    "%s.example.com",
    $randomizer->getBytesFromString(
        'abcdefghijklmnopqrstuvwxyz0123456789',
        16,
    ),
);
var_dump($randomDomain);
//string(28) "hiqsw02bg93s8ycd.example.com"

// rangeを使うと使う文字列の範囲がわかりやすく、漏れもおこしにくくなります。
$randomChars = implode('',[...range(0, 9),...range('A', 'Z'), ...range('a', 'z')]);
var_dump($randomChars);
// string(62) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
var_dump($randomizer->getBytesFromString($randomChars, 16));
// string(16) "u1rhHuWZV87eOdhy"

// Bytesの名前が示す通り、バイト単位でのランダムのため日本語をそのまま使うと文字化けします。
var_dump($randomizer->getBytesFromString('あいうえお', 16));
// string(16) "���ぁ���め���"

// 日本語を使う場合は配列の要素からランダムに選んでつなげる必要があります。
$randomChars = ['あ', 'い', 'う', 'え', 'お'];
$randomCharsLastIdx = count($randomChars) - 1;
$result = '';
for ($i = 0; $i < 10; $i++) {
    $result .= $randomChars[$randomizer->getInt(0, $randomCharsLastIdx)];
}
var_dump($result);
// string(30) "えいあああえうあうう"


数値や数値形式の文字列以外に++や–を使うべきではない

 PHP: PHP 8.3.x で推奨されなくなる機能 – Manual#加算子/減算子 に対する変更

 数値らしいもの以外に++--を使うと非推奨の警告が出る様になりました。アルファベットは++は許されますが--は非推奨です。実際に動かすと次のコードのようになります。

<?php

$a = '1';
$a++;
var_dump($a); // int(2)
$a--;
var_dump($a); // int(1)
$b = 'a';
$b++;
var_dump($b); // string(1) "b"
$b--;
// Deprecated: Decrement on non-numeric string has no effect and is deprecated
var_dump($b); // string(1) "b"
$c = '';
$c++;
// Deprecated: Increment on non-alphanumeric string is deprecated
var_dump($c); // string(1) "1"
$d = '';
$d--;
// Deprecated: Decrement on empty string is deprecated as non-numeric
var_dump($d); // int(-1)
$d = 'あ';
$d++;
// Deprecated: Increment on non-alphanumeric string is deprecated
var_dump($d); // string(3) "あ"
$d--;
// Deprecated: Decrement on non-numeric string has no effect and is deprecated
var_dump($d); // string(3) "あ"

 数値以外の文字をずらすのであれば++--をやめてstr_incrementstr_decrementを使うべきというわけです。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG