電子書籍の厳選無料作品が豊富!

自作の関数で、issetとemptyを一緒に判定する関数を作っているのですがエラーが出ます。

ある変数が「未定義」または「null」または「""(空白)」の場合はnullである、という関数を作りたいです。

------------------------------------------
function is_null_ex($value){
 if (!isset($value)) {return true;}               // 未定義かnullの場合、trueを返す
 else if (strlen(strval($value)) === 0) {return true;}   // 空白の場合はtrueを返す
 else {return false;}                      // $valueに値が入っている場合はfalseを返す
}

is_null_ex($val);
------------------------------------------

上記の関数で$valueが未定義の場合にfuncを使うと、次のようなエラーが出ます。

Notice: Undefined variable: val

つまり、未定義の変数を引数に渡すとエラーが出ます。
「未定義なら関数に渡さなければ?」と思うかもしれませんが、そもそもこの関数は「未定義」または「null」または「""(空白)」を判定したい関数なのです。

この場合、どうすれば良いのでしょうか?
エラーは出ますが上記の関数で「if (!isset($value)) {return true;}」の部分できちんと判定はされています。
PHP5.3系で運用しています。

ぞうぞよろしくお願い致します。

A 回答 (9件)

http://qiita.com/akisssa/items/342d742c6ce9cd30b …



PHPでは原則的に未定義の変数の値を取得しようとしたときに Notice が発生して NULL 扱いになるが、参照渡しのデフォルト値の場合だけ例外的にNoticeを発生せずにNULLとして初期化される。

と書いてある。

上記のページに「強引な解決方法」が書いてあるけど、ページ読んで意味や方法が判らない場合は諦めるべし。
    • good
    • 0
この回答へのお礼

ありがとうございます!
意味わかります。助かりました。

お礼日時:2014/07/15 08:48

>> $stmt->bindValue(":name", null, PDO::PARAM_NULL);


>> ですが、
>> $stmt->bindValue(":name", null);
>> できちんとnullが入っているので問題ない気がしますが、どうでしょうか?

NULLだけが特別視されると考えるのが良さそうです。SELECTで抜き出してくる時もNULLだけは型を保っていますし、言われてみれば当然の挙動だったかもしれません。検証有難うございます。
    • good
    • 0
この回答へのお礼

いろいろありがとうございました。
とにかく問題が解決できてよかったです!

お礼日時:2014/07/18 09:43

>> $stmt->bindValue(":name", is_null_ex($val) ? null : $val);



なるほど、ちょっとこれはどうしようか迷うところですね。文字列の "0" も "" と同じ扱いで良ければ

$stmt->bindValue(":name", empty($val) ? null : $val);

と書きたいところですが、それでは困る感じでしょうか。でしたら冗長ですが

$stmt->bindValue(":name", !isset($val) || $val === "" ? null : $val);

ぐらいが妥当だと思います。エラー抑制して

$stmt->bindValue(":name", @$val == "" ? null : $val);

とする手もありますが、個人的にはこれはちょっと嫌ですね。エラーを発生するだけでパフォーマンスは大きく落ちるので、このようなコーディングを局所的にでもすることは避けるべきだと思います。塵も積もれば山となってしまうので、このような癖をつけるのはやめましょう。
(※ なお、この場合は === ではなく == にする必要があります)


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


さて、ちょっと見方を変えたソリューションを導きましょう。

【NULLや空文字列を代入して初期化しておく】

そもそも未定義かもしれない変数を使用する時点でコードが冗長になることは避けられません。これをあらかじめ初期値を代入しておくことでシンプルさを維持できます。今回の例の場合、NULLよりも空文字列を代入しておく方が型に一貫性が確保できるので望ましいと思います。

$val = "";
....
$stmt->bindValue(":name", $val === "" ? null : $val);

あとここまで書いていて気付いたのですが、bindValueは自分で型を指定しなければなりませんね。このままのコードだと全部デフォルトの文字列(PDO::PARAM_STR)が使われて文字列にキャストされてしまうので、NULLにすべきときは(PDO::PARAM_NULL)を使いましょう。

$val = "";
....
if ($val === "") {
$stmt->bindValue(":name", null, PDO::PARAM_NULL);
} else {
$stmt->bindValue(":name", $val);
}
    • good
    • 0
この回答へのお礼

再度のアドバイス、ありがとうございます。

最初にnullや空文字で初期化しておく・・・たしかにそうしておくのが一番ですね。

それで、最後に部分のbindValueですが、型指定については以前こちらで聞いたりネットで調べたりしたんです。そのときの質問がこちらです。
http://oshiete.goo.ne.jp/qa/8478452.html

