PHP Tips | 文字列処理:入力補助 - 文字種判定(英字/数字/記号)

PHP PHP
スポンサーリンク

何をしたいユーティリティなのか

「文字種判定(英字/数字/記号)」は、 ある文字列の中に「英字」「数字」「記号」がどれくらい含まれているか、 あるいは「この文字列は英字だけか?数字だけか?記号を含んでいるか?」を判定するためのユーティリティです。

パスワードチェック、ユーザー名のバリデーション、 入力制限(英数字のみ/記号禁止/記号必須など)で、ほぼ必ず出番があります。

基本方針:1 文字ずつ「何者か」を調べる

「文字列全体」ではなく「1 文字単位」で見る

文字種判定の考え方はシンプルで、

  1. 文字列を 1 文字ずつ見る
  2. その文字が「英字か」「数字か」「記号か」を判定する
  3. 必要に応じてカウントしたり、フラグを立てたりする

という流れになります。

PHP には「文字種判定」に向いた関数群(ctype 系)が用意されていて、 これを使うと初心者でも読みやすいコードで書けます。

ctype 系関数で文字種を判定する

よく使う 3 種類

代表的なものはこのあたりです。

ctype_alpha($ch); // 英字かどうか
ctype_digit($ch); // 数字かどうか
ctype_punct($ch); // 記号(英数字・空白以外の印字可能文字)かどうか
PHP

これらは「引数が 1 文字の文字列」であるとき、 その文字がそのカテゴリに属しているかどうかを true/false で返してくれます。

ポイントは、「ASCII ベースの判定」であることです。 英字は A〜Z / a〜z、数字は 0〜9、記号は一般的な記号類が対象になります。

1 文字を分類する小さな関数

まずは「1 文字を英字/数字/記号のどれかに分類する」関数を作ってみます。

/**
 * 1 文字を「英字」「数字」「記号」「その他」に分類する
 */
function classify_char(string $ch): string
{
    // 1 文字でない場合は「その他」
    if (strlen($ch) !== 1) {
        return 'other';
    }

    if (ctype_alpha($ch)) {
        return 'alpha'; // 英字
    }

    if (ctype_digit($ch)) {
        return 'digit'; // 数字
    }

    if (ctype_punct($ch)) {
        return 'symbol'; // 記号
    }

    return 'other'; // 空白や日本語など
}
PHP

ここでの重要ポイントは、「その他」をちゃんと用意していることです。

  • 英字でも数字でも記号でもないもの(空白、日本語、絵文字など)は other
  • 判定対象外のものを無理にどれかにねじ込まない

という方針にしておくと、後の処理が分かりやすくなります。

文字列全体の「文字種」を集計する

英字・数字・記号の個数を数える

次に、「文字列全体で何文字が英字/数字/記号なのか」を数えるユーティリティを作ります。

/**
 * 文字列中の「英字」「数字」「記号」「その他」の個数を数える
 */
function count_char_types(string $text): array
{
    $alpha = 0;
    $digit = 0;
    $symbol = 0;
    $other = 0;

    $len = strlen($text);

    for ($i = 0; $i < $len; $i++) {
        $ch = $text[$i];

        if (ctype_alpha($ch)) {
            $alpha++;
        } elseif (ctype_digit($ch)) {
            $digit++;
        } elseif (ctype_punct($ch)) {
            $symbol++;
        } else {
            $other++;
        }
    }

    return [
        'alpha'  => $alpha,
        'digit'  => $digit,
        'symbol' => $symbol,
        'other'  => $other,
    ];
}
PHP

ここでの重要ポイントは、「1 文字ずつループして、分類しながらカウントしている」ことです。 この形にしておくと、あとで「英字が 1 文字以上あるか」「記号が 2 文字以上あるか」などの条件を簡単に書けます。

例題で挙動を確認する

$text = 'Abc123!@';

$result = count_char_types($text);

var_dump($result);
PHP

出力イメージはこうなります。

array(4) {
  ["alpha"]  => int(3) // A, b, c
  ["digit"]  => int(3) // 1, 2, 3
  ["symbol"] => int(2) // !, @
  ["other"]  => int(0)
}
PHP

