Torihaji's Growth Diary

Little by little, no hurry.

学習日記 20230903

6:24 2023/09/03
はい、でははじめましょう。
配列の最後の要素であるかを判別できる関数みたいなものはないのかな。
endもあるみたいだけど、
同一要素があったら処理がバグるので、array_key_lastにしましょう。

ええと、php sqlのバインドってどうやるんだったけか。
ずっとFW通りに書いていたから、元の書き方を忘れた、
bindvalueを使うことは覚えているけど。。
prepareで引数に指定したsql文を発行する。
このsql文は一部を変数のように記述しておき、
後から割り当てるという使い方ができる。
データベースに作成したSQL文を発行するのは、execute。

同時並行でいろいろやろうとすると、結局何も進まないので、やめよう。
経理なんか一緒にやるもんじゃない。
7:30 2023/09/03

8:32 2023/09/03
sql文をプリペア度ステートメント書いて、バインドしようと思ったら、
バインドがうまくできていないのかエラーが返ってくる。なぜだろう。

prepare($sql)で、$pdoに変数埋め込み予定のsql文を装填して、
execute($binds)で、変数埋め込み予定の箇所を置き換えたsql
DBに発行して、結果を受け取る、というのがお決まりの流れだと思うから、
できていないとするなら
この中のどこかがおかしいことになる。
vardumpして、executeする直前のsqlを見てみたけど、
想定通りだから、bindがうまくいっていない。
んーー。
おそらく、$bindsが複数キーを持つものだと思っていたけど、
1個のキーしか入ってないから、
変数割り当て予定の数と合わないよ、と怒られてる。
これじゃ配列に新規追加されないんだね

でもダメそう。

名前付きプレースホルダーの前後に、
直接%を使うことはできません。という記述があった。
これが悪さしてるかもしれない。

文字列結合で埋め込んであげる必要があります。だそうです。

prepareで渡すsql文の中にLIKEで%が入っているときはひと工夫が必要。

書いてあることをやったがうまくいかない。
なぜ。わからん。

その原因はなぜか不自然についてるシングルクォーテーションでした。
こいつがエラーの原因です。
タイプミスでしょうね。

動いたーーーーーーーーーーーーーーーーーーーーーーーーーー。

長かったぞー。よかったー。
9:35 2023/09/03

11:25 2023/09/03
今、検索結果に対してページネーション用に、
OFFSET設定しようとしているけど、
今の状態だと、ずれが生じる。

1投稿が複数枚画像もってる構造で、
表示の際は、その画像も1件ずつ表示させるようにしている。
それに投稿TBと投稿画像TBで分けてるから、
当然、発行するSQLも2通り。(JOINはあえてしていない)

そのため、投稿TBでOFFSET設定しても、
結局、各投稿に複数枚画像があったら
15件表示するつもりが、20件とかになってしまって、おかしくなる。
だから、投稿一覧に表示する際は、
1投稿につき1画像だけにするように変更しよう。
12:02 2023/09/03

15:18 2023/09/03
array_key_exists ですでに 画像を入れる配列のキーがあれば
画像を挿入しないよ、という処理に変更。

予想通りに動作。

二つのTBをJOINして、$wheres という配列
(WHERE OO = :OO というWHEREの中身(OO)を動的に設定する配列)を
foreach内
$sql .= $key . " = :$val";
という形でいつも通り使おうかと思っていた。

しかし、JOINするとテーブル名を a.OOという形で
付与しなければならず、上で書いたやり方だと、
判別ができないことに今気づいた。
case で強引にやるか?んー。。

     if(is_array($wheres)){

            $sql .= " WHERE ";
            $a_column_names = array('*', '**', '***');
            $u_column_names = array('###');

            foreach($wheres as $key => $val){

                //$wheres の キー名が投稿TB側のものだった場合
                if(in_array($key, $a_column_names)){
                    
                    $sql .= "a.$key = :$key";
                
                }

                //$wheres の キー名がユーザTB側のものだった場合
                if(in_array($key, $u_column_names)){
                
                    $sql .= "u.$key = :$key";
                
                }

                //配列の最後の要素でない場合、WHEREを付与してループを継続
                if(!($key == array_key_last($wheres))){
                
                    $sql .= " AND ";
                
                }
            }
        }

