エス技研

WordPress、CakePHP、PHP、baserCMSなどの Web系システムを中心に情報を提供します!


数値がMySQLのint(11)に保存できない!PHPの変数が本当にint型か確認!

   

数値なのにMySQLのint(11)に保存できない!「The provided value is invalid」のエラーが出る理由とその対処方法の解説

 

PHPで数値を int(11)に保存しているのにエラーとなった経緯

 
LAMP環境(Linux、Apache、MySQL、PHPの環境。いわゆる Web環境)で、商品を販売し、その販売手数料をデータベースに保存する、という仕組みを作りました。
 
具体的には...
「商品の価格($price):100,000円」の商品を
「販売手数料率($rate):20%」として手数料を計算し
その手数料を「fee int(11)」というカラムに保存する
というものです。
 
 
これを処理するため、下記の処理を作成しました(言語は PHPです)。
 

$price  = 100000;
$rate   = 20;
$rate_percent = $rate / 100;

$fee = $price * $rate_percent;

 
この処理の結果の「$fee」をテーブルの「fee int(11)」カラムに保存する処理を作成しました。
 
しかし、テーブルに保存する処理で MySQLが「The provided value is invalid」のエラーを出力するのです。
「$fee」に入っている値は「20000」という数値なのにも関わらず!です。
 
それはそれはもう悩みましたよ。
 
 

検証ソースコード・その1

 
この問題を確認するために下記のソースコードを作成しました。
 

$price  = 100000;
$rate   = 20;
$rate_percent = $rate / 100;

$fee = $price * $rate_percent;
echo $fee;

if(is_int($fee)){
  echo "INTです";
} else {
  echo "INTではありません";
}

 
さて問題です!
この場合「INTです」「INTではありません」のどちらになるでしょうか?
 
問題にするくらいなので、「INTではありません」と出てくると考える方もあるかもしれませんが、理由はお分かりになりますか?
 
 

検証ソースコード・その2

 
では、下記のように記述した場合はどうでしょうか?
 

$price  = 100000;
$rate   = 20;

$fee2 = $price * $rate / 100;
echo $fee2;

if(is_int($fee2)){
  echo "INTです";
} else {
  echo "INTではありません。";
}

 
その1と2の違いは、あらかじめ手数料率を計算して変数「$rate_percent」に入れているか、いないかの違いです。
 
 
「$fee」「$fee2」のいずれも「echo」で出力される値は「20000」なのですが、
前者は「INTではありません」となります。
後者は「INTです」となります。
 
理由は、
後者は、変数はすべて「int」であり、計算結果も「int」であるため、最終的な変数である「$fee2」も「int」になります。
 
対して、前者は変数「$rate_percent」に代入される値「0.2」が「int」ではない値(double)となります。
そのため、「int」に「intではない値(double)」をかける計算をする事になり、計算結果の見た目が「int」であったとしても「$fee」は「intではない(double)」となるのです。
 
 

PHPで integerと doubleの計算をする際の対策

 
今回のような integerと doubleの計算をする際の対策としては、キャスト演算子を使って型を指定する必要があります。
 
今回の場合は、下記のような表記にすることで「int」に変換することができます。
 

// 下記のいずれかの方法で対応が可能です。
$fee = (int)($price * $rate_percent);
$fee = (int)$fee = $price * $rate_percent;

// 下記の記述では「int」にはなりません。
(int)$fee = $price * $rate_percent;

 
 

PHPの変数の型を調べるには「gettype()」関数を使う

 
PHPでは変数を型を気にすることがほぼないため、そもそもの変数の確認の仕方を忘れておりまして、「in_int()」関数を使って検証を行いましたが、「gettype()」関数を使うと変数の型を簡単に確認することができます。
 

echo gettype($fee);
// double

echo gettype($rate_percent);
// double

echo gettype($fee2);
// integer

 
「gettype()」関数を使えばここまで悩まずに済んだかもしれません...
 
 

PHPで integerと doubleの計算をしてみて...のまとめ

 
PHPで integerと doubleの計算をしてみて驚きがありました!
こんな仕様、知りませんでした...
 
