• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:DBのWHERE~ANDの使い分けをphpで処理)

DBのWHERE〜ANDの使い分けをphpで処理する方法

このQ&Aのポイント
  • phpを使用して、DBのWHERE〜ANDを適切に処理する方法について解説します。
  • 30個のinput値を取得し、それぞれの値に基づいてWHERE句を動的に作成します。
  • また、input値が存在する場合にのみWHERE句を生成し、値に基づいて絞り込みを行います。

質問者が選んだベストアンサー

  • ベストアンサー
  • LancerVII
  • ベストアンサー率51% (1060/2054)
回答No.2

こんにちは。 何故エラーになるかのエラー内容を添付してもらえると回答が付き易いと思います。 また、SQLのエラーの場合はどういうSQLが生成されたかをprint等で画面に表示してみると修正のきっかけ見つかるかもしれません。 以下のような感じで実装できると思います。 入力内容のチェック等セキュリティについては省いていますのでその辺は実装して下さい。 またPOSTで書いています。ここは環境に合わせて下さい。 動作原理としてはパラメータ名とカラム名が違うのでそれを紐付ける連想配列を用意しています。 これによりformから送信されたパラメータ名がどのカラムであるか判断します。 あとは送られてきたパラメータとカラム名を紐付けながら条件を生成します。 ループ内での判断が面倒でしたので必ず" and カラム名='パラメータ値'"で条件を生成しておきます。 そのまま処理をすると select * from TABLENAME where and id='value' というSQLになってしまいますので and以降をwhereにくっつけます。 <?php // パラメータ名とカラム名を紐付けるマップ $key = array ( 'aaaaa' => 'id', 'bbbbb' => 'name', 'ccccc' => 'textdata', 'ddddd' => 'value1' ); if ( isset($_POST) ) { $sql = "select * from TABLENAME"; $where = ""; foreach ( $_POST as $k => $v ) { // 送信内容をループ if ( isset($key[$k]) && $_POST[$k] !== "" ) { // 送信内容のキーがカラム名マップに存在し、 // 送信内容が入力されていたら条件に追加 $value = mb_convert_encoding ( $_POST[$k],"UTF-8" ); $where .= " and " . $key[$k] . "='" . $value . "'"; } } if ( strlen($where) > 0 ) { // 条件が追加されている場合はSQLに追加する // $whereの先頭には" and"が無条件に入っているためand以降をwhereに追加する $where = " where " . substr($where,4); $sql .= $where; } } ?>

juju-juju
質問者

お礼

