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

学習日記 20230902

8:20 2023/09/02
おはようございます。先ほど起きました。
fix祭り開催です。
のまえに、自分の書いたコードに対して、
理由をもって説明できるようにしましょう。
なんでここでこのようにコードを書くのか、また書いたのか、
そういうことを自分の言葉で説明できるようにしましょう。
このサイトから似たようなものがあったので、引っ張ってきたら動いたしいっか。
は絶対にやめましょう。自分のためになりません。

まず1つ目。
DBについて。
pdo、インスタンス化して
そこにsqlセットして、結果をstmtで受け取る。
あとはどこがおかしいか。

朝、だらだらやりすぎた。午後に期待
9:29 2023/09/02

 

15:24 2023/09/02
午後の部開始。
基本、if文かくときにelseは書かないようにする。
見づらいから。
変数の空判断とかで使用する際は、defaultでnullとかをセットしておいて、変数がセットされた状態で
渡ってきたら、その値を入れる、という処理方針にしていく。
issetはisset(NULL)は判定できないみたい。

いろいろあって。
20:50 2023/09/02
検索用のSQLとかその処理作るのって本当に大変。
何が大変かって、場合分けがいろいろあるし、
フォームからどういうnameつけて、もらってくるかも考えないと、イケないから。
初め、1つの検索フォームから1つのデータしか持ってこれないから、
投稿のタイトルと、ユーザ名の検索をしたい、となったら、その個数分のフォームを作らないといけないのかと思っていたし
その個数分、検索したいカテゴリが分かれていたら、そのカテゴリがあるTBに対して
SQLクエリを発行しなければならないのかと思っていた。 
今回の場合であれば、投稿のタイトルで検索をしたい場合は、投稿TBにSQLを発行し、
対してユーザ名の検索ならユーザTBにSQLを発行して、、というように。

そうしなければならないのかもしれないけど、今回はあらかじめ、
別で分けてる投稿TBとユーザTBをjoinして、投稿のタイトルとユーザ名を一緒のTBにしてから
そのTBに対して、ORでaritcle_title LIKE $val OR user_name LIKE $val・・
にしたらいいよと教わったので、そうしていこうと思う。

考えてたら時間が過ぎた。無念。
23:30 2023/09/02

学習日記 20230901

19:58 2023/09/01
なんかこのまま続けても実務に役に立つのかといまさらながら
不安になってきた。
なぜだろうか。とりあえず、この製作物を早く完成させるところまでもっていこう。

今日は投稿詳細ページを作ろう
まず画像をクリック。
a タグでarticle_idが紐づいているから
まずはarticle_tableでその投稿レコードを引っ張ってくる。
その中にuseridがあるからそれを取得する。
それを元にarticleimageテーブルと、userテーブルでwhere検索をかければ行ける。

配列に新規追加するには[]がおぬぬめ。ということに気づいた。
これをすると
すごい楽。ほかの方法があるのだろうか。

cssだけでカルーセルを作りたい。
jsだとページ読み込みが遅くなるみたい。
white-spaceというプロパティ
white-space: nowrapというものを使えば、行が折り返されないらしい。

本当にhtmlのdiv クラス名の決め方、idの使いどころ。
レイアウトの組み立て方がわからん。

今週の授業終了。
先生からサイト綺麗だね。と言われた。
ぼそっと言われたので、真実味がマシマシでとてもうれしかった。
デザイン頑張ろうと思う。

今日教わったのは、
joinしたほうがいいよ、そしたらdbへの問い合わせが1回減るから
ページャもやってみよか。
複数検索はそのページを新しく作った方がいいよ、
の3本でした。

lazyloaderのことも気にはなったが、一旦ページャを採用しよう。
明日からは何をしようか。まず半日でコードの修正をした後に。。。
いや明日はメンテナンス祭りにしよう。

はい、今日は早く寝よ。終了!
22:50 2023/09/01

 

学習日記 20230901

19:58 2023/09/01
なんかこのまま続けても実務に役に立つのかといまさらながら
不安になってきた。
なぜだろうか。とりあえず、この製作物を早く完成させるところまでもっていこう。

