人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PHPに関して質問です。
下記のようなスクリプトがあります。(一例です)

----------------------------------------------
function test() {
$a = 1;
return $a;
}

if (!$b = test()) {
print "false";
}

----------------------------------------------

この時、return $a;の直前で$aの値を表示すると
値は1と表示されるのに、if文ではfalseと判定されます。
これは100%では無く、1%ぐらいの確率で起きます。
発生条件がわからないのですが、
何かわかる方はいらっしゃいますでしょうか?

●質問者: m-nisi
●カテゴリ:コンピュータ インターネット
✍キーワード:PHP print test スクリプト 確率
○ 状態 :終了
└ 回答数 : 7/7件

▽最新の回答へ

1 ● la-la-land
●18ポイント

if (!$b = test()) {

これは

if (!$b == test()) {

が正しいと思います

◎質問者からの返答

PHP Notice: Undefined variable: b・・・

とNoticeが出ます。

($bは定義されていないので当然ですが)


2 ● pinkymonk
●17ポイント

if (!$b = test()) {

print "false";

}

ここのIF文を


if (!$b == test()) {

または

if ($b != test()) {

としてください。

◎質問者からの返答

どちらのケースも

PHP Notice: Undefined variable: b・・・

とNoticeが出ます。

($bは定義されていないので当然ですが)


3 ● よたか
●17ポイント

自信がないので、外している場合ポイントはいりません。

このifの判定は$bがブランクか否かの判定ですよね。

判定式の中で、test()の返りを代入しているので、

必ず1になると思いますが、

動作環境の問題(負荷が大きくて値を取得できないなど?)で、

functionからの返りを取得できない場合にfalseになるのではないでしょうか?

私なら、用心して、あらかじめ$bに代入してからifの判定します。

下記の様な感じだとどうなりますか?

function test() {

$a = 1;

return $a;

}

$b = test();

if (!$b) {

print "false";

}

◎質問者からの返答

そうですね。実際はtest()の中ではいろいろやって、

その返り値がfalseなら○○の処理をする

という事を想定して作っています。

最終的には私も、予め代入してから判定するようにして、

問題無く動作する事は確認しました。

負荷に関しては私一人で使っているサーバなので、特に高いという事はないです。

> functionからの返りを取得できない場合にfalseになるのではないでしょうか?

まさにこの部分で、そういうケースがあり得るのか?

あり得るならどういった条件で起こるのか?

といった事が知りたくて質問させて頂きました。

ご回答ありがとうございます。


4 ● あすか
●17ポイント

PHPはシングルスレッド処理のシステムなので、ご質問のスクリプトが false を示すことは絶対に起こり得ません。


しかし、問題になっているスクリプトはご質問のような単純なものでは無いでしょうし、その中でstream_selectのような非同期処理を可能にする仕組みを導入しているとしたら、可能性として false が表示されることがあり得ます。

◎質問者からの返答

実際に関数の中で行っている事は、

mysql_query関数を使ってDBからデータを取得し、

その結果を返すようにしております。

ご指摘の通り、非同期処理ならあり得る気もしますが、

returnの直前の出力では値があるのに、

その後のif文でfalseになる事は無い気がします。

(当然出力される順番も正常です)

ご回答ありがとうございます。


5 ● うぃんど
●17ポイント ベストアンサー

質問の意味が「ユーザー定義関数を100個作ると、その中の1つくらいがfalseになる」という意味にも取れたので、静観しておりました(コメント・トラックバックを表示するにチェックが入っていればコメントできたのですけどね)

(1)原因の推定

「1つのユーザー定義関数が100回に1回くらいの割合でfalseになる」ということであれば、原因としてはMySQL関数が「構文エラーや接続失敗、SQLを実行した結果として行が存在しない場合など様々な場面でfalseを返す」ことが考えられ、結果として下記と等価の状態になっているのだと思われます

(どのような状態でfalseを返すかはマニュアル http://www.php.net/manual/ja/ref.mysql.php 参照)

<?php
function test() {
 return false;
}

if (!$b = test()) {
 print "false";
}

(2)対策

対策としては、MySQL関数それぞれの結果に対してfalseでないかどうかを逐一確認するようにプログラムを作るということになります

手前味噌ですが、私の最近の回答から…

http://q.hatena.ne.jp/1301754362#a1065616

(データベースに接続できないというくらい重症な事象はor dieでphpの実行を止めて、結果が望みどおりでない場合は状況に応じて結果表示を変えるという形にしています)

関数化するのであればyotacaさんのおっしゃるとおり「あらかじめ何らかの値をセットしておく」といったような対策もあわせて行っておくと関数の使い勝手も向上し、ブラックボックス化することも可能になったりします(ブラックボックス化は諸刃の剣になってしまう場合もあるので注意)

◎質問者からの返答

かなり簡略化して例を書いてしまい申し訳ございません。

実際にはMySQLからの戻りをきちんとチェックし、

値が入っている事を確認した上でreturnしています。

まさしくwindofjuly様の回答のような形でチェックしています。

そのreturn直前にvar_dumpして値が入っている事を確認しました。

しかし、その関数の戻りがfalseになってしまうという話でした。

ご回答ありがとうございます。


1-5件表示/7件
4.前の5件|次5件6.
関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