カテゴリー
SugiBlog Webエンジニアのためのお役立ちTips

文字列”false”をbool型にキャストするとtrueになる問題

文字列”false”をbool型として扱いたい場合、単純にキャストしてしまうとfalseの動作を期待しているのに意図とは反対にtrueの動作となってしまうことがあるので注意が必要です。

例えば以下のように文字列”false”をbool型にキャストしてみます。

$bool = (bool)"false";
var_dump($bool);

するとどうでしょう。以下のような結果が返ってきます。

bool(true)

“false”をキャストしたのにtrueとなってしまいます。
この原因はキャストだとfalseとは認識されず、”false”というただの文字列という認識となり空文字ではないという判断になるためです。

公式のマニュアルを見てみてください。
booleanへの変換

  • boolean の false
  • integer の 0 (ゼロ)
  • float の 0.0 および -0.0 (ゼロ)
  • 空の文字列 “”、 および文字列の “0”
  • 要素の数がゼロである 配列
  • unit 型 NULL (値がセットされていない変数を含む)
  • bool 型へキャストするように動作がオーバーロードされた内部オブジェクト。 例: 属性がない空要素から作成された SimpleXML オブジェクト。

上記以外は全てtrueとみなされます。

ではどうすれば良いでしょうか。
続きを読む…»

30 views

XAMPPでPHPのモジュール版・CGI版切り替え

PHPにはモジュール版・CGI版の2種類があります。
主な違いは次の通りです。
モジュール版:ApacheのrootユーザーでPHPを実行・処理が速い
CGI版:ユーザー毎のPHP実行環境・セキュリティや安全性に優れている・モジュール版より遅い

XAMPPを使ってローカル環境で開発している場合、特に切り替えが必要なケースは稀かと思いますが、
参考までに切り替えの方法を記載しておきます。

httpd.conf

以下の行をコメント解除します。

#LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

httpd-xampp.conf

モジュール用セットアップの記述をコメントアウト
※PHP7の場合の例です。

#
# PHP-Module setup
#
LoadFile "/xampp/php/php7ts.dll"
LoadFile "/xampp/php/libpq.dll"
LoadFile "/xampp/php/libsqlite3.dll"
LoadModule php7_module "/xampp/php/php7apache2_4.dll"

<FilesMatch "\.php$">
    SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch "\.phps$">
    SetHandler application/x-httpd-php-source
</FilesMatch>

CGI用セットアップの記述をコメント解除します。

#
# PHP-CGI setup
#
#<FilesMatch "\.php$">
#    SetHandler application/x-httpd-php-cgi
#</FilesMatch>
#<IfModule actions_module>
#    Action application/x-httpd-php-cgi "/php-cgi/php-cgi.exe"
#</IfModule>

PHPINFOを表示し、Server APIの欄を確認します。
こちらがApache 2.0 Handlerとなっていればモジュール版、
CGI/FastCGIになっていればCGI版で動作していることになります。

1,073 views

PDOで取得したデータが、数値型なのに文字列型になってしまう

PHPのバージョンを7.4系から8.x系にバージョンアップする事案があり、変更点やシステムの動作に問題がないか等の調査をしていました。
その中で公式ページにも見当たらないことがあったので、実際にバージョンを切り替えながら検証して分かったことを共有させていただければと思います。

今回発見した問題点はPDOのプリペアドステートメントです。
セキュリティ上、脆弱性のないように開発する中で必ず使われているかと思います。

ただ、このプリペアドステートメント、数値型のデータを文字列型で返してきます。
困りますね。
しかしながらそういう仕様なので、それに合わせてコーディングするしかないわけなんですが、
これがなんと、8.1以降だと数値型で返ってるのです。

なんということでしょう・・・。

厳密な比較を行っている箇所はすべて修正しないといけません。
例えば以下のような場合です。

if($col["COLUMN_NAME_INDEX"] === "1") { ... }

このCOLUMN_NAME_INDEXのデータ型は数値型(Integer)ですが、PDOのプリペアドステートメントで返ってくるのは文字列型のため、このような比較をしています。
これが8.1以降だとCOLUMN_NAME_INDEXのデータが数値型のため、(1 === "1")という式となり判定はfalseとなります。

この問題については、コーディング自体に間違いがあるわけではありませんので、コード解析ツール等にかけても出てこないと思います。
原因の究明に時間がかかったので、ここに記しておきます。

更に調査したところ、PDOの設定でエミュレート・モードというものがあり、有効/無効(true/false)で設定します。
実際には今回の件に関する具体的な設定ではないのですが、この設定を無効(false)に設定してみると8.0でも数値型で返ってきました。

PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, false)

検証したバージョンは次の通りです。
7.4.29
8.0.28
8.1.17
8.2.4

また、逆に従来の文字列に合わせる場合だと確実に動作させることができます。
PDO::ATTR_STRINGIFY_FETCHESオプションをtrueにすることで全て文字列で返すように設定することが可能です。
公式リファレンスにも「全てのフェッチする値を強制的に文字列として扱います。」と書かれています。

PDO::setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true)

公式:PHP 8.0.x から PHP 8.1.x への移行

1,512 views

PHPで10進数を2・8・16進数に変換

PHPで10進数から2・8・16進数へと、基数変換を行う方法をご紹介します。

まずは10進数で変換する値を宣言しておきます。

$dec = 500;

2進数に変換

書式:decbin(int $num): string

$bin = decbin($dec);
echo $bin;

出力結果は111110100となります。

8進数に変換

書式:decoct(int $num): string

$oct = decoct($dec);
echo $oct;

出力結果は764となります。

16進数に変換

書式:dechex(int $num): string

$hex = dechex($dec);
echo $hex;

出力結果は1f4となります。


今度は逆に変換してみましょう。

2進数から10進数に変換

書式:bindec(string $binary_string): int|float

$dec = bindec('111110100');
echo $dec; //500

続きを読む…»

588 views

PHPでPOSTリダイレクトする方法

PHPでリダイレクトさせたいとき、header関数を使いますよね。
通常はGETリクエストにてリダイレクトされます。
それを強制的にPOSTリクエストにし、パラメータを引き継ぐことができます。

headerの書式

header(string $header, bool $replace = true, int $response_code = 0): void

POSTリクエストでパラメータを引き継いでリダイレクトするには、$response_code307を与えます。

header("Location: example.php", true, 307);

公式マニュアル:
https://www.php.net/manual/ja/function.header.php

6,917 views