4349
度々失礼します。

データベース(MySQL)にOR検索をかけて、結果の一覧を表示するプログラムを作っています。

質問の内容が前回と似通っているとは思いましたが、今回は前回解決した内容をコードに組み込んだ状態で の事でしたので再度質問をさせていただきました。
また、今回は前回とコードの書き方に違いが多くあるのでそちらも再度質問をさせていただいた理由になります。

テーブル名：goods カラム名：name カラムの内容：りんご バナナ みかん りんす ミカルゲ

SQL文を作成するところまではできていると思うのですが、どう表示させたら良いのかが分かりません。

while文を配列の個数分回して、中でforeachを使って表示するのかと思って以下のコードを書いてみたのですが、結果は「データベースに登録がありました」と出るもののデータ自体は表示されません。

前回解決した時の原因として、echoが足りなかったところにはecho(自分はprintです)を、SQL文の必要な部分に半角スペースを入れていなかったことによるエラーに関しても必要部分に半角スペースを入れて対処してあります。

```

    <?php
    //  HTTPヘッダーで文字コードを指定
    header("Content-Type:text/html; charset=UTF-8");
    ?>
    <?php
    
    //h()関数の読み込み
    require_once 'lib/h.php';
    //checkinput()関数の読み込み
    require_once 'lib/checkinput.php';
    
    //POSTされたデータのチェック
    $_POST = checkinput($_POST);
    
    //三項演算子で検索文字列の有無を判定し処理
    $data = isset($_POST['data']) ? trim($_POST['data']) : '';
    //OR検索
    $query = 'SELECT * FROM goods WHERE ';  //クエリ前半
    if($data){
        $count = 1; //カウントを１にしておく
        $data = trim($data); //検索文字列の前後の空スペースだけを除去
        //全角スペースはmb_convert_kana()関数で半角スペースに変換
        $datalist = mb_convert_kana($data, 's');
        //複数キーワードでの検索
        if(stristr($datalist," ")){
            //検索ワードをスペースで分割して配列に格納
            $keyword = explod(" ",$datalist);
            //配列の数を数える
            $count = count($datalist);
            //空スペースで区切られた数によってSQL文を組み立てる
            for($i=0; $i<$count; $i++){//配列の数だけ繰り返す
                if($i!="0"){
                    $sql = $sql."OR";
                }
            $sql = $sql." name LIKE :$datalist".$i;
            }
        }
    }else{
        $count = 0;
    }
    //SQL文準備
    $query = $query.$sql;
    ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
    <head>
    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
    <meta http-equiv="content-script-type" content="text/javascript" />
    <meta http-equiv="content-style-type" content="text/css" />
    <!--  StyleSheet記述
    <link rel="stylesheet" href="./css/main.css" type="text/css" media="all" />
    StyleSheet記述  -->
    <!-- PAGE TITLE -->
    <title>ページタイトル</title>
    </head>
    <body>
    <?php
    if(!empty($datalist)){
    
        try{
            $username = "root";
            $password = "root";
            $pdo = new PDO(
                'mysql:host=localhost;dbname=shop',
                $username,
                $password,
                array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
    
            //プリペアドステートメントのエミュレーションを無効にする
            $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
            //エラーが発生した場合、例外がスローされるようにする
            $pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    
            //検索結果
            if($datalist <> ""){//検索窓が空なら検索しない
                //単ワードでの検索時
                if($count == 1){
                    $datalist2 = '%'.$datalist.'%'; //検索文字列を%検索文字%とする
                    $stmt = $pdo->prepare("SELECT * FROM goods WHERE name LIKE :datalist");
                    $stmt->bindParam(':datalist',$datalist2,PDO::PARAM_STR);
                    $stmt->execute();
            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
                }
            }//OR検索時
            elseif($count > 1){
                $stmt = $pdo->prepare($query);
                for($i=0; $i<$count; $i++){ //検索ワードの数だけ繰り返す
                    $keyword2[$i] = '%'.$keyword.'%';   //検索ワード1つ1つを%検索文字%にする
                    $holder = ':datalist'.$i;   //ホルダー用
                    $stmt->bindParam($holder,$keyword2[$i],PDO::PARAM_STR);
                    }
                $stmt->execute();       
                $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
            }
    
    
            if(count($result) == 0){
                print '<p>「'.h($data).'」はデータベースに登録がありません</p>';
            }else{
                print '<p>「'.h($data).'」はデータベースに登録がありました</p>';
    ?>
                <p>検索結果</p>
                <table>
                <tr>
                    <th>商品名</th>
                    <th>価格</th>
                </tr>
    
    <?php
                while($count > count($result)){
                foreach ($result as $row){
    ?>
                <tr>
                    <td><?php print h($row['name']) ?></td>
                    <td><?php print h($row['price']) ?></td>
                </tr>
    <?php
                }
            }
                print '</table>';
            }
    
    //接続でいない場合、PDOException例外がスローされるのでキャッチする
        }catch(PDOException $e){
            print 'エラーが発生しました。。　内容：' . h($e->getMessage());
        }
    }
    ?>
    <p>検索したい文字列を入力</p>
    <form action="list_s.php" method="POST" >
    <input type="search" name ="data">
    <input type="submit" value="検索">
    </form>
    </body>
    </html>
    
```

