まず前提。
インデントがあったりなかったりで非常に読みづらいです。
構文チェック及びコードフォーマット機能のあるエディタを利用するのはもちろん(できればIDEと呼ばれるものが望ましい)
自身でもインデントは意識してコードを組むようにしてください。
それに、提示コードには全角スペースが大量に入っています。
これでは回答者が手元で質問者さんの現象を正しく確認することができません。
※下記は全角スペース部分を除去し、Eclipseで整形した例
php
1 <?php
2 $maxrow = 50 ;
3 $pagenum = 0 ;
4
5 if ( isset ( $_GET [ 'pagenum' ] ) && is_numeric ( $_GET [ 'pagenum' ] ) ) {
6 $pagenum = $_GET [ 'pagenum' ] ;
7 }
8 $startrow = $pagenum * $maxrow ;
9
10 // 初期化
11 $err = "" ;
12 $key = "" ;
13 $condi = "" ;
14
15 $key = filter_input ( INPUT_GET , 'key' ) ;
16 $key = mb_convert_kana ( $key , "KVas" , 'UTF-8' ) ;
17 $key = explode ( " " , str_replace ( " " , " " , trim ( $key ) ) ) ;
18 $keys = array_filter ( $key , function ( $val ) {
19 return $val != '' ;
20 } ) ;
21
22 try {
23 $pdo = new PDO ( "mysql:host= $hostname ;dbname= $database ;charset=utf8" , $user , $pass ) ;
24 $pdo -> setAttribute ( PDO :: ATTR_EMULATE_PREPARES , false ) ;
25 $pdo -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION ) ;
26 // 入力キーワード処理
27 foreach ( $keys as $key => $value ) {
28 $condi .= sprintf ( 'AND contents1 LIKE :word%d' , $key ) ;
29 }
30
31 $ord = 0 ;
32 if ( isset ( $_GET [ 'ord' ] ) ) {
33 $ord = $_GET [ 'ord' ] ;
34 }
35 switch ( $ord ) {
36 case 1 :
37 $ord2 = "order by getday desc,upd desc,id desc" ;
38 break ;
39 case 2 :
40 $ord2 = "order by upd desc,id desc" ;
41 break ;
42 default :
43 $ord2 = "order by videoid desc" ;
44 break ;
45 }
46
47 if ( $condi ) {
48 $videoSQL = "SELECT * FROM video WHERE 1 $condi $ord2 " ;
49 } else {
50 $videoSQL = "SELECT * FROM video $ord2 " ;
51 }
52
53 // プリペアードステートメント
54 $stmt = $pdo -> prepare ( $videoSQL ) ;
55
56 // SQL文のプレースホルダーに値をバインド
57 for ( $i = 0 ; $i < count ( $keys ) ; $i ++ ) {
58
59 // 検索文字列の中のワイルドカード文字「_」「%」およびエスケープ文字「¥」をエスケープ
60 $like = preg_replace ( '/[_%\\]/u' , '\\$1' , $keys [ $i ] ) ;
61 $stmt -> bindValue ( ':word' . $i , '%' . $like . '%' , PDO :: PARAM_STR ) ;
62 }
63 // 実行
64 $stmt -> execute ( ) ;
65 $row_video = $stmt -> fetchAll ( PDO :: FETCH_ASSOC ) ;
66
67 // ページング用にLIMIT句のSQLを作成
68 $stt = $pdo -> prepare ( " $videoSQL LIMIT $startrow , $maxrow " ) ;
69 // SQL文のプレースホルダーに値をバインド
70 for ( $i = 0 ; $i < count ( $keys ) ; $i ++ ) {
71
72 // 検索文字列の中のワイルドカード文字「_」「%」およびエスケープ文字「¥」をエスケープ
73 $like = preg_replace ( '/[_%\\]/u' , '\\$1' , $keys [ $i ] ) ;
74 $stt -> bindValue ( ':word' . $i , '%' . $like . '%' , PDO :: PARAM_STR ) ;
75 }
76 $stt -> execute ( ) ;
77 $limit_video = $stt -> fetchAll ( PDO :: FETCH_ASSOC ) ;
78
79 if ( $stmt && $stt ) {
80 $tr_all = $stmt -> rowCount ( ) ;
81 $tp = ceil ( $tr_all / $maxrow ) - 1 ;
82 }
83 } catch ( PDOException $e ) {
84 $err .= "<span class=\"red\">サーバエラーです</span>" . htmlspecialchars ( $e -> getMessage ( ) ) ;
85 }
86
87 ?>
88 <! DOCTYPE html >
89 < html >
90 < body >
91 < p > 検索結果 </ p >
92 <?php
93
94 if ( $err ) {
95 echo "<p>" . $err . "</p>" ;
96 } else {
97 ?>
98
99 <?php if ( $tr_all ) { ?>
100 < p >
101 <?php if ( $ord != 2 ) { ?> < a href = " <?php echo $_SERVER [ "PHP_SELF" ] ; ?> ?ord=2 " > 最終更新日順 </ a > <?php } else { echo "最終更新日順" ; } ?> |
102 <?php if ( $ord != 1 ) { ?> < a href = " <?php echo $_SERVER [ "PHP_SELF" ] ; ?> ?ord=1 " > 撮影日順 </ a > <?php } else { echo "撮影日順" ; } ?> |
103 <?php if ( $ord != 0 ) { ?> < a href = " <?php echo $_SERVER [ "PHP_SELF" ] ; ?> ?ord=0 " > video
104 No.順 </ a > <?php } else { echo "video No.順" ; } ?>
105 </ p >
106
107 < form method = " GET " action = " " >
108 < input type = " text " name = " key " /> < input type = " submit " value = " 検索 " />
109
110 </ form >
111 < p > <?php if ( $condi ) { ?>
112 <?php echo $tr_all ; ?> 件中
113 <?php echo ( $startrow + 1 ) ; ?> ~ <?php echo min ( $startrow + $maxrow , $tr_all ) ; ?> 件を表示 </ p >
114 <?php } ?>
115 < p >
116 <?php if ( $pagenum ) { ?>
117 < a
118 href = " <?php echo $_SERVER [ "PHP_SELF" ] ; ?> ?pagenum=0&ord= <?php echo $ord ; ?> " > 1 </ a >
119 <?php
120
121 } else {
122 echo "1" ;
123 }
124 ?>
125 <?php
126 for ( $i = 0 ; $i < $tp ; $i ++ ) {
127 if ( ! ( $pagenum == ( $i + 1 ) ) ) {
128 echo " <a href=\"" . $_SERVER [ "PHP_SELF" ] . "?pagenum=" . ( $i + 1 ) . "&ord=" . $ord . "\">" . ( $i + 2 ) . "</a> |" ;
129 } else {
130 echo " " . ( $i + 2 ) . " |" ;
131 }
132 }
133 ?>
134 </ p >
135
136 < table >
137 < tr >
138 < td > 内容 </ td >
139 < td > video No. </ td >
140 < td > 入手・作成(最終更新) </ td >
141 </ tr >
142 <?php foreach ( $limit_video as $row ) { ?>
143 < tr >
144 < td > < a href = " video_detail.php?id= <?php echo $row [ 'id' ] ; ?> " >
145 <?php echo $row [ 'contents1' ] ; ?> </ a > </ td >
146 < td > <?php echo $row [ 'videoid' ] ; ?> </ td >
147 < td >
148 <?php
149 $getday = date ( "y/m/d" , strtotime ( $row [ 'getday' ] ) ) ;
150 $upd = date ( "y/m/d" , strtotime ( $row [ 'upd' ] ) ) ;
151 echo $getday . "(" . $upd . ")" ;
152 ?>
153 </ td >
154 </ tr >
155 <?php } ?>
156 </ table >
157
158
159 <?php } else { ?>
160 < p class = " l3 " > 検索結果が0件です </ p >
161 <?php } ?>
162 <?php } ?>
163
164 </ body >
165 </ html >
あと、下記、読んでください。
PDOStatement::rowCount
PDOStatement::rowCount() は 相当する PDOStatement オブジェクトによって実行された 直近の DELETE, INSERT, UPDATE 文によって作用した行数を返します。
中略
ほとんどのデータベースでは、PDOStatement::rowCount() は SELECT 文によって作用した行数を返しません。
代わりに、 PDO::query() を使って 意図する SELECT 文として同様の述部を持つ SELECT COUNT(*) 文を発行 し、PDOStatement::fetchColumn() を使って返される行数を取得することができます。 そうすることで、アプリケーションは正しい動作をすることができます。
rowCount()ではなくSQLでcount()を実行しましょう。
回答本編
キーワード検索の件
まず、PHPは度外視してどういう結果を得たいか、そのためにどういうSQLを組むべきか、から考えると良いです。
・検索キーワードが2つ以上でも検索できるようにしたい。
・検索対象のカラムを2つにしたい。現在contents1を検索対象にしていますが、contents2も検索対象にしたい。
となると、コードから「スペースで区切られたワードを分割する」
+
①「それぞれのワードを全て含むデータを探す」
②「それぞれのワードをいずれか含むデータを探す」
+
a.contents1またはcontents2にそれらを含む?
b.contents1とcontents2にそれらを含む?
↑①②ab それぞれどっちになるか 組み合わせによってコードが変わります。
①-a
sql
1 SELECT
2 *
3 FROM
4 video
5 WHERE
6 (
7 contents1 LIKE '%word1%'
8 AND contents1 LIKE '%word2%'
9 AND contents1 LIKE '%word3%'
10 )
11 OR
12 (
13 contents2 LIKE '%word1%'
14 AND contents2 LIKE '%word2%'
15 AND contents2 LIKE '%word3%'
16 )
17
②-a
sql
1 SELECT
2 *
3 FROM
4 video
5 WHERE
6 (
7 contents1 LIKE '%word1%'
8 AND contents1 LIKE '%word2%'
9 AND contents1 LIKE '%word3%'
10 )
11 AND
12 (
13 contents2 LIKE '%word1%'
14 AND contents2 LIKE '%word2%'
15 AND contents2 LIKE '%word3%'
16 )
17
まあ、ORかANDが変わるくらいで、構成はほぼ変わりません。(②-a,②-bも考えてみてください)
で、決めたらDBに対して、PHPからではなくコマンドから直接実行して 結果を確かめます。
これはPHPからHTML出力を組む時と同じで、まずは固定データを入れた静的な状態のコードを組んで想定の表示や結果になるかを確認し、
そこからPHPで同じコードを目指します。
そのコードになるまでexecuteもしません。
※というか、executeして想定の結果を得られるまでhtmlも書きません
そして、key
もいきなりGETで受け取るのではなく、固定値で試します。
スペースは全角も半角も受け入れるということで、そこは変わりなしと言う前提で、例えば下記。
※パターンは①-aを想定
php
1 <?php
2 $target_columns = [ 'contents1' , 'contents2' ] ;
3 $where_condition = [ ] ;
4
5 $key = "a b c d" ;
6
7 $key = mb_convert_encoding ( $key , 'UTF-8' , 'auto' ) ;
8 $key = mb_ereg_replace ( " " , " " , $key ) ;
9
10 if ( trim ( $key ) !== "" ) {
11 $keys = explode ( " " , $key ) ;
12
13 foreach ( $target_columns as $column ) {
14 $like_keyword = [ ] ;
15 foreach ( $keys as $keyword ) {
16 $like_keyword [ ] = " { $column } LIKE '% { $keyword } %'\n" ;
17 }
18 $where_condition [ ] = "
19 (
20 " . implode ( " AND " , $like_keyword ) . "
21 )
22 " ;
23 }
24 }
25
26 $sql = "
27 SELECT
28 *
29 FROM
30 video
31 " ;
32 if ( count ( $where_condition ) > 0 ) {
33 $sql .= " WHERE " . implode ( " OR " , $where_condition ) ;
34 }
35 $sql .= ";" ;
36 echo $sql ;
ここができたら出来上がったSQLをDBに対して、PHPからではなくコマンドから直接実行して
始めに作ったSQLと同じ結果が出るかを確かめます。
あとはprepare,bindValueにあわせた形に整形していきます。
※構文エラーは出ませんが動作未確認です
php
1 <?php
2 $target_columns = [ 'contents1' , 'contents2' ] ;
3 $where_condition = [ ] ;
4 $keys = [ ] ;
5
6 $key = "a b c d" ;
7
8 $key = mb_convert_encoding ( $key , 'UTF-8' , 'auto' ) ;
9 $key = mb_ereg_replace ( " " , " " , $key ) ;
10
11 if ( trim ( $key ) !== "" ) {
12 $keys = explode ( " " , $key ) ;
13
14 foreach ( $target_columns as $column ) {
15 $like_keyword = [ ] ;
16 foreach ( $keys as $num => $keyword ) {
17 $like_keyword [ ] = " { $column } LIKE :word { $num } \n" ;
18 }
19 $where_condition [ ] = "
20 (
21 " . implode ( " AND " , $like_keyword ) . "
22 )
23 " ;
24 }
25 }
26
27 $sql = "
28 SELECT
29 *
30 FROM
31 video
32 " ;
33 if ( count ( $where_condition ) > 0 ) {
34 $sql .= " WHERE " . implode ( " OR " , $where_condition ) ;
35 }
36 $sql .= ";" ;
37 //echo $sql;
38
39 try {
40 //PDO接続部分省略
41 $stmt = $pdo -> prepare ( $sql ) ;
42 foreach ( $keys as $num => $keyword ) {
43 $stmt -> bindValue ( ':word' . $num , '%' . $keyword . '%' , PDO :: PARAM_STR ) ;
44 }
45 $stmt -> execute ( ) ;
46 var_dump ( $stmt -> fetchAll ( PDO :: FETCH_ASSOC ) ) ;
47
48 } catch ( PDOException $e ) {
49 var_dump ( $e ) ;
50 }
ここで想定通りに動いてようやく、GETの出番です。
GETということはURLに出ているはずで、a b c d
というキーワードを送ったらURLエンコードがかかってa+b%E3%80%80c+d
のようになっていると思います。
もしecho $_GET['key'];
として、a+b%E3%80%80c+d
と出たのでしたら、スペースの処理の前にurldecode() しておく必要があります。
ソートの件
SQLとしては前項と同じく静的SQLを作るところから始めますので省略します。
つまり、GETも後です。
固定でGETに相当する情報を用意してSQLを作ります。
※GETするとしても下記のようなコードから確認していきましょう
php
1 $ord = 0 ;
2
3 if ( isset ( $_GET [ 'ord' ] ) ) {
4 echo "get ord:" . $_GET [ 'ord' ] . PHP_EOL ;
5 $ord = $_GET [ 'ord' ] ;
6 }
7
8 switch ( $ord ) {
9 case 1 :
10 echo "1です" ;
11 break ;
12 case 2 :
13 echo "2です" ;
14 break ;
15 default :
16 echo "それ以外です" ;
17 }
そのうえで懸念。
下記、ちゃんと出力されていますか?
php
1 <?php if ( $tr_all ) { ?>
2 < p >
3 <?php if ( $ord != 2 ) { ?> < a href = " <?php echo $_SERVER [ "PHP_SELF" ] ; ?> ?ord=2 " > 最終更新日順 </ a > <?php } else { echo "最終更新日順" ; } ?> |
4 <?php if ( $ord != 1 ) { ?> < a href = " <?php echo $_SERVER [ "PHP_SELF" ] ; ?> ?ord=1 " > 撮影日順 </ a > <?php } else { echo "撮影日順" ; } ?> |
5 <?php if ( $ord != 0 ) { ?> < a href = " <?php echo $_SERVER [ "PHP_SELF" ] ; ?> ?ord=0 " > video No.順 </ a > <?php } else { echo "video No.順" ; } ?>
6 </ p >
出力されているとして、$_GET['ord']
は想定の値が渡ってきていますか?
いずれにしても、検索ワードがURLパラメータにつけられていないので、リンクを押すと全件での表示順が切り替わるだけです。
keyがあったら&key=$key
つけましょう。
ご確認ください。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/12/19 00:05
2019/12/19 00:23
2019/12/19 11:59
2019/12/19 18:57
2019/12/20 14:25
2019/12/20 14:40
2019/12/20 19:58