構文:substr(string $string, int $start, ?int $length = null): string|false
// 基本例
substr("Hello, World!", 7); // "World!"
substr("Hello, World!", 7, 5); // "World"
substr("Hello, World!", -6); // "orld!" ← 末尾から
PHPのsubstr()関数は、文字列の一部を切り出すための組み込み関数です。先頭・末尾・任意の位置からの切り出し、長さ指定など、文字列操作の基本として頻繁に使います。ただし日本語(マルチバイト文字)にはmb_substr()を使う必要があります。この記事では構文・よく使うパターン・日本語対応・他関数との使い分けまで網羅します。
PHPで文字列を切り出す方法
PHPで文字列を切り出す主な方法は5種類あります。目的に合わせて使い分けてください。
| 目的 | 関数 | 特徴 |
|---|---|---|
| 文字数で切り出す(英数字) | substr() |
バイト単位処理。ASCII文字・バイト列の操作に適する |
| 文字数で切り出す(日本語) | mb_substr() |
文字単位処理。日本語を含む文字列に必須 |
| 区切り文字で分ける | explode() |
CSV・パス・URLなど区切り文字がある場合 |
| パターンで抜き出す | preg_match() |
正規表現で複雑なパターンを抽出する場合 |
| 先頭・末尾の文字を削る | trim() / ltrim() / rtrim() |
空白や指定した文字を先頭・末尾から除去 |
⚠️ 日本語を扱う場合は substr() ではなく mb_substr() を使ってください。substr() はバイト単位で処理するため、UTF-8の日本語文字(1文字3バイト)が文字化けします。
substr関数とは?
PHPのsubstr()は文字列の一部を返す組み込み関数です。
substr(string $string, int $start, ?int $length = null): string|false
引数の詳細
| 引数 | 型 | 必須 | 説明 |
|---|---|---|---|
$string |
string | 必須 | 操作対象の文字列 |
$start |
int | 必須 | 切り出し開始位置(0始まり)。負の値は末尾から数える |
$length |
int|null | 任意 | 切り出す文字数。省略すると末尾まで。負の値は末尾から除外する文字数 |
$start と $length の動作まとめ
| パターン | 例 | 結果 | 説明 |
|---|---|---|---|
| 正の $start | substr("abcdef", 2) |
"cdef" |
先頭から2文字目以降 |
| 負の $start | substr("abcdef", -2) |
"ef" |
末尾から2文字目以降 |
| 正の $length | substr("abcdef", 1, 3) |
"bcd" |
1文字目から3文字分 |
| 負の $length | substr("abcdef", 0, -2) |
"abcd" |
末尾2文字を除いた部分 |
| $start が範囲外 | substr("abc", 10) |
false |
PHP 8.0以降は空文字列 "" |
よく使うパターン
先頭から切り出す
$text = "PHP is great!";
// 先頭から3文字
echo substr($text, 0, 3); // "PHP"
// 先頭から7文字目以降すべて
echo substr($text, 7); // "great!"
末尾から切り出す
$text = "Hello, World!";
// 末尾6文字を取得
echo substr($text, -6); // "orld!"
// 末尾から1文字を除いた部分
echo substr($text, 0, -1); // "Hello, World"
指定文字数だけ取得する(中間切り出し)
$text = "2025-08-19";
$year = substr($text, 0, 4); // "2025"
$month = substr($text, 5, 2); // "08"
$day = substr($text, 8, 2); // "19"
拡張子を取得する
$filename = "report.pdf";
// 最後のドット以降を取得
$ext = substr($filename, strrpos($filename, '.') + 1);
echo $ext; // "pdf"
// pathinfo() を使う方法(より堅牢)
echo pathinfo($filename, PATHINFO_EXTENSION); // "pdf"
一部をマスクする
$creditCard = "1234-5678-9012-3456";
// 先頭4桁と末尾4桁を残してマスク
$masked = substr($creditCard, 0, 4)
. str_repeat('*', strlen($creditCard) - 8)
. substr($creditCard, -4);
echo $masked; // "1234-****-****-3456"
// メールアドレスのドメイン前をマスク
$email = "user@example.com";
$atPos = strpos($email, '@');
$masked = str_repeat('*', $atPos) . substr($email, $atPos);
echo $masked; // "****@example.com"
ファイル名を取得する
$filepath = "/var/www/html/report_2025.pdf";
// basename() でファイル名部分を取得
$filename = basename($filepath);
echo $filename; // "report_2025.pdf"
// pathinfo() で拡張子なしのファイル名を取得
$nameOnly = pathinfo($filepath, PATHINFO_FILENAME);
echo $nameOnly; // "report_2025"
// substr で拡張子を除いたファイル名を取得
$ext = pathinfo($filepath, PATHINFO_EXTENSION);
$nameOnly = substr($filename, 0, -(strlen($ext) + 1));
echo $nameOnly; // "report_2025"
メールアドレスのローカルパート・ドメインを取得する
$email = "user@example.com";
// @ の位置を取得
$atPos = strpos($email, '@');
// ローカルパート(@ より前)
$localPart = substr($email, 0, $atPos);
echo $localPart; // "user"
// ドメイン(@ より後)
$domain = substr($email, $atPos + 1);
echo $domain; // "example.com"
文字数制限して表示する
// 日本語を含む場合は mb_substr() を使う
function truncate(string $text, int $maxLength, string $suffix = '...'): string {
if (mb_strlen($text) <= $maxLength) {
return $text;
}
return mb_substr($text, 0, $maxLength) . $suffix;
}
echo truncate("PHPで文字列を切り出す方法を学ぼう", 10); // "PHPで文字列を切り出す..."
echo truncate("Hello, World! This is PHP.", 13, '…'); // "Hello, World!…"
日本語文字列には mb_substr() を使う
substr()はバイト単位で文字列を処理するため、日本語などのマルチバイト文字を扱うと文字化けや不正なバイト列が発生します。
$text = "こんにちは世界";
// NG: substr() は文字化けする
echo substr($text, 0, 3); // 文字化け(バイト単位のため)
// OK: mb_substr() は文字単位で処理
echo mb_substr($text, 0, 3); // "こんに"
echo mb_substr($text, -2); // "世界"
mb_substr() の構文
mb_substr(string $string, int $start, ?int $length = null, ?string $encoding = null): string
第4引数に文字コードを指定できます(省略時はmb_internal_encoding()の設定に従う)。
$text = "PHPで文字列操作";
echo mb_substr($text, 0, 3, 'UTF-8'); // "PHP"
echo mb_substr($text, 3, 4, 'UTF-8'); // "で文字列"
substr() / mb_substr() / explode() / preg_match() / trim() の使い分け
| 関数 | 用途 | 日本語対応 | 使うべき場面 |
|---|---|---|---|
substr() |
位置・長さ指定での切り出し | ×(バイト単位) | ASCII文字・バイト列の操作 |
mb_substr() |
位置・長さ指定での切り出し | ○(文字単位) | 日本語を含む文字列全般 |
explode() |
区切り文字で分割 | △ | CSV・パス分割など区切り文字がある場合 |
preg_match() |
パターンマッチ・抽出 | ○(uフラグ) | 複雑なパターンや複数の候補がある場合 |
trim() / ltrim() / rtrim() |
先頭・末尾の文字を削除 | ○ | 空白や指定文字を先頭・末尾から除去したい場合 |
使い分けの例
$path = "/var/www/html/index.php";
// substr: 位置が分かっているとき
echo substr($path, 1); // "var/www/html/index.php"
// explode: 区切り文字で分割したいとき
$parts = explode('/', $path);
echo end($parts); // "index.php"
// preg_match: パターンで抽出したいとき
preg_match('/\/([^\/]+)$/', $path, $matches);
echo $matches[1]; // "index.php"
関連関数:substr_replace() / substr_count()
substr()と合わせてよく使う関連関数にsubstr_replace()(部分置換)とsubstr_count()(出現回数カウント)があります。
substr_replace() — 指定位置の文字列を置換する
substr_replace(string|array $string, string|array $replace, int|array $offset, int|array|null $length = null): string|array
$text = "1234-5678-9012-3456";
// 先頭4桁を "****" に置換
echo substr_replace($text, "****", 0, 4); // "****-5678-9012-3456"
// 末尾4桁を置換(負のoffset)
echo substr_replace($text, "0000", -4); // "1234-5678-9012-0000"
substr()は「切り出す」だけですが、substr_replace()は「切り出した部分を別の文字列に差し替える」点が異なります。
substr_count() — 部分文字列の出現回数を数える
$text = "banana";
echo substr_count($text, "an"); // 2
文字の位置ではなく「何回登場するか」を知りたいときはsubstr_count()を使います。substr()で位置を割り出してからループで数える必要はありません。
関連記事
- PHP strpos関数を使って文字列内の位置を取得する方法 — 切り出す位置を検索したいときに使う関数です
- PHPのexplode関数を使った文字列分割の基本と応用テクニック — 区切り文字で分割したい場合はこちら
- mb_strlen — マルチバイト対応の文字数(コードポイント数)を取得 — 日本語の文字数カウントと組み合わせて使う
- PHPのstr_replace関数 — 文字列・配列を置換する使い方と実例 — 切り出した部分を別の文字列に置き換えたい場合はこちら
エラーハンドリングと注意点
substr()で$startが文字列の長さを超えた場合、PHP 7以前はfalse、PHP 8.0以降は空文字列""が返ります。
$text = "Hello";
// PHP 7以前: false が返る
// PHP 8.0以降: "" が返る
$result = substr($text, 10);
// 安全に扱う方法
if ($result === false || $result === '') {
echo "範囲外のインデックスが指定されました。";
}
FAQ
PHPで文字列を切り出すには?
PHPで文字列を切り出す基本は substr()(英数字)と mb_substr()(日本語)です。開始位置と文字数を指定して切り出します。区切り文字がある場合は explode()、パターンで抽出したい場合は preg_match() が向いています。
// 英数字の切り出し
echo substr("Hello, World!", 7, 5); // "World"
// 日本語の切り出し(mb_substr を使う)
echo mb_substr("PHPで文字列操作", 3, 4); // "で文字列"
// 区切り文字で分ける
$parts = explode(',', "php,python,ruby");
echo $parts[0]; // "php"
日本語を切り出すには?
日本語(マルチバイト文字)を切り出す場合は、必ず mb_substr() を使ってください。substr() はバイト単位で処理するため、UTF-8の日本語(1文字3バイト)を中途半端に切ると文字化けします。
$text = "日本語テスト";
// NG: substr() は文字化けする
echo substr($text, 0, 3); // 文字化け(1バイト目〜3バイト目 = "日"の途中まで)
// OK: mb_substr() は文字単位で処理
echo mb_substr($text, 0, 3); // "日本語"
echo mb_substr($text, -2); // "スト"(末尾2文字)
特定文字より前後を取得するには?
strpos() で対象文字の位置を取得し、substr() で前後を切り出します。日本語を含む場合は mb_strpos() と mb_substr() を組み合わせてください。
$text = "2025-08-19";
// "-" の位置を取得
$pos = strpos($text, '-');
// "-" より前を取得
$before = substr($text, 0, $pos);
echo $before; // "2025"
// "-" より後を取得
$after = substr($text, $pos + 1);
echo $after; // "08-19"
// メールアドレスのドメイン部分を取得
$email = "user@example.com";
$domain = substr($email, strpos($email, '@') + 1);
echo $domain; // "example.com"
まとめ
substr()関数のポイントをまとめます。
substr($string, $start, $length)で位置・長さを指定して文字列を切り出す- 負の
$startで末尾から数えた位置を指定できる - 負の
$lengthで末尾からN文字を除いた部分を取得できる - 日本語など多バイト文字には
mb_substr()を使う(substr()では文字化けする) - 区切り文字での分割は
explode()、パターンマッチにはpreg_match()が向いている
文字列操作の基本としてsubstr()とmb_substr()の違いを押さえておくことで、バグの少ないPHPコードが書けるようになります。

コメント