6

コード全体で使用される関数があります。この関数は、渡されたパラメーターが正の整数であることを想定しています。PHP は緩く型付けされているため、データ型は重要ではありません。ただし、数字だけが含まれていることが重要です。現在、続行する前に正規表現を使用して値を確認しています。

これが私のコードの簡略版です:

function do_something($company_id) {
    if (preg_match('/\D/', $company_id)) exit('Invalid parameter');
    //do several things that expect $company_id to be an integer
}

私は Perl のバックグラウンドを持っており、正規表現を頻繁に使用する傾向があります。しかし、私はそれらの使用法が物議を醸していることを知っています.

intval()orの使用(int)強制 $company_idを整数にすることを検討しました。ただし、予期しない値が発生する可能性があるため、すぐに失敗したいと考えています。

他のオプションは次のとおりです。

if (!ctype_digit((string) $company_id)) exit('Invalid parameter');

このシナリオは正規表現の有効な使用法ですか? ある方法が他の方法よりも優先されますか? もしそうなら、なぜですか?私が考慮していない落とし穴はありますか?

4

3 に答える 3

7

目標

元の質問は、不明なデータ型の値を検証し、数字以外の値を除くすべての値を破棄することに関するものです。この望ましい結果を達成するには、2 つの方法しかないようです。

目標が迅速に失敗するifことである場合、有効な値をチェックしてすべてのコードをブロックにラップするのではなく、無効な値をチェックしてから失敗することをお勧めします。

質問のオプション 1

if (preg_match('/\D/', $company_id)) exit('Invalid parameter');

regex数字以外に一致する場合に失敗するために使用します。短所: 正規表現エンジンにはオーバーヘッドがあります

質問のオプション 2

if (!ctype_digit((string) $company_id)) exit('Invalid parameter');

ctype_digitFALSE の場合に失敗するために使用します。短所:値を文字列にキャストする必要がありますが、これは(小さな)余分なステップです

ctype_digit文字列を期待し、PHP はパラメーターを文字列にキャストしないため、値を文字列にキャストする必要があります。に整数を渡すctype_digitと、予期しない結果が得られます。

これは文書化された動作です。例えば:

ctype_digit('42'); // true
ctype_digit(42); // false (ASCII 42 is the * character)

オプション 1 と 2 の違い

正規表現エンジンのオーバーヘッドのため、オプション 2 がおそらく最適なオプションです。ただし、これら 2 つのオプションの違いについて心配することは、時期尚早の最適化のカテゴリに分類される可能性があります。

注:上記の 2 つのオプションには機能上の違いもあります。最初のオプションはNULL空の文字列を有効な値と見なしますが、2 番目のオプションはそうではありません (PHP 5.1.0 以降)。そのため、ある方法が他の方法よりも望ましい場合があります。オプションの機能をバージョンregexと同じにする場合は、代わりにこれを使用します。ctype_digit

if (!preg_match('/^\d+$/', $company_id)) exit('Invalid parameter');

注:上記の「文字列の開始」^および「文字列の終了」$アンカーregexは非常に重要です。それ以外の場合は、abc123def有効と見なされます。

その他のオプション

ここおよび他の質問で提案されている他の方法は、記載されている目標を達成できませんが、他の人を助ける可能性があるため、それらに言及し、それらが機能しない理由を説明することが重要だと思います.

  • is_numeric指数部、浮動小数点数、および 16 進値を使用できます

  • is_int'1'が有効であると見なされる場合、検証に役立たない値ではなくデータ型をチェックします。フォーム入力は常に文字列です。値の取得元がわからない場合は、データ型もわかりません。

  • filter_varwithFILTER_VALIDATE_INTでは、負の整数と などの値を使用できます1.0。これは、データ型に関係なく整数を実際に検証するための最良の関数のようです。ただし、数字だけが必要な場合は機能しません。注:が有効な値であると見なされる場合は、真実か偽かだけでなく、FALSE 身元を確認することが重要です。0

于 2012-12-08T20:15:45.273 に答える
0

どちらのメソッドも、変数を文字列にキャストします。preg_matchは整数型のサブジェクトを受け入れないため、関数に渡されると文字列にキャストされます。ctype_digitこの場合、間違いなく最善の解決策です。

于 2012-12-09T05:15:35.500 に答える
0

filter_var+はどうFILTER_VALIDATE_INTですか?

if (FALSE === ($id = filter_var($_GET['id'], FILTER_VALIDATE_INT))) {
    // $_GET['id'] does not look like a valid int
} else {
    // $id is a int because $_GET['id'] looks like a valid int
}

さらに、min_range/max_range オプションがあります。

この関数の基本的な考え方は、次のものとほぼ同等です。

function validate_int($string) {
    if (!ctype_digit($string)) {
        return FALSE;
    } else {
        return intval($string);
    }
}

また、整数が必要な場合は、 を使用できますis_int。残念ながら、型ヒントはオブジェクトと配列に限定されています。

于 2012-12-08T17:46:49.610 に答える