今日は投稿詳細ページを作ろう
まず画像をクリック。
a タグでarticle_idが紐づいているから
まずはarticle_tableでその投稿レコードを引っ張ってくる。
その中にuseridがあるからそれを取得する。
それを元にarticleimageテーブルと、userテーブルでwhere検索をかければ行ける。

配列に新規追加するには[]がおぬぬめ。ということに気づいた。
これをすると
すごい楽。ほかの方法があるのだろうか。

cssだけでカルーセルを作りたい。
jsだとページ読み込みが遅くなるみたい。
white-spaceというプロパティ
white-space: nowrapというものを使えば、行が折り返されないらしい。

本当にhtmlのdiv クラス名の決め方、idの使いどころ。
レイアウトの組み立て方がわからん。

今週の授業終了。
先生からサイト綺麗だね。と言われた。
ぼそっと言われたので、真実味がマシマシでとてもうれしかった。
デザイン頑張ろうと思う。

今日教わったのは、
joinしたほうがいいよ、そしたらdbへの問い合わせが1回減るから
ページャもやってみよか。
複数検索はそのページを新しく作った方がいいよ、
の3本でした。

lazyloaderのことも気にはなったが、一旦ページャを採用しよう。
明日からは何をしようか。まず半日でコードの修正をした後に。。。
いや明日はメンテナンス祭りにしよう。

はい、今日は早く寝よ。終了!
22:50 2023/09/01

 

学習日記 20230831

6:46 2023/08/31
凸凹だった画像一覧を、タイル状?みたいな形で敷き詰めることを
やってみたいんだけど、どういうことをすればいいんだろうか。
CSSグリッドていう機能があるんだと。
子要素を親要素に対してタイルのように並べることが可能になるそう。
タイルが子要素、グリッドアイテム。それをグリッドコンテナで囲むらしい。
グリッドアイテム同士の間隔をグリッドギャップ。

並べたいアイテムを1つのコンテナで囲む。
コンテナに対してdisplay:grid;を記述
レイアウトを調整。
の流れで出来るらしい。
なんだ、簡単じゃない。

親に
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px;
gap: 20px;

まず横に何枚、どのくらいの大きさのタイルを作るのかを決めるのは
grid-template-clumns
これ、複数値指定、とあるけど、何個なんだろうか。3つ?
3つだとしたらそれぞれは何を表している?

指定する数値の数は、そのまま列数になっている。
2つ指定すれば、2列のタイルができるし、3つ指定すれば、3つのタイルができている。
なるへそ、そういうことか。

ならば、パソコンなら、3つでスマホなら2つくらいにしようかな。
そうしよう。
はい、朝終わり
7:04 2023/08/31

 

21:58 2023/08/31
今日は少し遅くから開始。とてつもなく眠い。
11時までで終わりにしよう。

今日はcssをいじってみようかな。
cssグリッドの記憶が新しいうちに。
たしか、display:gridを親の入れ物に指定して、
列の指定と行?の指定みたいなことをすればよかったはず。

わからん、調べよう。
flexboxとcssグリッドの違いは1次元か2次元かみたいだね。
確かに。似たようなことやっているから、言われてみればそうなんだね。
flexboxは子要素を1方向に並べられる。
対してcssグリッドは子要素を列と行という2方向に並べられる、らしい。

display:flexflex-wrap,flex-grow等を使えば
pinterestみたいに画像を敷き詰めるようなレイアウトを作ることも可能らしい。
たしかに。敷き詰まっている。

だめだ、頭が働かない。腰が疲れた。足がむくんでいる。
寝よう。
22:32 2023/08/31

学習日記 20230830

20:19 2023/08/30
最終成果物がうまくいかない、というか納得いかないのは
デザインが微妙だから。おそらく。
htmlとか馬鹿にしていたけど、やっぱりhtmlとかもわからないと
これは進まないかもしれない。
もちろん、単純なものならわかるけど
自分が作りたいようなデザインがどのように書けばいいのかがわからない。
というかそもそもどんなデザインがいいのかも自分でよくわかっていないかもしれない。

困ったなー。

まいいや、とりあえずデザインはあとにして、今は裏側の機能に集中しよう。

今やるべきは検索機能。
今のところ、投稿のタイトルをキーワードにして検索をすることが可能
キーワードは部分一致で、検索をかけている。
キーワードが空白であれば、最初の全検索と変わらない。
投稿タイトルがあるのはarticleテーブルで、ユーザ名があるのがuserテーブル。

