Webエンジニアの日常とリーグオブレジェンド

Webエンジニアとして働いている猫のブログ。EmacsとMySQLとリーグオブレジェンド(LoL)が好物。主に技術的な記事かLoLの記事を書く。

PHPでstringをintにキャストする場合のバリデーションについて

f:id:yoshiki_utakata:20181004212834j:plain

環境

利用しているバージョンは

  • PHP 7.2

ですが、結構幅広いバージョンに通じる話だと思う。

はじめに

PHPのキャストがガバガバなのはみなさんご存知だろう。

$ php -r "var_dump((int)'ホゲーーー');"
int(0)

0じゃねえよ!

ということで int にキャストする前にバリデーションしたいがこれがまた悩ましい

要するにこういう感じのことことをしたい

<?php

$intval = intにキャストできるか判定($strval) ? (int)$strval : null:

is_numeric

https://www.php.net/manual/ja/function.is-numeric.php

$ php -r "var_dump(is_numeric('100'));"
bool(true)

$ php -r "var_dump(is_numeric('ホゲー'));"
bool(false)

一見良さそうだがダメだ。

$ php -r "var_dump(is_numeric('3.14'));"
bool(true)

これは小数でもOKなのだ。

ctype_digit

https://www.php.net/manual/ja/function.ctype-digit.php

$ php -r "var_dump(ctype_digit('100'));"
bool(true)

$ php -r "var_dump(ctype_digit('ホゲー'));"
bool(false)

$ php -r "var_dump(ctype_digit('3.14'));"
bool(false)

これは少数でも弾いてくれるようなのでOK...な気がするがこれもダメだ!

$ php -r "var_dump(ctype_digit('-100'));"
bool(false)

マイナスが弾かれる

結論: filter_var

こんなメソッドが...

https://www.php.net/manual/ja/function.filter-var.php

qiita.com

filter_var($strval, FILTER_VALIDATE_INT); としてみるといいっぽい。やってみる。

$ php -r "var_dump(filter_var('100', FILTER_VALIDATE_INT));"
int(100)

$ php -r "var_dump(filter_var('ホゲー', FILTER_VALIDATE_INT));"
bool(false)

$ php -r "var_dump(filter_var('-100', FILTER_VALIDATE_INT));"
int(-100)

$ php -r "var_dump(filter_var('3.14', FILTER_VALIDATE_INT));"
bool(false)

$ php -r "var_dump(filter_var(null, FILTER_VALIDATE_INT));"
bool(false)

完璧じゃないか。。。