![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
自作の関数で、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系で運用しています。
ぞうぞよろしくお願い致します。
No.2ベストアンサー
- 回答日時:
に
PHPでは原則的に未定義の変数の値を取得しようとしたときに Notice が発生して NULL 扱いになるが、参照渡しのデフォルト値の場合だけ例外的にNoticeを発生せずにNULLとして初期化される。
と書いてある。
上記のページに「強引な解決方法」が書いてあるけど、ページ読んで意味や方法が判らない場合は諦めるべし。
No.9
- 回答日時:
>> $stmt->bindValue(":name", null, PDO::PARAM_NULL);
>> ですが、
>> $stmt->bindValue(":name", null);
>> できちんとnullが入っているので問題ない気がしますが、どうでしょうか?
NULLだけが特別視されると考えるのが良さそうです。SELECTで抜き出してくる時もNULLだけは型を保っていますし、言われてみれば当然の挙動だったかもしれません。検証有難うございます。
No.8
- 回答日時:
>> $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);
}
再度のアドバイス、ありがとうございます。
最初に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が入っているので問題ない気がしますが、どうでしょうか?
No.7
- 回答日時:
エラーチェックの関数で、エラーが出るのでは困りものですが、
処理や変数の前に@をつけるとエラーを非表示にできます。
ちゃんとあるんですねぇ。
呼び出し時に、
@is_null_ex($value)
これは試していませんが、どうなんでしょうか。
is_null_ex(@$value)
function is_null_ex(@$value){
function @is_null_ex($value){
No.6
- 回答日時:
#3です
まあ私の方法を使うことはないとして、勘違いがあるようなので1点だけ補足。
>文字列を直接入れることは想定していないです。
変数名を文字列として渡してチェックするという意味です
ご理解いただいているとおり未定義の変数が渡せないのであれば
該当する変数名を文字列でわたせばチェックができます。
$x=1;
$y="x";
print $$y;//→出力「1」
というロジックです
No.5
- 回答日時:
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
ありがとうございます!
issetとか、普通の関数じゃない気はしていました…。
>個人的な考え方としては「未定義」と「NULL」は一緒くたにしてはいけないと思うので、このやり方は非推奨です
はい、そこはわかっています。
で、なぜnullとしたいかというと、引数の変数が「未定義」「null」「""(空白)」の場合に、データベースの値をnullにしたかったからです。
$stmt->bindValue(":name", is_null_ex($val) ? null : $val);
みたいな感じです。
filter_inputですが、スーパーグローバル変数を対象にすることはないので使用しませんでした。
No.4
- 回答日時:
変数そのものを判定するのに、変数の内容を渡すからそういうことになるんですよ。
認識の誤りです。
参照形で変数そのものを渡すべきです。
参照形では、関数内で未定義の変数に直接値を代入することができません。
PHPでの参照渡し:
関数定義で引数に & をつけると、関数内で扱う変数名が呼び出し元のスコープに存在する変数名の エイリアス のようになる。
ありがとうございます。
たしかにおっしゃる通りでした…。
実はこの参照渡し、いろんな言語で使ったりCのポインタとか、
もうごちゃごちゃしていてよくわからないんですよね。
もっと勉強しないとダメですね…。
No.3
- 回答日時:
まぁあまり頭のいい方法ではないですが
is_null_ex("val");
のように文字列で渡す手もあるかと、
その場合
function is_null_ex($value){
global $$value;
うんたらかんたら
}
と、関数外の変数を参照するためglobalで参照しないといけないかも。
クラスを使っていればそれにあわせてください
ありがとうございます。
文字列を直接入れることは想定していないです。
そもそも未定義の変数が引数の場合にnullと判定したかったので・・・。
No.1
- 回答日時:
set_error_handler — ユーザー定義のエラーハンドラ関数を設定する
この辺を工夫してなんとか実装するしか方法はないでしょうね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
フォントの色を変えるには?
-
Localeクラスについて
-
PHPでのPASSWORD一致確認処理に...
-
phpの imap_search で漢字コード
-
awsにApacheとPHPを入れて、何...
-
[php初心者]サイトを見てデータ...
-
phpでPEAR::DBを使っているので...
-
onedrive にexcelファイルをア...
-
.phpファイルが、表示されない
-
a href リンクタグでだけで 送...
-
リンク先を隠す方法はないでし...
-
文字化けについて
-
XserverでpearのDBでMySQLに接続
-
スケジュール共有管理ツールの...
-
バッチを用いたフォルダの自動移動
-
apacheで拡張子を省略してアク...
-
phpでファイルの先頭8バイトだ...
-
exec()で他ディレクトリのexeプ...
-
youtubeに音声のみのmp4ファイ...
-
stdinからの処理でメール情報を...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
フォントの色を変えるには?
-
[php初心者]サイトを見てデータ...
-
「@$変数」の「@の意味は?」
-
トランザクションが原因?DBに...
-
パースエラーとは?
-
PHP8を使うと、大量のWarningが...
-
error_reporting(0);にも関わら...
-
PHPでfatal errorが出ても無視...
-
PHPでネットワークドライブのop...
-
ある条件に当てはまったときに...
-
PHPにて外部サイト内容が取得不...
-
ワードプレスサイト PHP8.0.25...
-
PHPで、エラーがない場合のみ画...
-
SELECTの値を保持する
-
bindValueエラー
-
これは例外処理でしょうか?
-
phpでクラスのメソッドで同名の...
-
phpのエラー(T_LNUMBER)について
-
phpのrenameでエラーが出ます
-
phpでget_headers()が使えない?
おすすめ情報