四則演算でも「+」「-」「×」は気にしなくて良さそうですが、「÷」を使うときは途中で変数を使う場合は、その変数にどのような値が入るのか、それを確認しておく必要がありますね。
 
ちなみに「$rate = 200」を入れると「$rate_percent」も「int」となるため、前者の計算式でも「INTです」となります。
 
 
代入される値によって結果が異なりますので、十分なデバッグが必要になりますね。

 - PHP・Smarty・ECCUBE

最後までお読みいただきましてありがとうございます。
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!

Message

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

下記の空欄を埋めてください。 * Time limit is exhausted. Please reload CAPTCHA.

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

※入力いただいたコメントは管理者の承認後に掲載されます。

  関連記事

路線・駅検索をPHPで実装する方法解説。GoogleMapsの緯度経度から計算し検索
路線・駅検索をPHPで実装する方法解説。GoogleMapsの緯度経度から計算し検索

路線・駅検索の仕組みの構築は大変。登録する側も最寄り駅が多い場合は大変。なので簡易に実装するため緯度経度に基づき直線距離を計算する処理を考案して実装して、その処理を解説。

ECCUBEの管理画面のSSL設定をインストール後に変更する方法

ECCUBEをインストールした後から管理画面のSSL設定を変更する方法を解説します。config.phpファイルのHTTPS_URLとADMIN_FORCE_SSLの値を変更すればOK。

AdminerはphpMyAdmin代替のデータベース管理ツール

AdminerはphpMyAdminとほぼ同機能のデータベース管理ツール。PHP 1ファイルのため設置が非常に簡単で軽快に動作し、phpMyAdminの置き換えで使うのも問題なし。

指定した数で文字列を丸める関数substr、mb_substr、mb_strimwidthの違い
指定した数で文字列を丸める(n文字目で…にする)関数substr、mb_substr、mb_strimwidthの違い

文字列を指定された数で抜き出すPHPの関数、substr、mb_substr、mb_strimwidthについての解説。似た関数だが引数の指定方法が違ったり、文字数がバイト数か文字数かも違ったり、注意が必要だ。

GMOペイメントゲートウェイのjava.io.IOExceptionのエラー

ECCUBEの決済でGMOペイメントゲートウェイのモジュールを使ってテスト決済を行った場合の不具合、java.io.IOExceptionと言うエラーの原因と対策方法の解説です。

sleepの秒指定は整数のみなので1.5秒はsleep、usleepを組み合わせる
sleepの秒指定は整数のみなので1.5秒はsleep、usleepを組み合わせる

PHPのプログラム処理を遅延させる「sleep()」は整数秒単位。「usleep()」は1秒未満のマイクロ秒単位。では「1.5」秒はどう表現するのか。「sleep()」「usleep()」を組み合わせる。その解説。

PHPのデバッグで使う print_r、var_dump、var_exportの動作の違い
PHPのデバッグで使う print_r、var_dump、var_exportの動作の違い

PHPのデバッグ等で変数や配列の中身を確認するために使用する関数print_r、var_dump、var_exportの動作の違い、仕様の違いについて確認した。var_exportがオススメ。

QRコード作成ライブラリ「cakePHP-QR-Code-Helper」をPHPで使うカスタマイズ
QRコード作成ライブラリ「cakePHP-QR-Code-Helper」をPHPで使うカスタマイズ

CakePHP2用のQRコード作成ライブラリ「cakePHP-QR-Code-Helper」をプレーンのPHPでも使うためのカスタマイズ方法を解説。1ファイルを設置するだけでQRコードが作れるため使い勝手がいい。

ECCUBEを開発環境から本番ドメインに変更でエラーが・パス変更について

レンタルサーバでサーバ会社から割り当てられたURLで開発し、本番公開時にドメインを当てたらエラーが!そんな場合の対処方法の解説。対処方法は簡単ですが管理画面からは対応不可。

数値文字参照コード変換ツール(HTML特殊文字コード変換ツール)

テキストを数値文字参照コード(特殊文字コード)に変換するツール。テキストを数値文字参照コードに簡単変換。数値文字参照、文字実体参照、特殊文字などの違いも解説。