mb_convert_encodingとhtmlentitiesをまとめていっぺにできる方法があったので、それも使って直してみました。ちゃんと動くようになりました。ありがとうございます。 >if ( isset($key[$k]) && $_POST[$k] !== "" ) { 空白のチェックで != としないで !== するのは「0」への対策ですか? <?php mb_http_output('UTF-8'); mb_internal_encoding('UTF-8'); //-------------------------- //初めの値を設定 //-------------------------- $get['aaaaa'] = ""; $get['bbbbb'] = ""; $get['ccccc'] = ""; //30個分つづきます。 $get['zzzzz'] = 10; //表示数 $get['ppppp'] = 1; //ページの番号 //-------------------------- //$_GETは全部、中身がどうあれ処理させます function abcdef($str) { $str = mb_convert_encoding($str, "UTF-8", "UTF-8"); $str .= htmlentities($str, ENT_QUOTES, "UTF-8"); return $str; } if (isset($_GET)){ foreach($_GET as $key => $val){ $get[$key] = abcdef($val); } } $key = array( $get['aaaaa']=>'id', $get['bbbbb']=>'name', $get['ccccc']=>'textdata' ); $my_1 = "SELECT * FROM infotable"; $where = ''; foreach($key as $k => $v){ if(isset($key[$k]) && $key[$k] !== ''){ $where .= " AND ".$key[$v]."='".$key[$k]."'"; } } if(strlen($where)>0){ $where = " where ".substr($where,4); $my_1 .= $where; } $my_2 = $my_1." ORDER BY id LIMIT 0,10"; $my_3 = "SELECT COUNT(*) AS CNT FROM tablename WHERE id='".$get['aaaaa']."' AND name='".$get['bbbbb']."'"; mysql_set_charset('utf8'); $my_1_q = mysql_query($my_1,$mysql); $my_2_q = mysql_query($my_2,$mysql); $my_3_q = mysql_query($my_3,$mysql);

その他の回答 (2)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

条件設定がない場合は「全て表示する」のか「一つも表示しない」のかで 処理がことなります。 今回のケースだと基本的に全て表示し、条件が提示されたとき 完全一致でAND絞り込みをしていくという流れにみえます 全て表示するのは「WHERE 1」としておくと便利です 絞り込みはあとANDでつないでいくだけです。 また、他のSQLで同じwhere条件を使うのであれば関数化するのが妥当です <?PHP $sql="SELECT * FROM hoge"; $sql.=setWhere(); function setWhere() { $str=" WHERE 1"; $list=array( "aaaaa"=>"id" ,"bbbbb"=>"name" ,"ccccc"=>"textdata" ); foreach($list as $key=>$val){ if(!isset($_REQUEST[$key]) or $_REQUEST[$key]==='') continue; $str.=" AND `".$val."`='".mysql_real_escape_string($_REQUEST[$key])."'"; } return $str; } print $sql; ?> <form> <input type="text" name="aaaaa" value=""><br> <input type="text" name="bbbbb" value=""><br> <input type="text" name="ccccc" value=""><br> <input type="submit" value="go"> </form>

juju-juju
質問者

お礼

mb_convert_encodingとhtmlentitiesをまとめていっぺにできる方法があったので、それも使って直してみました。ちゃんと動くようになりました。すごく参考になりました。 >WHERE 1 SELECT * FROM tablename; SELECT * FROM tablename WHERE 1; どっちが早いですか? <?php mb_http_output('UTF-8'); mb_internal_encoding('UTF-8'); //-------------------------- //初めの値を設定 //-------------------------- $get['aaaaa'] = ""; $get['bbbbb'] = ""; $get['ccccc'] = ""; //30個分つづきます。 $get['zzzzz'] = 10; //表示数 $get['ppppp'] = 1; //ページの番号 //-------------------------- //$_GETは全部、中身がどうあれ処理させます function abcdef($str) { $str = mb_convert_encoding($str, "UTF-8", "UTF-8"); $str .= htmlentities($str, ENT_QUOTES, "UTF-8"); return $str; } if (isset($_GET)){ foreach($_GET as $key => $val){ $get[$key] = abcdef($val); } } $list = array( $get['aaaaa']=>'id', $get['bbbbb']=>'name', $get['ccccc']=>'textdata' ); $my_1 = "SELECT * FROM tablename"; $my_1 .= setWhere($list); function setWhere($param){ $str = ' WHERE 1'; foreach($param as $key => $val){ if(!isset($key) or $key==='') continue; $str .= " AND ".$val."='".$key."'"; } return $str; } $my_2 = $my_1." ORDER BY id LIMIT 0,10"; $my_3 = "SELECT COUNT(*) AS CNT FROM tablename WHERE id='".$get['aaaaa']."' AND name='".$get['bbbbb']."'"; mysql_set_charset('utf8'); $my_1_q = mysql_query($my_1,$mysql); $my_2_q = mysql_query($my_2,$mysql); $my_3_q = mysql_query($my_3,$mysql);

  • _if_
  • ベストアンサー率52% (26/50)
回答No.1

まず if(isset($aaaaa) && strlen($aaaaa)>0){  $aaaaa = mb_convert_encoding($_GET['aaaaa'], "UTF-8");  htmlentities($aaaaa, ENT_QUOTES);  $test1["id"] = $aaaaa; } の、1行目の$aaaaa は定義済みですか? 2行目に初めて$_GETからの代入があるように見受けられます。 それと、3行目の変換はスルーされています。 とりあえず、正確な書き方は偉人達にお任せして、大雑把にイメージですが、 function strConv( $strIn = "", &$strOut ) {  if( strlen($strIn) ) {   $strOut = $strIn;   $strOut = mb_convert_encoding( $strOut, "UTF-8" );   $strOut = htmlentities( $strOut, ENT_QUOTES );   return 1;  }  return 0; } をどっかに置いて if( isset( $_POST['aaaaa'] ) && strConv( $_POST['aaaaa'], $str ) ) $test1['id'] = $str; if( isset( $_POST['bbbbb'] ) && strConv( $_POST['bbbbb'], $str ) ) $test1['name'] = $str; などにすればすっきりはします。 次に、SQL作成部ですが、、、 foreach($test1 as $key => $value){$test2 = $key;} とありますが、コピーミスなのか、オリジナルがこうなっているのか・・・。 $test2は値が1つだけしか入ってませんよ。 あと、while($test1--){...} はphpの文法にはないのではないでしょうか? まずは、落ち着いて都度print_rなりechoなりで出力して状況を確かめてみるといいかと思われます。 また、phpはエラーが親切なので、それも記載されると的確な回答がしやすくなります。 ご参考になればいいのですが。

juju-juju
質問者

お礼

いろいろ調べてみるとクエリの作成でなくて、ご指摘して頂いた通りphpの使い方が間違っていました。 >function strConv( $strIn = "", &$strOut ) { strConv( $_POST['aaaaa'], $str ) function strConv( $strIn = "", &$strOut ) { strConvの第一引数の意味は、$_POST['aaaaa']に値が入っていても""にするということですか? あと&$strOutの&をつけるとreturnで返さなくても自動で返すようになるのですか?

関連するQ&A