substr($string, $offset, $length)は、$stringの位置$offset(0から数える)から始まる$length文字分の部分を返します。substr('Hello world', 0, 5)は"Hello"を返します。$lengthを省くと末尾までを取得します。
substr()はバイトを数えます。英語のテキストなら文字数と同じですが、日本語、中国語、絵文字、アクセント付きの文字では違います。それらには、下で紹介するmb_substr()を使います。
構文
substr(string $string, int $offset, ?int $length = null): string
$offsetは開始位置です。0が最初の文字で、負の値は末尾から数えます。$lengthは取り出すバイト数です(ASCIIだけのテキストなら1バイトが1文字)。負の値は末尾からその数だけ残します。null(または省略)は「末尾まで」の意味です。
負のオフセットと長さ:末尾から処理する
負の$offsetは文字列の末尾から数え始めるので、-1は最後の文字です。負の$lengthは、末尾からその文字数だけ手前で止まります。
substr($s, 0, -1)は、ループで残った末尾のカンマなど、最後の文字を取り除く定番の方法です。
最初や最後の文字を取得する
1バイトだけなら、文字列に直接添字でアクセスすることもできます。$s[0]が最初の文字で、PHP 7.1以降は$s[-1]が最後の文字です。
存在しない位置に添字でアクセスすると警告が出ますが、substr()は空文字列を返すだけです。文字列が空かもしれないならsubstr()を選びましょう。
範囲外:falseではなく空文字列
$offsetが文字列の末尾を超えていると、PHP 8のsubstr()は""を返します。PHP 7ではfalseを返していたので、=== falseで判定している古いコードはもう動きません。
日本語のテキスト:mb_substrを使う
UTF-8では、かなとよく使う漢字は1文字3バイトで保存されます(𠮷のような珍しい漢字や絵文字は4バイト)。substr()はバイトを数えるので、substr('こんにちは', 0, 3)はこしか返さず、文字の境界に当たらない長さだと文字が半分に切れて壊れたテキストになります。mb_substr()は同じ引数を受け取り、文字を数えます。
同じことが絵文字やéのようなアクセント付きの文字にも当てはまります。文字数を数えるにはmb_strlen()を使います。バイトと文字の違いはstrlen()を参照してください。
省略記号付きでテキストを短くする
一覧やカード用に長いタイトルを切り詰めるのが、substr()のいちばんよくある実際の使い方です。日本語のタイトルが文字の途中で切れないようmb_substr()を使い、実際に短くしたときだけ...を付けます。
mb_strimwidth($text, 0, $width, '...')は同じことを表示幅で行い、全角の日本語は2桁、ラテン文字は1桁と数えます。固定幅のレイアウトに向いています。
substr_countで部分文字列を数える
substr_count($haystack, $needle)は、$needleが何回現れるかを返します。大文字小文字を区別し、重なり合う一致は数えません。
substrとstrpos:ある文字の前後のテキスト
メールアドレスの@のように、位置が事前にわからない文字で切るには、substr()とstrpos()を組み合わせます。
strpos()の結果を使う前に、falseが返っていないかを確認してください。文字がないとfalseは警告なしで0として扱われるので、substr('nobody', 0, $at)は""を、substr('nobody', $at + 1)は"obody"を返してしまいます。
よくある質問
PHPで文字列の最後の数文字を取得するには?
負のオフセットを使います:substr($s, -3)は最後の3文字を返します。日本語などのマルチバイト文字を含みうるテキストにはmb_substr($s, -3)を使います。
substrとmb_substrの違いは何ですか?
substr()はバイトを数え、mb_substr()は文字を数えます。UTF-8ではかなとよく使う漢字は1文字3バイトなので、substr('日本語', 0, 2)は文字を半分に切ってしまいますが、mb_substr('日本語', 0, 2)は"日本"を返します。
開始位置が文字列の末尾を超えているとsubstrは何を返しますか?
空文字列です。PHP 8.0以降、substr('abc', 5)は""を返します。PHP 7ではfalseを返していました。
PHPで文字列の最後の1文字を削除するには?
substr($s, 0, -1)は最後の1バイト以外のすべてを返します。マルチバイトのテキストにはmb_substr($s, 0, -1)を使い、特定の末尾の文字だけを取り除きたいならrtrim($s, ',')を使います。
PHPで部分文字列が何回現れるかを数えるには?
substr_count($haystack, $needle)です:substr_count('banana', 'an')は2を返します。大文字小文字を区別し、重なり合う一致は数えません。