はじめに
・PHPで0.1から99.9の値をDBに登録するメソッド作成していたときの話です。
・浮動小数(float,double)と整数(int)をフロントから取得してくるのですがここで問題が...
・PHPのint型は10進数だけでなく16進数なんかも含むみたいで0xなんかをDBに登録されるわけにはいかいですよね。
・Javascriptは16進数(0xから始まる)は文字列判定なのですがバックエンドエンジニアとしてフロントに委ねるわけにはいかないので判定処理をつくるに至りました。
PHPのマニュアルをみてみたら...
<?php
$a = 1234; // 10進整数
$a = 0123; // 8進数 (10進数の83と等価)
$a = 0o123; // 8進数 (PHP 8.1.0 以降)
$a = 0x1A; // 16進数 (10進数の26と等価)
$a = 0b11111111; // 2進数 (10進数の255と等価)
$a = 1_234_567; // 10進数 (PHP 7.4.0 以降)
?>
ごらんの通り'_'や'x'なんかを含んでやっかいですよね。
<参考>
phpマニュアル
https://www.php.net/manual/ja/language.types.integer.php
ということで実際にわたしがつくったものをご覧ください。
0.1~99.9の小数点一位の判定処理
/**
* decimal型判定処理
*
* 0.1以上99.9以下場合値を返す
*
* @param int|float|null $value チェック対象文字列
* @return bool 判定結果(true:不適切 / false:適切)
*/
public static function isDecimalFormat(int|float|null $value): bool
{
if (is_null($value)) {
return false;
}
// 各メソッドの引数が[string]なので変更
$string_value = (string)$value;
$comma = '.';
if (self::isIncludeComma($string_value, $comma)) {
// 数値分割処理
$fullNumber = self::isSplitValue($string_value, $comma);
// 数値桁数判定処理(2桁)
if (!self::isNumberOfDoubleDigits($fullNumber[0])) {
return false;
}
// 10進数自然数判定
if (!self::isInteger($fullNumber[0])) {
return false;
}
// 数値桁数判定処理(1桁)
if (!self::isNumberOfADigits($fullNumber[1])) {
return false;
}
// 10進数自然数判定
if (!self::isInteger($fullNumber[0])) {
return false;
}
return true;
} else {
// 数値桁数判定処理(2桁)
if (!self::isNumberOfDoubleDigits($string_value)) {
return false;
}
// 10進数自然数判定
if (!self::isInteger($string_value)) {
return false;
}
return true;
}
}
ということで各メソッドの紹介です。
コンマ判定処理
/**
* コンマ判定処理
*
* コンマが含まれているか判定する
*
* @param string $value チェック対象文字列
* @param string $comma コンマ
* @return bool 判定結果(true:コンマが含まれている / false:含まれていない)
*/
public static function isIncludeComma(string $value, string $comma): bool
{
if (str_contains($value, $comma)) {
return true;
} else {
return false;
}
}
それでは解説です。
str_contains($value,$conmma)
こちらで$value'.'が含まれているか判定しています。
このメソッド割愛で下記のものでいいですよね。笑
if (str_contains($value,$comma) {
/// 以後省略
}
数値分割処理
/**
* 数値分割処理
*
* コンマの前と後で数値を分ける
*
* @param string $value チェック対象文字列
* @param string $comma コンマ
* @return array 判定結果(true:適切 / false:不適切)
*/
public static function isSplitValue(string $value, string $comma): array
{
$position = strpos($value, $comma);
$firstHalf = mb_strstr($value, $comma, true);
$secondHalf = substr($value, $position + 1);
return [$firstHalf, $secondHalf];
}
それでは解説です。
// '.'の場所を$positionに格納
// 2番目なら1が入る(最初が0のため)
$position = strpos($value, $comma);
// mb_strstrは$commaが見つかるまでの文字列を格納(第3引数がtrueのため)
$firstHalf = mb_strstr($value, $comma, true);
// substrは$position+1以降の文字列を取得
$secondHalf = substr($value, $position + 1);
数値桁数判定処理(2桁)
/**
* 数値桁数判定処理(2桁)
*
* @param string $value チェック対象文字列
* @return bool 判定結果(true:2ビット以下 / false:3ビット以上)
*/
public static function isNumberOfDoubleDigits(string $value): bool
{
if (strlen($value) <= 2) {
return true;
} else {
return false;
}
}
それでは解説です。
strlen($value <= 2);
10~99が半角数値2桁なので2以下ですね。
数値桁数判定処理(1桁)
/**
* 数値桁数判定処理(1桁)
*
* @param string $value チェック対象文字列
* @return bool 判定結果(true:2ビット以下 / false:3ビット以上)
*/
public static function isNumberOfADigits(string $value): bool
{
if (strlen($value) == 1) {
return true;
} else {
return false;
}
}
isNumberOfDoubleDigits()の1桁バージョンです。
数値int型判定処理
/**
* 数値int型判定処理
*
* @param string $value チェック対象文字列
* @return bool 判定結果(true:int型 / false:不適切)
*/
public static function isInteger(string $value): bool
{
if (ctype_digit($value)) {
return true;
} else {
return false;
}
}
整数が確定したのでctype_digit()が使えます。
長々説明して申し訳ないです。
終わりに
丁寧に説明したと思いますが至らないところがありましたら申し訳ないです。
お役にたてれば幸いです。