2時間で終わると思っていたけど、思った以上に時間かかった。
レベル低くてはずいけど、振り返り。
1. 仕様メモ
- 数ヶ月毎のスケジュールをタブ化して、それぞれの日に紐づく投稿記事をリスト化してほしい
- 土曜日と日曜日はclassを付与してcssで色を変更したい
- 記事にはtaxnomyを紐付けて、taxonomyで絞り込みができるようにしたい
2. 仕様をプログラムに落とし込み
前はボトムアップで考えていました。考えてもよくわからないので、手を先に動かしてハマったら覚えようの姿勢。
が、この方法はぐぐることが前提のため、知識は増えますが、ものすごく時間がかかります。
1日(8時間)かけて実装したけど、結果が全然違うので、夜間やり直し。みたいな。
なので、最近というか去年ぐらいから、要件定義とは別に、やりたいことのtodoをソースコードに書きなぐってから、実装しています。
今回こんな感じ。
- アクセスした日付から当月を取得する
- 当月から、来月、再来月...と数ヶ月のDatetimeオブジェクトを作成
- 揃ったらArray化
- それぞれの月で、日スケジュールArrayを作成(ex: 1日 ~ 30日)
- 指定月の最初の日、最後の日を取得する
- 無限ループの中で、最初の日を1日ずつインクリメントする
- Datetimeオブジェクトを作成するArrayにpushしていく
- インクリメントした日が最後の日を超えたらbreakする
- 指定月の日スケジュールArrayの準備完了
- 数ヶ月毎でループ
- 数ヶ月毎の中には、日スケジュールArrayがあるのでそれでループ
- それぞれ日にマッチする記事を検索して出力する
- 数ヶ月毎の中には、日スケジュールArrayがあるのでそれでループ
こんな感じに書きなぐった。
さぁ実装です!
次、結果
結果
実装に5時間かかりました(°ω°;
次、振り返り。
振り返り
主に遅くなった原因を上げていきます。
Datetimeクラスの使い方が曖昧だった
まぁーググりまくった。
色々ありますが、modify
の使い方やformat
をググった。あんまり覚えていなかったのね。反省。
フォーマットの符号をよく覚えていない問題
例えば
YYYY/MM/DD HH:mm:ss
よく見るこのフォーマットにするには
<?php echo (new Datetime())->format('Y/m/d H:i:s');
このH:i:s
のi
が中々覚えきれないね。i
って何の頭文字よ。さらに、よくやりがちなのはYYYY/MM/DD
とほしい形通りのフォーマットに置換してくれると勝手に解釈してしまい、その文字列を渡すってのもよくやりました。moment.jsはそう使えるんだよ!!orz
また、曜日はw
を使えますが、0 ~ 6 の数値が返ってきます。
英語ならStringを返すformatもありますが、日本人の場合は、日本語のArrayを用意してあげないといけません。これは次回から用意しておきます。
<?php $jaWeekArray = ['日', '月', '火', '水', '木', '金', '土']; echo $jaWeekArray[(new Datetime())->format('w')];
modifyに渡す文字列をよく覚えていない問題
<?php echo (new Datetime())->modify('+1 days')->format('Y/m/d');
こうすると、実行時の日から+1された日付が表示されます。便利。
便利ですが、色々と使い方があります。これは覚えておいた方がもっとコーディングが早くなると思いました。
<?php $nextDay = (new Datetime())->modify('+1 days'); // 次の日 $firstDay = (new Datetime())->modify('first day of this month'); // 今月の最初の日 $lastDay = (new Datetime())->modify('last day of this month'); // 今月の最後の日 $nextMonth = (new Datetime())->modify('+1 month'); // 来月 $afterMonth = (new Datetim())->modify('+2 month'); // 再来月
'+'と数字を使ったStringはまだわかりやすいですが、文にされると単純に暗記しないと覚えられないですね。。。
WordPressの検索の仕方が曖昧でした
4ヶ月前はガッツリWordPressを触っていたので、やりたいことはだいたいすぐ浮かぶようになりました。
が、「どのメソッドだっけ?」「ここのパラメータってなんだっけ?」ってのが多く、ググってしまいました。
これも今回やったことはちゃんと覚えなければ。。。
検索パラメータの構造
<?php $parameter = array( 'post_type' => 'post', 'posts_per_page' => 4, 'meta_query' => array( array( 'key' => 'target_date', 'value' => (new Datetime())->format('Y/m/d'), 'compare' => '>=', // これはvalue以上の日付を検索する用に指定 'type' => 'DATE' ) ), 'orderby' => array('target_date', 'event_start_time'), // orderは複数指定できる、また、mata_queryのkeyも指定可能 'order' => 'acs' ); return get_posts($parameter);
orderby
のところが曖昧でした。また、今回初めてしりましたがmetaの情報でもソートができることは覚えておきます。
テンプレートパーツに変数を渡す時
set_query_var
を使いましょう。
<?php set_query_var('tagName', 'タグの名前'); get_template_part('template-parts/part', 'test_tag_name'); // ~/template-parts/part-test_tag_name.phpってphpファイルを読み込む
todoの見直しをした
これが一番の原因じゃないかな。
わかった人は多いと思いますが、上に書いたtodoの中で、
- 数ヶ月毎でループ
- 数ヶ月毎の中には、日スケジュールArrayがあるのでそれでループ
- それぞれ日にマッチする記事を検索して出力する
この部分の、「1. それぞれ日にマッチする記事を検索して出力する」この箇所。これヤバイです。
というのも、数ヶ月毎ループ => 日スケジュール毎ループ => 記事検索(sql発行 -> 問い合わせ)というフローになっているので、DBへの軽いdos攻撃になるんじゃないかなと思ったわけですよ。
ということで、これはまずいと最後の最後で考えを変えないといけなくて、ちと混乱しました。
こういうときはコンビニやトイレ休憩がおすすめです。目の前にいるとこんがらがっているので、一旦別のことすると、少し気持ちが楽になります。んで、歩いているとさっき出てこなかった考えがひらめいたりするのでおすすめです。
さて、じゃあどうしようかなと思ったら、そもそも、数ヶ月毎のループの前で検索する月は決まっています。ので、betweenなどを使って、先に数ヶ月毎の記事を取得しましょう。
ただ、取得したデータは array(indexNumber => post)
となっていて、post
にアクセスしないと、日付の情報などがとれないです。そのため、日スケジュールのループ時に、2016/01/01というデータが渡された時、その値が記事リストの中に入っているのか確認するため、ループする必要があります。
日スケジュールのループの中で、マッチする日を探すためにループする。月の日数 x 記事数のループをしなければいけません。これはよくない。
「うーん」と悩んでいる中、コンビニ行ってきましたが、単純な話なことに気づきました。
記事リストの配列の構造を変えてしまえばいいのです。
keyを日付、valueを記事情報にしてあげれば、isset
で、日付がマッチしていれば、それは表示したい記事だ。ということがわかります。
長くなりました。とまあこんな感じで、todoまで戻って、やり直して、構造を変えて、スマートな感じの処理になり、サービスを実装することができました。
振り返り終わり。
次回どうする?
使いそうな形にして、githubとかでコードを追加しておく
次回はコピペで終了するようにします。
「コピペは禁止」って人も多いと思いますが、数行のコード、またそのコードを理解しているのなら、自分おkだと思っています。
https://github.com/Aipakazuma/php-technical-collection/blob/master/jaWeekArray.php
実装前の // todo:
の書きなぐりは引き続き続ける
これは頭がスッキリするので、続けてもいいかなと思う。
また、仕様書とエディタをいったりきたりせずに、エディタ上でソース書きながら確認できるので、いいかなと。
感想
自分で振り返るのってやっていたと思ったけど、今回はじめてかも。