これに落ち着いて、無事動いたので、採用。 私は師匠の教えに倣って、このような形で、 SQL文にどんどん文字列結合で動的に設定していくスタイルを信仰しています。 elseを書いてもいいのですが、文頭がずれて見づらくなるのでしていません。

実際に使う関数はこのような形で使っています。(まだミカンですが)

 /**
     * function 投稿テーブルとユーザテーブルをjoinした後、各値に応じて動的に設定したSQLをDBに発行し、結果を取得する
     * @params $wheres プリペアドステートメントに仕込む変数とその値を格納した配列
     * @params $all fetchALLで取るか、fetchで取るかの判別
     * @params $limit SQLのLIMITを発動させるか否か(固定値15)
     * @params $offset ページャで使用予定(まだミカン)
     * @return articleTB+userTB
     */
    public function selectForArticles($wheres = null, $all = true, $limit = null, $offset = null){

        $sql = "SELECT 文****;

        if(is_array($wheres)){

            $sql .= " WHERE ";
            $a_column_names = array('*', '**', '***');
            $u_column_names = array('###');

            foreach($wheres as $key => $val){

                //$wheres の キー名が投稿TB側のものだった場合
                if(in_array($key, $a_column_names)){
                    
                    $sql .= "a.$key = :$key";
                
                }

                //$wheres の キー名がユーザTB側のものだった場合
                if(in_array($key, $u_column_names)){
                
                    $sql .= "u.$key = :$key";
                
                }

                //配列の最後の要素でない場合、WHEREを付与してループを継続
                if(!($key == array_key_last($wheres))){
                
                    $sql .= " AND ";
                
                }
            }
        }

        if($limit){

            $sql .= " LIMIT 15";

        }

        // if($offset > 1){
            
        // }

        if($all){

            return $this->fetchAll($sql, $wheres);
        
        }

        return $this->fetch($sql, $wheres);
    }

前まではfetchAllかfetchでとってくるかの考慮($all)をしていなかったが、
今回どちらを使用するかによって
結果が異なったので、導入を決めた。

そもそも何が違うのか。coreをのぞいてみる。
そんなに変わらなかった。

そもそもなんでこんなことを考慮しなければならなくなったかというと、
fetchで1件とってきた結果と、fetchAllかつTB上の一意の値で
WHERE検索をかけた結果、取得できた1件の
データ構造が同じだと思って動かしていたら、
挙動が違くてなんだこれは、となってしまったから。

fetchは配列で結果が返ってくるのに対し、
fetchAllは配列の配列、つまり2次元配列で帰ってきてしまうということ。
fetchだと

array(2){
 ['hoge'] => int(1)
 ['huga'] => int(2)
}

fetchAllだと

array(1){
  [0] =>
   array(2){
  ['hoge'] => int(1)
  ['huga'] => int(2)
 }
}

そりゃあ合わないわけですね。

ただ、htmlのレイアウトが何よりも不格好。ダサい。 何とかせねば。 17:51 2023/09/03

21:04 2023/09/03
唐突に気になった。
phpに出てくるsession_start()関数というもの。
これを使うと$_SESSIONという値が使えるようになるってことなのだろうか。

そうみたい。

すごい。見る見るうちにコードがすっきりしていく。

さぁ、投稿編集画面を作ろう。
まず編集できるのは自身の投稿のみ。
どうやって判断するか。..

よしできた。
さぁ、投稿編集画面なんだが、なにがあればいいだろうか。
投稿のデータを取得してきて、それをあらかじめform内に入力しておく、
というのはいつもの流れなんだけど、
いつもと違うことが1つ。

既に画像の差し替え、削除てどうやればいいの。
想像がつかない。

眠気が襲ってきた。無理。終了
22:29 2023/09/03