だからユーザ名で検索をかける場合はuserテーブルへクエリを発行しなければいけない。
でもそうすると、入力を分けないといけない?
今のこのフォームのままでarticleテーブルとuserテーブルを検索対象にするにはどうしたらいいんだろうか。

全く関係ないが、画像投稿サービスなので、とりあえず、いろんなユーザでいろいろ画像を投稿してみた。
画像の大きさがバラバラで、凸凹しているので、見た目はあまりよくないかもしれないが、
それらしくなってきた。気分が上がる。。
というか載せてる写真がおしゃれだから、なんかすごくきれいに見える。(笑)

試しに画像アップロード5枚まで制約のテストをしてみたけど、
無事制約がしっかり効いていてよかった。

あとは、この画像一覧の凸凹を何とかしたいな。
どうすればいいんだろう。
アップロードの段階で、画像の大きさをトリミングできるような機能を追加した方がいいのかな。

あと画像クリックしたら投稿詳細画面に飛べるようにしないと。
表示するのはユーザ名、画像(スライドさせて)、投稿タイトル、投稿の内容、かな。
いいねぼたんもつけるかな。

あとは投稿編集か。これも投稿詳細画面と表示させるものは一緒だけど
投稿の所有者であれば、編集できるボタンを作らないとな。
それはどう判別しようかな。

全く関係ないけど、管理者ページを久々にのぞいてみると、
予期しない動作ばっかするので、こっちも並行してメンテしていかないと。
まだあんまりわかっていない時に書いたから、そうなるのもやむなし。
今なら少し理解も進んでいるだろうから、復習もかねていい勉強になるでしょう。
また今度ですね。

まいいや、今日は終了。お疲れ
22:09 2023/08/30

学習メモ 20230829

21:02 2023/08/29
今は検索フォーム、検索機能を作っている。
検索ということは、
検索フォームからキーワードをgetで受け取り、それをdbに渡して、WHERE value LIKE :value でヒットしたものを
また更に受け取ればいい。
今悩んでいるのはどんなことだ。
検索をかけるテーブルをどうしようかに悩んでいる。
一応、検索するワードのカテゴリは、投稿のタイトル、ユーザ名の2つ。
まず投稿のタイトルだけで検索をかけてみよう.
なので検索をかけるのはarticleテーブル
 
やはり、できたな。簡単だ。
まずは1つから。
ただ、おかしい。検索フォームが消えてしまった。
なぜだ。
layout.phpにおいて 検索フォームを表示する条件がpost/list.phpのみだったから
これに search.php分も追加すればよい。
だめだった。検索ワードをurlの後ろに?でつけているからヒットしない。
 
/pattern/のように必ず正規表現を//で囲むこと。
そうすればpreg_match("/pattern/", 検索対象)
でヒットすればtrue, falseが出力される。
 
preg_match("/\/test\/example.*/", $_SERVER['PATH_INFO'])
で$_SERVER['PATH_INFO']が/test/exampleだったらtrue、みたいな。
 
---------------------------------------------------------------------
検索フォームにおいて、何も入力せずに検索をしたらそのまま全投稿一覧が表示されるようにしたい。
そもそも何も入力されていない時にDBに対して 全検索をかける風にするには。
 
現状、WHERE value LIKE :value で行っているが、部分一致で検索をしているため
実際には少し変換して
WHERE value LIKE %value% という形で DBに検索をかけている。
 
########################################################
//空白のままであれば、NULLで検索をかける
if ( empty($this->request->getGet('keyword'))){
 
$keyword = NULL;
}else{//入力されている場合
 
$keyword = $this->request->getGet('keyword');
}
//部分一致検索をするため、$keywordを%で囲む
$partial_keyword = "%{$keyword}%";
######################################################
これでたとえ、検索フォームに何も入力しなくても投稿全件が出力される。
 
※前回の反省
前まで 学習日記 OO日目とかやっていたが、毎回、今何日か忘れて
それを調べるのが面倒になって、やめていた。
あと、どうしても人に伝えようと、文を加工しすぎて
面倒になって、やめていた。
しかし、この学習の際に書きなぐっているメモであれば、
難なく書けるので、これを発信していこうと思う。