bindValueは全て文字列にキャストされてしまうようで、PDO::PARAM_INTとかは意味ないみたいですね。

で、

$stmt->bindValue(":name", null, PDO::PARAM_NULL);

ですが、

$stmt->bindValue(":name", null);

できちんとnullが入っているので問題ない気がしますが、どうでしょうか?

お礼日時:2014/07/18 01:24

エラーチェックの関数で、エラーが出るのでは困りものですが、


処理や変数の前に@をつけるとエラーを非表示にできます。
ちゃんとあるんですねぇ。

呼び出し時に、
@is_null_ex($value)

これは試していませんが、どうなんでしょうか。
is_null_ex(@$value)
function is_null_ex(@$value){
function @is_null_ex($value){
    • good
    • 0
この回答へのお礼

ありがとうございます。
エラー出さないように、@つけるとそういえばエラー出力しませんでしたね。

お礼日時:2014/07/18 01:12

#3です


まあ私の方法を使うことはないとして、勘違いがあるようなので1点だけ補足。

>文字列を直接入れることは想定していないです。

変数名を文字列として渡してチェックするという意味です
ご理解いただいているとおり未定義の変数が渡せないのであれば
該当する変数名を文字列でわたせばチェックができます。

$x=1;
$y="x";
print $$y;//→出力「1」

というロジックです
    • good
    • 0
この回答へのお礼

ああすみませんでした。
そのことに気づいていませんでした…。

お礼日時:2014/07/18 01:11

issetとemptyは変数シンボルを対象にする関数ではない特別な構文なので、通常の考え方でラッパー関数を書くことは出来ません。

所々で毎回issetを記述するしかないです。参照渡しにすれば例外的にエラーを発生せずにNULLを自動代入出来ますが、個人的な考え方としては「未定義」と「NULL」は一緒くたにしてはいけないと思うので、このやり方は非推奨です。

Qiita - PHPでの参照渡し
http://qiita.com/akisssa/items/342d742c6ce9cd30b …
(実はこれ大部分私の編集リクエストなんですがw)

但し、 isset($_POST['test']) のようにスーパーグローバル変数を対象にする場合はこれを効率化する関数があります。以下の記事中で紹介しているfilter_input関数です。

Qiita - $_GET, $_POSTなどを受け取る際の処理
http://qiita.com/mpyw/items/2f9955db1c02eeef43ea
    • good
    • 0
この回答へのお礼

ありがとうございます!

issetとか、普通の関数じゃない気はしていました…。

>個人的な考え方としては「未定義」と「NULL」は一緒くたにしてはいけないと思うので、このやり方は非推奨です

はい、そこはわかっています。
で、なぜnullとしたいかというと、引数の変数が「未定義」「null」「""(空白)」の場合に、データベースの値をnullにしたかったからです。

$stmt->bindValue(":name", is_null_ex($val) ? null : $val);

みたいな感じです。

filter_inputですが、スーパーグローバル変数を対象にすることはないので使用しませんでした。

お礼日時:2014/07/15 09:00

変数そのものを判定するのに、変数の内容を渡すからそういうことになるんですよ。


認識の誤りです。

参照形で変数そのものを渡すべきです。
参照形では、関数内で未定義の変数に直接値を代入することができません。

PHPでの参照渡し:
関数定義で引数に & をつけると、関数内で扱う変数名が呼び出し元のスコープに存在する変数名の エイリアス のようになる。
    • good
    • 0
この回答へのお礼

ありがとうございます。

たしかにおっしゃる通りでした…。

実はこの参照渡し、いろんな言語で使ったりCのポインタとか、
もうごちゃごちゃしていてよくわからないんですよね。

もっと勉強しないとダメですね…。

お礼日時:2014/07/15 08:53

まぁあまり頭のいい方法ではないですが



is_null_ex("val");
のように文字列で渡す手もあるかと、

その場合
function is_null_ex($value){
global $$value;
うんたらかんたら
}

と、関数外の変数を参照するためglobalで参照しないといけないかも。
クラスを使っていればそれにあわせてください
    • good
    • 0
この回答へのお礼

ありがとうございます。

文字列を直接入れることは想定していないです。
そもそも未定義の変数が引数の場合にnullと判定したかったので・・・。

お礼日時:2014/07/15 08:50

http://php.net/manual/ja/function.set-error-hand …
set_error_handler — ユーザー定義のエラーハンドラ関数を設定する

この辺を工夫してなんとか実装するしか方法はないでしょうね。
    • good
    • 0
この回答へのお礼

ありがとうございます!
なかなか面倒なことですね…。

お礼日時:2014/07/15 08:44

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!