LoginSignup
1
1

More than 5 years have passed since last update.

PHPのフィルタ関数の、「文字列に変換してる箇所のコード」の自己解釈

Last updated at Posted at 2016-12-07

FILTER_CALLBACKで受け取る変数は常に文字列になるでコード見たので、せっかくなので、自己解釈のコメントを入れてみたのを書いておきます。

フィルタリング関数に渡す前に、文字列に変換してる
  /* #49274, fatal error with object without a toString method
    Fails nicely instead of getting a recovarable fatal error. */
  /* https://bugs.php.net/bug.php?id=49274 */
  /* オブジェクトの場合は、文字列に変換できないかもしれないので、
      convert_to_string()の直前で確認する。
  */
  if (Z_TYPE_P(value) == IS_OBJECT) {
    zend_class_entry *ce; /* たぶん、Class Entry の略 */

    ce = Z_OBJCE_P(value);
    if (!ce->__tostring) {
      /* なんでrefcounterをデクリメントしてるのかはわからない */
      zval_ptr_dtor(value);
      /* #67167: doesn't return null on failure for objects */
      /* https://bugs.php.net/bug.php?id=67167 */
      if (flags & FILTER_NULL_ON_FAILURE) {
        ZVAL_NULL(value);
      } else {
        ZVAL_FALSE(value);
      }
      /* 文字列に変換できない場合は、convert_to_stringを通したくない。 */
      goto handle_default;
    }
  }

  /* Here be strings */
  /* 事前にStringにしてから、各filter関数を適用する */
  convert_to_string(value);
  filter_func.function(value, flags, options, charset);

  /* 「フィルタが失敗した場合に返す値」を指定するオプション の処理
  http://jp2.php.net/manual/ja/filter.filters.validate.php
  */ 
  /* 文字列に変換できなかった場合に、ここまで飛んでこれるようにしたいので、ラベル */
handle_default:
    /* 中身のコードはif文の条件式のネストが深くて厄介なので、次のコードの方に分ける */
handle_defaultラベルの中身
  if (
    /* オプション(PHPのfilter関数の第3引数)が指定されてて */
    options
    &&
    /* そのオプションが配列orオブジェクトで指定されてて(≒optionの型のValidate) */
    ( 
      Z_TYPE_P(options) == IS_ARRAY
      || Z_TYPE_P(options) == IS_OBJECT
    )
    &&
    /* フィルタリングに失敗していて */
    (
      (
        flags & FILTER_NULL_ON_FAILURE
        && Z_TYPE_P(value) == IS_NULL
      )
      ||
      (
        !(flags & FILTER_NULL_ON_FAILURE)
        && Z_TYPE_P(value) == IS_FALSE
      )
    )
    &&
    /* 「デフォルト値」の設定がある */
    zend_hash_str_exists(HASH_OF(options), "default", sizeof("default") - 1)
  ) {
    zval *tmp;
    if ((tmp = zend_hash_str_find(HASH_OF(options), "default", sizeof("default") - 1)) != NULL) {
      ZVAL_COPY(value, tmp);
    }
  }

goto使って無理やり経路追加してるあたり、良くも悪くもC言語っぽい感じしますね(笑)。php_zval_filter だと、プリミティブ型なやつとそれ以外(オブジェクトと配列)が混ざるし、あんまよくないのかなぁとか思います。

laruence氏が最後にリファクタしたのが2014年5月7日なので、気になるんならPR投げつけてもいいかなぁとも思ったりしました。しらんけど。

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1