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

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

ただいまの
回答率

90.51%

  • PHP

    20416questions

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

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

解決済

回答 3

投稿

  • 評価
  • クリップ 2
  • VIEW 208

ogura87

score 96

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

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

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

$sql = "SELECT * FROM rk_list";
$jyoken = 0;

// タイプ
if ($typeno > 0){
    if($jyoken == 0){
        $sql = $sql . " where ";
        $jyoken = 1;
    }else{
        $sql = $sql . " and ";
    }
     $sql = $sql . "typeno = " . $typeno;
}

// 価格1
if ($price1 > 0){
    if($jyoken == 0){
        $sql = $sql . " where ";
        $jyoken = 1;
    }else{
        $sql = $sql . " and ";
    }
     $sql = $sql . "price >= " . $price1;
}

// 価格1
if ($price2 > 0){
    if($jyoken == 0){
        $sql = $sql . " where ";
        $jyoken = 1;
    }else{
        $sql = $sql . " and ";
    }
     $sql = $sql . "price <= " . $price2;
}

// 年
if ($year > 0){
    if($jyoken == 0){
        $sql = $sql . " where ";
        $jyoken = 1;
    }else{
        $sql = $sql . " and ";
    }
    if($year == "2016
        $sql = $sql . "year <= " . $year;
    }else{
        $sql = $sql . "year = " . $year;
    }
}

$sql = $sql . ";";

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

SELECT * FROM rk_list;

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

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

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

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

<?php

$sql    = 'SELECT * FROM rk_list';

$typeno = 3;
$price1 = 1000;
$price2 = 3000;
$year   = 2016;

// 条件配列を作る
$input = array();

if ( $typeno > 0 ) {
    $input[] = array(
        'key'     => 'typeno',
        'value'   => $typeno,
        'compare' => '=',
    );
}

if ( $price1 > 0 ) {
    $input[] = array(
        'key'     => 'price',
        'value'   => $price1,
        'compare' => '>=',
    );
}

if ( $price2 > 0 ) {
    $input[] = array(
        'key'     => 'price',
        'value'   => $price2,
        'compare' => '<=',
    );
}

if ( $year > 0 ) {
    $input[] = array(
        'key'     => 'year',
        'value'   => $year,
        'compare' => 2016 === $year ? '<=' : '=',
    );
}

// where 句を作る
$where = implode(
    ' and ', array_map(
        function ( $query ) {
            // key = value のような形に加工
            return implode( ' ', array( $query['key'], $query['compare'], $query['value'] ) );
        }, $input
    )
);

// 空じゃない場合のみ where を先頭につける
$where = empty( $where ) ? '' : ' where ' . $where;

// 合体!
$sql = $sql . $where . ';';

echo $sql;
// SELECT * FROM rk_list where typeno = 3 and price >= 1000 and price <= 3000 and year <= 2016;

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/16 21:24

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

    キャンセル

  • 2018/07/16 21:30

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

    キャンセル

  • 2018/07/16 22:24 編集

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

    キャンセル

  • 2018/07/17 00:48

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

    キャンセル

+3

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/16 21:24

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

    キャンセル

+1

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

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

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

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

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

ご覧のように、WHERE句の断片を配列に追加していき、同時に型と値も別の配列に追加しているだけです。
面倒なように見えるかもしれませんが、単純な繰り返しなので、難しくはないと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/17 00:49

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

    キャンセル

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

  • ただいまの回答率 90.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    20416questions

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