PHP7.4からPHP8.1までの新機能をキャッチアップ

PHP

アプリケーション

2022-03-21 23:01:33

概要

PHPの知識が7.3から止まっているので8.1までの新機能を駆け足でキャッチアップする。

PHP 7.3.x - PHP 7.4.x

新機能

型付きプロパティ

<?php
    class Person {
        public int $age; // 指定の型だけ代入できるように強制される
        public string $name;
    }

?>

アロー関数

<?php
// これが
$a = 1
$func_7_3 = function($b) use ($a) {
    return $a + $b;
}
echo $func_7_3(1); // 2

// 7.4からはこのように書ける
$func_7_4 = fn($b) => $a + $b; // 暗黙的な値スコープを持つ
echo $func_7_4(1); // 2

?>

Null合体代入演算子

<?php
// これが
$name = isset($name) $name : getName();

// 7.4からはこのように書ける
$name ??= getName();
?>

配列内でのアンパック

<?php
$values = ['a', 'b'];
$all = [...$values, 'c']; // a, b, c
?>

FFI(Foreign Function Interface)

PHPから別言語を呼び出せる。
Goのcgoみたいなやつ。

preload

opcacheにスクリプトを事前ロードする機能が追加された。

// php.ini
opcache.preload=preload.php

PHP 7.4.x - PHP 8.0.x

新機能

名前付き引数

<?php
function namedFunc($foo, $bar, $baz) {
  echo $foo . $bar . $baz;
}

// 引数の順番は関係なく、名前付きで引数をセットできる
namedFunc(baz: "baz", foo: 'foo', bar: "bar"); // bazfoobar
?>

アトリビュート

アノテーションの新機能。

<?php
#[Attribute]
class Person
{
  public $name;

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

#[Person(name: "John")]
class Man
{
}

// Reflection APIでアトリビュートにアクセスできる
function output($reflection) {
  foreach ($reflection->getAttributes() as $attribute) {
    var_dump($attribute->getName());
    var_dump($attribute->getArguments());
    var_dump($attribute->newInstance());
  }
}


output(new ReflectionClass(Man::class));
// string(6) "Person"
// array(1) {
//   'name' =>
//   string(4) "John"
// }
// class Person#3 (1) {
//   public $name =>
//   string(4) "John"
// }
?>

union型

引数、戻り地、プロパティに対してunion型を宣言できるようになった。

<?php
function unionFunc(int|string $value): int|string
  return $value;
}

unionFunc(1);
unionFunc("Hello World");
?>

match式

<?php
function matchFunc($value) {
    // switch文とは異なり、厳密な比較(===)となる
    return match($value) {
        "one" => 1,
        "two" => 2,
        "three" => 3,
    };
};

echo matchFunc("one"); // 1
?>

nullsafe演算子

null安全なコードが書きやすくなる。

<?php
class User
{
  public $name;

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

  public function getName()
  {
    return $this->name;
  }
}

class Account
{
  public User|null $user = null;
}

$account = new Account();
// $account->user->getName(); // PHP Fatal error:  Uncaught Error: Call to a member function getName() on null
$account->user?->getName();
?>

PHP 8.0.x - PHP 8.1.x

新機能

文字列をキーとして持つ配列のアンパック

<?php
    $a1 = ["a" => 1];
    $a2 = ["a" => 2];
    var_dump(["a"=>0, ...$a1, ...$a2]); // ["a" => 2] キーは後勝ちになるっぽい。
?>

列挙型

<?php
enum ColorCode: string
{
  case BLUE = "#0000ff";
  case YELLOW = "#ffff00";
  case RED = "#ff0000";
}

function enumFunc(ColorCode $color) {
  echo $color->name; 
  echo $color->value; 
}

enumFunc(ColorCode::BLUE); // BLUE blue
// enumFunc("green"); // PHP Fatal error:  Uncaught TypeError: enumFunc(): Argument #1 ($color) must be of type ColorCode, string given
?>

Fibers

完全なスタックを持つ、停止可能な関数。コールスタックのどこからでも停止・再開が可能。
非同期処理が書ける。

交差型

unionが型のORなら、交差型は型のAND。

<?php
function check(Foo&Bar $intersection)
{
  return;
}

class Foo{}
class Bar{}
class Baz{}


$foo = new Foo();
$foo->check(new Foo());
$foo->check(new Bar());
// $foo->check(new Baz()); // PHP Fatal error:  Uncaught Error: Call to undefined method Foo::check() 
?>

never型

戻り値にのみ指定できる型。関数がexit()するか例外を投げるか終了しないかを示す。
voidとは違う。

所感

どんどん型を意識したコードが書きやすくなってきている印象。
下位互換性は流し読みしかしていないのでアプデ対応のときでも再度読み直したい。

参考

About the author

Image

bmf san @bmf_san
A web developer in Japan.