質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

313閲覧

このPHPソースをすっきりさせる為のいい案無いでしょうか?

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

2クリップ

投稿2018/07/16 11:13

PHPでSQLを組み立てて実行するプログラムを書いています。

ただ、この手のプログラム、書くのはそれほど苦ではないのですが、綺麗にと言いますか、コンパクトに無駄がなくまとめるのが苦手なのです。

例えば、このプログラム、

php

1$sql = "SELECT * FROM rk_list"; 2$jyoken = 0; 3 4// タイプ 5if ($typeno > 0){ 6 if($jyoken == 0){ 7 $sql = $sql . " where "; 8 $jyoken = 1; 9 }else{ 10 $sql = $sql . " and "; 11 } 12 $sql = $sql . "typeno = " . $typeno; 13} 14 15// 価格1 16if ($price1 > 0){ 17 if($jyoken == 0){ 18 $sql = $sql . " where "; 19 $jyoken = 1; 20 }else{ 21 $sql = $sql . " and "; 22 } 23 $sql = $sql . "price >= " . $price1; 24} 25 26// 価格1 27if ($price2 > 0){ 28 if($jyoken == 0){ 29 $sql = $sql . " where "; 30 $jyoken = 1; 31 }else{ 32 $sql = $sql . " and "; 33 } 34 $sql = $sql . "price <= " . $price2; 35} 36 37// 年 38if ($year > 0){ 39 if($jyoken == 0){ 40 $sql = $sql . " where "; 41 $jyoken = 1; 42 }else{ 43 $sql = $sql . " and "; 44 } 45 if($year == "2016 46 $sql = $sql . "year <= " . $year; 47 }else{ 48 $sql = $sql . "year = " . $year; 49 } 50} 51 52$sql = $sql . ";";

つまり、フォームで入力された値を元にWhere句を組み立てているのですが、未入力もありなので、何も入力されなければ、

SELECT * FROM rk_list;

で終わりなのですが、条件が入力された場合は、最初の条件の場合は前に"Where"を付け、2個め以降は、"and"でつないでいくので、項目ごとに最初かどうかの判定を入れており、大変冗長性のある、長いプログラムになってしまっています。

こういうの、なんとか条件判定分を減らし、でも、あまりにトリッキーではなく、見やすい、いい方法は無いかと思いまして。。。

一人で考えているのも煮詰まってしまっていますので、誰か一緒に考えて頂けないかと。。。

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

コード書いてる間に回答出てた…。せっかくなので貼っておきます。
maisumakun さんの2番目の手にあたります。

php

1<?php 2 3$sql = 'SELECT * FROM rk_list'; 4 5$typeno = 3; 6$price1 = 1000; 7$price2 = 3000; 8$year = 2016; 9 10// 条件配列を作る 11$input = array(); 12 13if ( $typeno > 0 ) { 14 $input[] = array( 15 'key' => 'typeno', 16 'value' => $typeno, 17 'compare' => '=', 18 ); 19} 20 21if ( $price1 > 0 ) { 22 $input[] = array( 23 'key' => 'price', 24 'value' => $price1, 25 'compare' => '>=', 26 ); 27} 28 29if ( $price2 > 0 ) { 30 $input[] = array( 31 'key' => 'price', 32 'value' => $price2, 33 'compare' => '<=', 34 ); 35} 36 37if ( $year > 0 ) { 38 $input[] = array( 39 'key' => 'year', 40 'value' => $year, 41 'compare' => 2016 === $year ? '<=' : '=', 42 ); 43} 44 45// where 句を作る 46$where = implode( 47 ' and ', array_map( 48 function ( $query ) { 49 // key = value のような形に加工 50 return implode( ' ', array( $query['key'], $query['compare'], $query['value'] ) ); 51 }, $input 52 ) 53); 54 55// 空じゃない場合のみ where を先頭につける 56$where = empty( $where ) ? '' : ' where ' . $where; 57 58// 合体! 59$sql = $sql . $where . ';'; 60 61echo $sql; 62// SELECT * FROM rk_list where typeno = 3 and price >= 1000 and price <= 3000 and year <= 2016;

投稿2018/07/16 11:43

yhg

総合スコア2161

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/07/16 12:24

おお~。なるほど! これぞプロのソースですね! ありがとうございました!
退会済みユーザー

退会済みユーザー

2018/07/16 12:30

このコードSQLインジェクションの脆弱性ありますよ。
yhg

2018/07/16 13:24 編集

主旨と違うのでSQLインジェクションについては考慮してません。 return implode( ' ', array( $query['key'], $query['compare'], '?') ); とでもしておけば簡単に対応できると思います。
退会済みユーザー

退会済みユーザー

2018/07/16 15:48

なるほど。奥が深いですね。
guest

0

よくある手としては2つあります。

  • 最初にWHERE 1 = 1のようなダミーの条件を入れて、残りはすべて機械的にANDでつなぐ
  • 条件を配列に入れておいて、ANDimplodeする

投稿2018/07/16 11:28

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/07/16 12:24

あ、WHERE 1 = 1は以前、パッケージソフトのコードで見かけて、何なんだろうと思っていましたが、そういう事でしたか。。 ありがとうございました!
guest

0

SQL の組み立ては、組立自体よりもデータのバインドの方に気を使ったほうが良いです。

回答はコピペですが参考まで。
参考コードは多分未完です。型を使用したバインドが完成形だと思います。

条件検索におけるプリペアドステートメントの使用
escape_wildcard()の実装は、本を買って確認してくださいw

answerer ockeghem [12月18日 17:19]

検索条件が動的に変わる場合、プレースホルダ(プリペアードステートメント)をどう使って良いかはよくある質問だと思います。「体系的に学ぶ 安全なWebアプリケーションの作り方」という本のP135にサンプルが出ています。以下に該当する部分を引用します。

php

1 // 基本となるSQL 2 $sql = 'SELECT id, title, author, publisher, date, price FROM books'; 3 if ($title !== '') { // 検索条件titleの追加(LIKE) 4 $conditions[] = "title LIKE ? ESCAPE '#'"; 5 $ph_type[] = 'text'; 6 $ph_value[] = escape_wildcard($title); 7 } 8 if ($price !== '') { // 検索条件priceの追加(大小比較) 9 $conditions[] = "price <= ?"; 10 $ph_type[] = 'integer'; 11 $ph_value[] = $price; 12 } 13 if (count($conditions) > 0) { // WHERE句がある場合 14 $sql .= ' WHERE ' . implode(' AND ', $conditions); 15 } 16 $stmt = $mdb2->prepare($sql, $ph_type); // SQL文の準備 17 $rs = $stmt->execute($ph_value); // バインド・問い合わせ実行

ご覧のように、WHERE句の断片を配列に追加していき、同時に型と値も別の配列に追加しているだけです。

面倒なように見えるかもしれませんが、単純な繰り返しなので、難しくはないと思います。

投稿2018/07/16 12:42

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/07/16 15:49

なるほど。ありがとうございます! 勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問