それと些細なことなのですが、

```

    $query = $query.$sql;
    
```

この部分で`Undefined variable: sql` というエラーが出てしまいます。
$sqlが定義されていないというエラーだと思うのですが、上のfor文の中のif文で既に使われているので原因が分かっていません。
こちらについてもよろしければご指摘ください。

よろしくお願いします。
CC BY-SA 3.0
2015-01-06T11:36:23.017
3191
2015-01-09T20:39:57.063
2015-01-06T11:41:23.633
3639
5985
question
php mysql
OR検索をした結果の表示方法
たぶんデータベースからデータを取れていないと思います。

前半の $query 変数に入れる SQL 文を作るところ、後半のクエリを実行するところで、

  1. explode() が explod() になている
  2. count($datalist) は、文字列をカウントしているので、常に1が返る
  3. OR の前後にスペースがない
  4. PDO ライブラリの使い方を間違えている

ので、正しい SQL 文が実行されてません。例外が発生していないとすると、失敗した fetchAll() が false
を返しているのではないかと思います。undefined は、スコープから外れてるからでしょう。

こんな感じでどうでしょう? h() が何をやっているのかわからないので、htmlspecialchars() にしました。

```

    <?php
    $query_string       = 'SELECT * FROM goods WHERE';
    $where_clause       = ' 1=1 ';
    $search_words_num   = 0;
    $search_words_array = array();
    if($data){
        $search_words_string = mb_convert_kana($data, 's');
        $search_words_string = trim($search_words_string);
        $tmp_array  = explode(' ', $search_words_string);
        $search_words_num    = count($tmp_array);
        $where_clause       .= 'AND (';
        while ($search_words_num--) {
            $where_clause        .= "(name LIKE ?)";
            $search_words_array[] = '%' . $tmp_array[$search_words_num] . '%';
            if ($search_words_num != 0)
                $where_clause .= ' OR ';
        }
        $where_clause .= ')';
    }
    
    $query_string .= $where_clause;
    
    if (!empty($data)) {
        try {
            $pdo = new PDO('mysql:host=localhost;dbname=shop',
                           'root', 'root',
                           array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
            $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
            $pdo->setAttribute(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
            $statement = $pdo->prepare($query_string);
            $statement->execute($search_words_array);
            $results = $statement->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            /* 例外処理省略 */
        }
    
        if (empty($results) || $results === false) {
            echo '<p>No entry was found.</p>';
        } else {
    ?>
        <p>検索結果</p>
        <table>
            <tr>
                <th>商品名</th>
                <th>価格</th>
            </tr>
    <?php
            foreach ($results as $name => $price) {
                echo '<tr>';
                echo '<td>' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</td>';
                echo '<td>' . htmlspecialchars($price, ENT_QUOTES, 'UTF-8') . '</td>';
                echo '</tr>';
            }
    ?>
        </table>
    <?php
        }
    }
    ?>
    
```
CC BY-SA 3.0
2015-01-09T20:39:57.063
4349
2015-01-09T20:39:57.063
5873
3191
answer