PHPでの文字数カウントには strlen が絶対NGな理由…正しい方法

PHPをある程度使ってる人なら常識中の常識だと思うんですが・・・

文字数カウントには絶対に strlen 関数は使っちゃダメです。

でも僕自身、PHP初心者の頃は strlen を使ってしまってたことがあります。

そこで過去の恥ずかしい教訓も込めて、
PHPで strlen 関数を使うのが絶対NGな理由と正しいやり方を解説!

なんで文字数カウントには strlen を使っちゃダメなの?

PHPに限らず他言語にも strlen  っていう関数はあります。

この strlen  っていう名前が本当に紛らわしい・・・

何も予備知識が無いと、
「str、len、、、そうか、文字列(str)の長さ(len)を測る関数か!」
みたいに思っても全くおかしくありません。

 

でもこの strlen   関数、公式リファレンスを見ると次のように説明されてます。

strlen ( string $string ) : int
与えられた string の長さを返します。

注意:
strlen() が返すのはバイト数であり、 文字数ではありません。

引用元 : https://www.php.net/manual/ja/function.strlen.php

ご親切にも「バイト数であり、文字数ではありません」とまで書いてくれてます。

 

とはいえ、半角英数なら1文字1バイトなので、文字数カウントに使っても問題ないです。

例えば次コードみたいに

 

でも日本語などのマルチバイト文字だと問題アリ

次コードみたいに書くと、正しい結果は当然ながら返してくれません。

ちなみに UTF-8 だと、日本語1文字は大体3バイト

なので strlen * 3  という考え方もできますが、
もし半角・全角混じっているなら、そういう稚拙な方法も通用しなくなってしまいます。

ここまで長々と書いたけど、要するに strlen  を使うのは絶対ダメ!

こういうことです。

文字数カウントには mb_strlen を使うのが基本

じゃあ strlen  を使っちゃダメなら何を使うかというと、専用の関数が用意されてます。

それが mb_strlen という関数

この関数は公式リファレンスだと、次のように説明されてます。

mb_strlen ( string $str [, string $encoding = mb_internal_encoding() ] ) : int

文字エンコーディング encoding の文字列 str の文字数を返します。 マルチバイト文字の一文字は1個として数えられます。

無効な encoding を指定した場合は FALSE を返します。

引用元 : https://php.net/manual/ja/function.mb-strlen.php

PHPだとデフォルトのエンコーディングは UTF-8 なので、
そのエンコーディング基準での文字数を返してくれるという訳です。

 

例えば次、これが文字列カウントしてるコード例

半角・全角関係なく、文字数でカウントされてるのが分かるはず

 

何度も言いますが、 strlen  という字面に騙されないように要注意です。

基本的な文字数カウントには必ず mb_strlen  を使う必要アリ!

もし全角1文字を半角2文字分でカウントしたいなら...

今紹介した mb_strlen  は半角・全角関係なく1文字としてカウントします。

でも全角1文字を半角2文字分でカウントしたいこともあるはず

自力でそういうコードを書くこともできるけど、あんまりにも非効率です。

 

その場合は mb_strwidth 関数を使うのがベスト

この関数についての説明は次の通り

mb_strwidth ( string $str [, string $encoding = mb_internal_encoding() ] ) : int
string str の幅を返します。 半角文字は 1 として、 全角文字は 2 として数えます。

全角文字は次のとおりです。 U+1100-U+115F、 U+11A3-U+11A7、 U+11FA-U+11FF、 U+2329-U+232A、 U+2E80-U+2E99、 U+2E9B-U+2EF3、 U+2F00-U+2FD5、 U+2FF0-U+2FFB、 U+3000-U+303E、 U+3041-U+3096、 U+3099-U+30FF、 U+3105-U+312D、 U+3131-U+318E、 U+3190-U+31BA、 U+31C0-U+31E3、 U+31F0-U+321E、...(以下略

引用元 : https://www.php.net/manual/ja/function.mb-strwidth.php

これは 文字の幅 を測るための関数で、全角を半角2文字分としてカウントします。

こういう日本語に優しい関数が用意されてるのもPHPのいいとこですね。

 

ちなみに以下が mb_strwidth  を使ったコード例

ちなみにこの関数については、次の記事でもチョッとだけ触れました。

▼ Twitter の最大文字数とバイト数を調べてみた

例えば Twitterボット を作るときとか、
日本語1文字を2文字分としてカウントしたいときに使うことが "ごくまれ" にあります。

ここまでのまとめ ~ strlenは絶対に使うな!

ということで、簡単にここまでの内容まとめ

  • 文字数カウントに strlen は絶対NG
    ⇒ これは文字数ではなく、バイト数を数える関数だから
  • 文字数カウントには mb_strlen を必ず使う
    ⇒ 半角・全角関係なく1文字としてカウントしてくれる
  • 半角全角区別するなら mb_strwidth を使う
    ⇒ これは 全角1文字 = 半角2文字 としてカウントしてくれる

以上、PHPで文字数カウントに strlen  を使っちゃダメという話でした。

知らないままで使い続けると、痛い目にあうので要注意です!

PHP

Shareこの記事をシェアしよう!

Commentsこの記事についたコメント

3件のコメント
  • mayu

    突然失礼します。
    PHPを勉強しておりましてたどり着き、ご質問させていただきたいです。

    strlenはつかっちゃダメでmb_strlenを使いましょう、とのことですが、strlenを使う場面はないのでしょうか。
    (この関数が存在する意味はあるのでしょうか)

    可能であればご教示いただけますと幸いです。
    どうぞよろしくお願いいたします。

    6月 7, 2020 9:46 am
    • ぴー助

      コメントありがとうございます!
      文字列以外を扱うときに strlen は存在意味を持ちます。

      なぜならPHPでの文字列はバイナリ(=2進数で表現できるデータ)も含められるためです。つまり変数には “abc” のような文字列だけでなく、画像の中身を読み込みしてそのデータを代入したりもできます。

      具体的な場面の例を出すなら・・・
      ■ file_get_contents() でのファイル読込後にサイズを測ったり、
      ■ バイナリデータを直に扱いたい時など
      ですね。少しでも参考になれば幸いです。

      6月 7, 2020 11:54 am
  • hoge

    print_r( mb_strwidth(‘…’) );
    /// => 1

    print_r( mb_strwidth(‘★’) );
    /// => 1

    6月 25, 2021 10:53 am

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください