フォームからの入力値、CSVファイルの読み込み、外部APIのレスポンスなど、文字列を扱う場面では「前後に意図しない空白が入っている」というトラブルが頻繁に発生します。そんなときに真っ先に使われるのが trim() 関数です。
シンプルな関数に見えますが、第2引数を使った高度な使い方や、見落としがちな注意点も多くあります。この記事では trim() の基本から実践的な活用パターン、関連関数との違いまで詳しく解説します。
関数概要
| 項目 | 内容 |
|---|---|
| 関数名 | trim() |
| 読み方 | トリム |
| 分類 | 文字列関数 |
| 対応バージョン | PHP 4以降(全バージョンで使用可能) |
| 引数 | 対象文字列(必須)、除去する文字セット(省略可) |
| 戻り値 | string(トリム後の文字列) |
| 名前空間 | グローバル関数 |
| 関連拡張モジュール | 標準で組み込み(拡張モジュール不要) |
構文
trim(string $string, string $characters = " \n\r\t\v\x00"): string
trim() は文字列の 先頭と末尾 から、指定した文字(省略時は空白系の文字)を取り除いた新しい文字列を返します。元の文字列の中身(先頭・末尾以外)は変更されません。
デフォルトで除去される文字は以下の5種類です。
| 文字 | 意味 |
|---|---|
" " | 半角スペース |
"\n" | 改行(ラインフィード) |
"\r" | キャリッジリターン |
"\t" | タブ |
"\v" | 垂直タブ |
"\x00" | NULLバイト |
基本的な使い方
<?php
$str = " こんにちは、PHP! ";
$trimmed = trim($str);
echo "[" . $trimmed . "]" . PHP_EOL;
実行結果:
[こんにちは、PHP!]
前後の半角スペースだけが取り除かれ、文字列内部の構造はそのまま保たれていることがわかります。
処理イメージ図
入力: " Hello, World! \n"
▲▲▲ ▲▲▲▲
└─ 先頭の空白類 └─ 末尾の空白・改行
▼ trim()
出力: "Hello, World!"
(前後の空白・改行のみ除去。中身はそのまま)
文字列の 真ん中 にある空白は対象外という点が重要です。"Hello World" のように単語間に余分な空白がある場合、trim() では除去できません(これは後述の preg_replace() などで対応します)。
実践的なコード例
例1:フォーム入力値のクリーニング
<?php
class FormInputCleaner
{
public function clean(array $formData): array
{
$cleaned = [];
foreach ($formData as $key => $value) {
$cleaned[$key] = is_string($value) ? trim($value) : $value;
}
return $cleaned;
}
}
$cleaner = new FormInputCleaner();
$rawInput = [
'name' => ' 山田 太郎 ',
'email' => ' yamada@example.com ',
'age' => 28,
];
$cleaned = $cleaner->clean($rawInput);
foreach ($cleaned as $key => $value) {
echo "{$key}: [{$value}]" . PHP_EOL;
}
実行結果:
name: [山田 太郎]
email: [yamada@example.com]
age: [28]
Webフォームの入力値は、ユーザーが意図せずスペースを含めてしまうことが多いため、バリデーション前に trim() を通すのが定石です。
例2:第2引数を使ったカスタム文字の除去
<?php
class CustomTrimmer
{
public function trimSymbols(string $str): string
{
// 空白だけでなく、記号類もまとめて除去する
return trim($str, " \t\n\r\0\x0B-_*#");
}
}
$trimmer = new CustomTrimmer();
$samples = [
"---重要なお知らせ---",
"***注目***",
" __タイトル__ ",
];
foreach ($samples as $sample) {
echo "[" . $trimmer->trimSymbols($sample) . "]" . PHP_EOL;
}
実行結果:
[重要なお知らせ]
[注目]
[タイトル]
第2引数に除去対象の文字を文字列として指定することで、空白以外の記号もまとめて取り除くことができます。
例3:CSVファイル読み込み時のデータクリーニング
<?php
class CsvRowCleaner
{
public function cleanRow(array $row): array
{
return array_map(fn($field) => trim($field), $row);
}
}
$cleaner = new CsvRowCleaner();
// CSVから読み込んだ直後を想定(タブや改行が混在しやすい)
$rawRow = [" 山田太郎 ", "30\r\n", " 東京都\t"];
$cleaned = $cleaner->cleanRow($rawRow);
foreach ($cleaned as $i => $value) {
echo "カラム{$i}: [{$value}]" . PHP_EOL;
}
実行結果:
カラム0: [山田太郎]
カラム1: [30]
カラム2: [東京都]
CSVファイルは改行コードの混在(\r\n と \n)が原因で末尾に見えない文字が残ることが多く、trim() での清掃が欠かせません。
例4:URLパスの先頭・末尾のスラッシュを除去する
<?php
class UrlPathNormalizer
{
public function normalize(string $path): string
{
return trim($path, '/');
}
public function buildUrl(string $base, string $path): string
{
return rtrim($base, '/') . '/' . $this->normalize($path);
}
}
$normalizer = new UrlPathNormalizer();
echo $normalizer->normalize('/users/123/') . PHP_EOL;
echo $normalizer->buildUrl('https://example.com/', '/api/users/') . PHP_EOL;
実行結果:
users/123
https://example.com/api/users
URLパスの結合処理では、スラッシュの重複や欠落を防ぐために trim()(および片側のみを対象とする rtrim()/ltrim())がよく使われます。
例5:多階層データの再帰的なトリム処理
<?php
class RecursiveTrimmer
{
public function trimDeep(mixed $data): mixed
{
if (is_string($data)) {
return trim($data);
}
if (is_array($data)) {
return array_map(fn($item) => $this->trimDeep($item), $data);
}
return $data;
}
}
$trimmer = new RecursiveTrimmer();
$nested = [
'user' => [
'name' => ' 鈴木一郎 ',
'tags' => [' PHP ', ' Web開発 ', ' 初心者 '],
],
'count' => 5,
];
$result = $trimmer->trimDeep($nested);
print_r($result);
実行結果:
Array
(
[user] => Array
(
[name] => 鈴木一郎
[tags] => Array
(
[0] => PHP
[1] => Web開発
[2] => 初心者
)
)
[count] => 5
)
JSON形式のAPIレスポンスなど、ネストした配列構造の文字列をまとめてクリーニングしたい場合は、このような再帰処理が便利です。
例6:パスワードや機密情報の末尾に潜む見えない文字を検出
<?php
class HiddenCharacterDetector
{
public function detect(string $original): array
{
$trimmed = trim($original);
$hasHiddenChars = ($original !== $trimmed);
return [
'original_length' => strlen($original),
'trimmed_length' => strlen($trimmed),
'has_hidden_chars' => $hasHiddenChars,
];
}
}
$detector = new HiddenCharacterDetector();
// コピペ時にうっかり改行が混入したケースを想定
$password = "MySecurePass123\n";
$result = $detector->detect($password);
print_r($result);
実行結果:
Array
(
[original_length] => 16
[trimmed_length] => 15
[has_hidden_chars] => 1
)
パスワード認証で「コピペした値の末尾に改行が混入していてログインできない」という不具合は実際によく起こります。trim() の前後で長さを比較することで、こうした見えない文字の混入を検出できます。
注意:パスワード自体に意図的な前後スペースが含まれる設計の場合、安易に
trim()を適用すると正規のパスワードが変わってしまう点には注意してください。
例7:複数行テキストの各行をトリムして整形する
<?php
class MultilineTextFormatter
{
public function formatLines(string $text): string
{
$lines = explode("\n", $text);
$trimmedLines = array_map('trim', $lines);
// 空行になった行は除去する
$filtered = array_filter($trimmedLines, fn($line) => $line !== '');
return implode("\n", $filtered);
}
}
$formatter = new MultilineTextFormatter();
$rawText = " 1行目 \n\n 2行目\t\n \n3行目 ";
echo $formatter->formatLines($rawText);
実行結果:
1行目
2行目
3行目
ユーザーが投稿したテキストエリアの内容を整形する際など、各行ごとにトリムしつつ余分な空行を除去するパターンです。
関連関数との比較
| 関数 | 除去する位置 | デフォルトの除去文字 |
|---|---|---|
trim() | 先頭と末尾の両方 | 空白系の文字(スペース、改行、タブ等) |
ltrim() | 先頭のみ(left trim) | 空白系の文字 |
rtrim() / chop() | 末尾のみ(right trim) | 空白系の文字 |
str_replace() | 文字列中のどこでも | 指定文字(位置の制約なし) |
preg_replace() | 正規表現にマッチする箇所すべて | 正規表現パターンで指定 |
mb_trim() | 先頭と末尾の両方(マルチバイト対応) | 空白系の文字(PHP 8.4以降) |
「先頭だけ」「末尾だけ」を処理したい場合は ltrim() / rtrim() を使います。また、文字列の中間にある余分な空白(例:"東京 都" の単語間スペース)を1つにまとめたい場合は trim() では対応できないため、preg_replace('/\s+/', ' ', $str) のような正規表現処理が必要になります。
よくある落とし穴・注意点
- 全角スペース(U+3000)は除去されない
trim()のデフォルトでは半角スペースや半角の制御文字しか対象になりません。日本語の文章でよく使われる**全角スペース「 」**は除去対象に含まれていないため、見た目には空白に見えてもtrim()では取り除けないことがあります。全角スペースも除去したい場合は、第2引数に明示的に追加するか、mb_trim()(PHP 8.4以降で導入)やpreg_replace('/^[\s ]+|[\s ]+$/u', '', $str)のような対応が必要です。<?php $str = " 全角スペースに囲まれた文字列 "; echo "[" . trim($str) . "]" . PHP_EOL; // 除去されない echo "[" . trim($str, " \t\n\r\0\x0B") . "]" . PHP_EOL; // 第2引数に全角スペースを追加実行結果:[ 全角スペースに囲まれた文字列 ] [全角スペースに囲まれた文字列] - 文字列中間の空白は除去されない 先述の通り、
trim()は先頭と末尾にのみ作用します。「単語間の余分なスペースを1つに統一したい」という要望はtrim()の役割ではないため、正規表現を使う関数と混同しないようにしましょう。 - 第2引数は「文字の集合」であり「文字列そのもの」ではない
trim($str, "abc")と書いた場合、これは「文字列abcを除去する」のではなく「a、b、cのいずれかの文字を、前後から連続して取り除く」という意味になります。複数文字の並び(例:"abc"という並び順)をそのまま除去したいわけではない点に注意してください。 - PHP 8.1以降、null を渡すと非推奨警告(Deprecated)が出る PHP 8.1以降では、
trim()の第1引数にnullを渡すと非推奨警告が発生するようになりました(PHP 9.0での完全な型エラー化が予定されています)。データベースから取得した値などがnullになる可能性がある場合は、trim((string) $value)のように明示的にキャストするか、trim($value ?? '')のようにnull合体演算子で対処しましょう。<?php $value = null; echo trim($value ?? '') . PHP_EOL; // 安全な書き方 - バイト単位の処理であり、マルチバイト文字を破壊する可能性は低いが過信は禁物
trim()自体はマルチバイト文字(日本語など)の文字コードを内部で解釈するわけではなく、指定したバイト列を前後から取り除く処理です。通常のUTF-8の日本語テキストに対して半角スペース等を除去する用途では問題になりませんが、第2引数にマルチバイト文字を含む複雑な文字セットを指定する場合は挙動を必ず確認しましょう。
まとめ
| ポイント | 内容 |
|---|---|
| 役割 | 文字列の先頭・末尾から指定した文字(デフォルトは空白類)を除去する |
| 引数 | 第1引数:対象文字列(必須)、第2引数:除去する文字セット(省略可) |
| 戻り値 | string型のトリム後の文字列 |
| 対象範囲 | 先頭と末尾のみ(文字列中間は対象外) |
| 全角スペース | デフォルトでは除去されないため要注意 |
| よく組み合わせる関数 | ltrim(), rtrim(), preg_replace() |
| 主な用途 | フォーム入力の整形、CSV/API応答のクリーニング、URLパス結合 |
| 注意点 | 全角スペース未対応、null非推奨警告(PHP 8.1+)、中間の空白は非対象 |
trim() は一見単純な関数ですが、フォーム処理・データインポート・API連携など、文字列を外部から受け取るあらゆる場面で「最初の防衛線」として機能します。全角スペースの扱いや null の非推奨警告など、地味ながら実務で踏みやすい落とし穴を押さえておくことで、より堅牢なコードを書けるようになります。
