読者です 読者をやめる 読者になる 読者になる

It's raining cats and dogs.

無駄なことなんてないはず

mb_strtolower(mb_strtoupper)とmb_convert_caseの違い

世間ではPHPが良いとか悪いとかで盛り上がっていたりしますね。まぁまぁ確かにそうだよねーとか、言わんとしていることはわかるけど、結局PHPでおまんま食ってる現実には変わりないから、悲しいけど、これが仕事なのよねとちょっと他人事の自分がいます。ともあれ、こういう話が持ち上がったときに、ここがいい、ここが悪い、こういう書き方したらだめ、ここ注意して書こうとかいう話題になるのは大歓迎。PHP始めて数ヶ月くらい経つけれどしらないことばかりなんだもの。
まぁ文句だけ言う輩にはなりたくないなと。

閑話休題

さて、この間PHPの仕事でマルチバイト文字列の中の大文字のアルファベットを小文字に変換する必要があったわけですが、実現方法としてmb_strtolowerとmb_convert_caseが候補に挙がったわけですが、これってどうちがうのかしら?マニュアル的には

  • mb_strtolower

string mb_strtolower ( string $str [, string $encoding ] )

mb_strtolower() は、str の すべてのアルファベットを小文字にして返します。
encoding は str の 文字エンコーディングを指定します。省略された場合は、 内部文字エンコーディングが使用されます。
Unicode 文字属性についての詳細は » http://www.unicode.org/unicode/reports/tr21/ を参照してください。
strtolower() と違い、アルファベットであるかどうかは Unicode 文字属性をもとに決定されます。したがって、この関数の挙動は ロケールの設定に影響されず、すべてのアルファベット、 例えば A ウムラウト (〓) を変換することができます。

http://jp.php.net/manual/ja/function.mb-strtolower.php
  • mb_convert_case

string mb_convert_case ( string $str , int $mode [, string $encoding ] )

mb_convert_case() は、mode で指定された方法で string に対してケースフォルディングを行い、それを返します。
mode は、MB_CASE_UPPER, MB_CASE_LOWER, MB_CASE_TITLE のいずれかの値を取ります。
encoding は str の文字エンコーディングを指定します。省略された場合は、 内部文字エンコーディングが使用されます。
返り値は適切なケースフォルディングが適用された文字列です。
標準のケースフォルディング関数である strtolower() や strtoupper() と違い、ケースフォルディングは Unicode 文字属性を基準に行われます。したがって、この関数の挙動は ロケールの設定に影響されず、また、すべてのアルファベット、 例えば A ウムラウト (〓) を変換することができます。
Unicode 文字属性についての詳細は » http://www.unicode.org/unicode/reports/tr21/ を参照してください。

http://jp.php.net/manual/ja/function.mb-convert-case.php

となってます。
すいません、パラメタが違うくらいしか、全然違いがわからないんですけど。。。
で、仕方がないので、PHPのソース見ます。PHP_SOURCE_ROOT/ext/mbstring/mbstring.cをみます。

  • mb_strtolower
/* {{{ proto string mb_strtolower(string sourcestring [, string encoding])
 *  Returns a lowercased version of sourcestring
 */
PHP_FUNCTION(mb_strtolower)
{
    char *str, *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
    int str_len, from_encoding_len;
    char *newstr;
    size_t ret_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &str, &str_len,
                &from_encoding, &from_encoding_len) == FAILURE) {
        RETURN_FALSE;
    }
    newstr = php_unicode_convert_case(PHP_UNICODE_CASE_LOWER, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);

    if (newstr) {
        RETURN_STRINGL(newstr, ret_len, 0);
    }
    RETURN_FALSE;
}
/* }}} */
  • mb_convert_case
/* {{{ proto string mb_convert_case(string sourcestring, int mode [, string encoding])
   Returns a case-folded version of sourcestring */
PHP_FUNCTION(mb_convert_case)
{
    char *str, *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
    int str_len, from_encoding_len;
    long case_mode = 0;
    char *newstr;
    size_t ret_len;

    RETVAL_FALSE;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|s!", &str, &str_len,
                &case_mode, &from_encoding, &from_encoding_len) == FAILURE)
        RETURN_FALSE;

    newstr = php_unicode_convert_case(case_mode, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);

    if (newstr) {
        RETVAL_STRINGL(newstr, ret_len, 0);
    }       
}
/* }}} */

えーと、違わない。。。
mb_convert_caseはパラメタによって、大文字に変換したり、小文字に変換したり、単語の先頭を変換したりできるので、そのパラメタのチェックが多いくらいで、あとの処理はほぼ同じだな。パラメタのチェックが少ない分、小文字に変換するとか、大文字に変換するとかわかってるときは、mb_strtolowerとかを使ったほうが速そうだな。便利なのか、はたまた紛らわしいだけなのかは気にしないことにしよう。。。