この結果を見れば、「英字も数字も記号も含まれている」ことが一目で分かります。

実務での使いどころ

パスワード強度チェック

よくある要件として、「英字・数字・記号をそれぞれ少なくとも 1 文字含める」というものがあります。

さっきの count_char_types を使うと、こう書けます。

$password = $_POST['password'] ?? '';

$types = count_char_types($password);

$hasAlpha  = $types['alpha']  > 0;
$hasDigit  = $types['digit']  > 0;
$hasSymbol = $types['symbol'] > 0;

if (!($hasAlpha && $hasDigit && $hasSymbol)) {
    $error = '英字・数字・記号をそれぞれ 1 文字以上含めてください。';
}
PHP

「何文字あるか」を数えているので、 「最低 2 文字以上」などの条件にも簡単に拡張できます。

ユーザー名のバリデーション(英数字のみ/記号禁止)

ユーザー名を「英数字だけにしたい」「記号は禁止したい」というケースもよくあります。

$username = $_POST['username'] ?? '';

$types = count_char_types($username);

if ($types['symbol'] > 0) {
    $error = 'ユーザー名に記号は使用できません。';
}

if ($types['other'] > 0) {
    $error = 'ユーザー名は英字と数字のみ使用できます。';
}
PHP

「記号が 1 文字でも含まれていたら NG」「その他(日本語など)が含まれていたら NG」といったルールを、素直なコードで書けます。

正規表現で「文字種をまとめて判定する」パターン

「全部英数字か?」を一発で見る

「この文字列は全部英数字か?」だけを見たい場合は、正規表現で一発判定する方法もあります。

/**
 * 文字列が「英字と数字だけ」で構成されているかを判定する
 */
function is_alnum_string(string $text): bool
{
    // 空文字を許すかどうかは要件次第
    if ($text === '') {
        return false;
    }

    return (bool)preg_match('/^[A-Za-z0-9]+$/', $text);
}
PHP

^[A-Za-z0-9]+$ は、

  • 先頭から末尾まで
  • 英字(A〜Z, a〜z)と数字(0〜9)だけ
  • 1 文字以上

という意味になります。

例:

var_dump(is_alnum_string('Abc123'));   // true
var_dump(is_alnum_string('Abc123!'));  // false(! が入っている)
var_dump(is_alnum_string('山田123'));  // false(日本語が入っている)
PHP

「文字列全体が英数字だけか」を見るには、この形が分かりやすいです。

まとめ:今日からの「文字種判定(英字/数字/記号)」ユーティリティ

文字種判定の本質は、「文字列の中身を“何者か”で分類して、ルールに沿って扱えるようにする」ことです。

そのために、

  • ctype_alpha / ctype_digit / ctype_punct で 1 文字ずつ分類する
  • 文字列全体をループして、英字・数字・記号・その他の個数を数える
  • その結果を使って「英字を含むか」「数字を含むか」「記号を禁止するか」などの条件を書く
  • 必要に応じて、正規表現で「全体が英数字だけか」を一発判定する

という形のユーティリティを用意しておくと、 入力チェックやパスワード強度判定、ユーザー名バリデーションなどが、ぐっと書きやすくなります。

最後に、いちばん汎用的な集計関数をもう一度載せておきます。

function count_char_types(string $text): array
{
    $alpha = 0;
    $digit = 0;
    $symbol = 0;
    $other = 0;

    $len = strlen($text);

    for ($i = 0; $i < $len; $i++) {
        $ch = $text[$i];

        if (ctype_alpha($ch)) {
            $alpha++;
        } elseif (ctype_digit($ch)) {
            $digit++;
        } elseif (ctype_punct($ch)) {
            $symbol++;
        } else {
            $other++;
        }
    }

    return [
        'alpha'  => $alpha,
        'digit'  => $digit,
        'symbol' => $symbol,
        'other'  => $other,
    ];
}
PHP

ここから先は、「あなたのシステムでどんな文字を許したいか/禁止したいか」に合わせて、 条件を足していくだけです。

タイトルとURLをコピーしました