引数のタイプチェックを手軽にする

このへんみて自分もPHPで似たようなもの作ってみた。
PHPではオブジェクトや配列のタイプヒンティングはできるがプリミティブな型はタイプヒンティングできないようになっているので、それを解決するためのもの。

ソース

<?php

function param()
{
    $typelist = func_get_args();

    $trace = debug_backtrace();
    $args = $trace[1]['args'];

    foreach ($typelist as $i => $type) {
        if (!isset($args[$i])) throw new InvalidArgumentException();
        $arg = $args[$i];
        $type = strtolower($type);

        switch (true) {
        case $type === 'boolean' || $type === 'bool':
            if (!is_bool($arg)) throw new InvalidArgumentException("not {$type}");
            break;

        case $type === 'null':
            if (!is_null($arg)) throw new InvalidArgumentException("not {$type}");
            break;

        case $type === 'string' || $type === 'str':
            if (!is_string($arg)) throw new InvalidArgumentException("not {$type}");
            break;

        case $type === 'int':
            if (!is_int($arg)) throw new InvalidArgumentException("not {$type}");
            break;

        case $type === 'float':
            if (!is_float($arg)) throw new InvalidArgumentException("not {$type}");
            break;

        case $type === 'callable':
            if (!is_callable($arg)) throw new InvalidArgumentException("not {$type}");
            break;

        case $type === '*' || $type === '_':
            break;
        default:
            throw new Exception("unknown type({$type})");

        }
    }
}

使い方

順々に型名を指定するだけ。

<?php
// $sを$i回繰り返して表示する関数
function repeat($s, $i) {
    @param(str, int); // ←ここで引数の型を制限
    
    for (; $i > 0; $i--) echo $s;
}

repeat('hello world!', 5); // 5回 'hello world!' を表示
repeat('hello world!', 'h'); // 二番目の引数がparam関数で指定した型とは違うので例外出る

// 特定の引数だけチェックしないこともできる
function procedure($first, $second) {
    @param(_, int); // ←'_'を指定することで一つ目の引数はチェックはされない

    // 何らかの処理
}

指定できる型一覧

  • string
  • str
  • int
  • float
  • null
  • boolean
  • bool
  • _ (←チェックしないことを指定する)

簡単ですね