PHP Tips | 文字列処理:実務向け便利系 - 複数行テキストを配列化

PHP PHP
スポンサーリンク

なぜ「複数行テキストを配列化」するのか

業務でよくあるのが、こんなテキストです。

山田太郎
佐藤花子
鈴木一郎

これを「1 行ずつ処理したい」「1 行ずつバリデーションしたい」「1 行ずつ DB に登録したい」となったとき、そのままでは扱いづらいですよね。
そこでやるのが、「複数行テキストを配列化する」——つまり、

[
    '山田太郎',
    '佐藤花子',
    '鈴木一郎',
]
PHP

のような形に変換することです。

やること自体は「改行で分割する」だけですが、実務では次のようなポイントをちゃんと押さえておく必要があります。

  • 改行コードの違い(\n / \r\n / \r
  • 空行をどう扱うか(残すか、捨てるか)
  • 前後の空白をどうするか

ここを最初にきちんと決めておくと、「後から地味に困る」を防げます。


改行コードの違いを吸収して「行ごと」に分割する

まずは「どんな改行でもちゃんと分割する」関数

複数行テキストを行ごとに分割する一番の基本は、「改行コードの違いを吸収する」ことです。
そのために、正規表現を使って「\r\n / \r / \n のどれでも区切りにする」ようにします。

/**
 * 複数行テキストを「行ごとの配列」に変換する(空行もそのまま残す)
 */
function text_to_lines(string $text): array
{
    if ($text === '') {
        return [];
    }

    // \r\n, \r, \n のどれでも分割
    $lines = preg_split('/\r\n|\r|\n/', $text);

    // preg_split は false を返す可能性があるので保険をかける
    if ($lines === false) {
        return [];
    }

    return $lines;
}
PHP

使い方の例です。

$text = "山田太郎\n佐藤花子\r\n鈴木一郎\r田中次郎";

$lines = text_to_lines($text);

var_dump($lines);
// array(4) {
//   [0]=> string(12) "山田太郎"
//   [1]=> string(12) "佐藤花子"
//   [2]=> string(12) "鈴木一郎"
//   [3]=> string(12) "田中次郎"
// }
PHP

ここでの重要ポイントは、「改行コードの種類を意識している」ことです。
explode("\n", $text) だけだと、\r\n\r が混ざったときに中途半端に残ってしまいます。


実務でよく使う「空行や空白をどう扱うか」のバリエーション

空行を捨てて、意味のある行だけ欲しい場合

ユーザーが入力した複数行テキストには、よく「空行」や「スペースだけの行」が紛れ込みます。
例えば、こんな感じです。

山田太郎

佐藤花子
   
鈴木一郎

これをそのまま配列にすると、空文字や空白だけの要素が混ざります。
「意味のある行だけ欲しい」場合は、トリム+フィルタをかけます。

/**
 * 複数行テキストを「トリム済みの行配列」に変換する(空行は除外)
 */
function text_to_non_empty_lines(string $text): array
{
    $lines = text_to_lines($text);

    $result = [];

    foreach ($lines as $line) {
        // 前後の空白を削除
        $trimmed = trim($line);

        // 空になった行はスキップ
        if ($trimmed === '') {
            continue;
        }

        $result[] = $trimmed;
    }

    return $result;
}
PHP

使い方の例です。

$text = "山田太郎\n\n佐藤花子\n   \n鈴木一郎";

$lines = text_to_non_empty_lines($text);

var_dump($lines);
// array(3) {
//   [0]=> string(12) "山田太郎"
//   [1]=> string(12) "佐藤花子"
//   [2]=> string(12) "鈴木一郎"
// }
PHP

ここでの重要ポイントは、「トリムしてから空行判定している」ことです。
スペースや全角スペースだけの行も、きちんと「空行」として扱えます。


例題:複数行のメールアドレス入力を配列にしてバリデーションする

ユースケースのイメージ

例えば、管理画面で「複数のメールアドレスを改行区切りで入力してください」というフォームがあるとします。

ユーザー入力例:

user1@example.com
user2@example.com

user3@example.com

これを 1 行ずつチェックして、
「正しいメールアドレスだけを配列にしたい」というケースです。

実装例

$raw = $_POST['emails'] ?? '';

$lines = text_to_non_empty_lines($raw);

$validEmails = [];
$invalidLines = [];

foreach ($lines as $i => $line) {
    if (filter_var($line, FILTER_VALIDATE_EMAIL)) {
        $validEmails[] = $line;
    } else {
        // 行番号を覚えておく(1 始まり)
        $invalidLines[] = $i + 1;
    }
}

if ($invalidLines) {
    echo 'メールアドレスの形式が不正な行があります: ' . implode(', ', $invalidLines);
} else {
    // $validEmails を使って処理を続行
}
PHP

ここでのポイントは、「複数行テキスト → 行配列 → 1 行ずつ検証」という流れが自然に書けていることです。
最初に「配列化」してしまえば、その後の処理は普通の配列処理として書けます。


もう一歩:行番号や元のテキストとの対応を意識する

行番号を一緒に持っておきたい場合

エラーメッセージで「何行目がダメか」を丁寧に出したい場合、
単に配列にするだけでなく、「行番号付き」で扱うのも手です。

/**
 * 行番号付きで複数行テキストを配列化する
 *
 * 戻り値の例:
 * [
 *   ['line_no' => 1, 'text' => '山田太郎'],
 *   ['line_no' => 2, 'text' => ''],
 *   ...
 * ]
 */
function text_to_lines_with_number(string $text): array
{
    $lines = text_to_lines($text);

    $result = [];

    foreach ($lines as $index => $line) {
        $result[] = [
            'line_no' => $index + 1,
            'text'    => $line,
        ];
    }

    return $result;
}
PHP

これを使えば、「2 行目の入力が不正です」のようなフィードバックを簡単に作れます。
業務システムでは、こういう「どこが悪いかを具体的に示す」ことが、ユーザー体験に直結します。


まとめ:今日からの「複数行テキストを配列化」ユーティリティ

大事なポイントを整理すると、こうなります。

複数行テキストを扱うときは、まず「改行コードの違いを吸収して行配列にする」。
空行や空白だけの行をどう扱うか(残すか捨てるか)を、用途ごとに決める。
配列化してしまえば、その後は普通の配列処理としてバリデーションや登録が書ける。

実務ユーティリティとして、まずはこの 2 本を持っておくとかなり便利です。

function text_to_lines(string $text): array
{
    if ($text === '') {
        return [];
    }

    $lines = preg_split('/\r\n|\r|\n/', $text);

    if ($lines === false) {
        return [];
    }

    return $lines;
}

function text_to_non_empty_lines(string $text): array
{
    $lines = text_to_lines($text);

    $result = [];

    foreach ($lines as $line) {
        $trimmed = trim($line);
        if ($trimmed === '') {
            continue;
        }
        $result[] = $trimmed;
    }

    return $result;
}
PHP

もし、あなたのコードのどこかで「explode("\n", $text) して、そのまま使っている」ような箇所があれば、そこがこのユーティリティに差し替えるポイントです。
改行コードの違いと空行の扱いをきちんと決めてあげるだけで、「現場で壊れにくいテキスト処理」に一気に近づきます。

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