プログラミングは面白い

プログラミングの事を中心に色々書いていきます

着々とデプロイは進んでいるが、やはり地獄

デプロイというより、環境構築でめっちゃ躓いた。
Linuxはコマンドとかそうゆうのは大分理解したんだけど、いまいちリポジトリの概念が理解出来ていない事が判明。
PHPをインストールするのにRemiというリポジトリからインストールを行ったんだけど、php-mbstringというのがインストール出来ていなかったようでこいつのせいで地獄みた。

単純にyum -y install php-mbstringみたいにするとphp-commonと干渉してるエラーを吐く。
でもphp-commonはちゃんとインストール済み。
何でだよ!とイライラすること1時間。
ドンピシャなページを発見。

teratail.com

これ通りやったら無事にphp-mbstringをインストール出来た。
このリポジトリの概念がいまいちよくわからん...
こうゆうのをもっとちゃんと理解出来れば余計な所で躓かないんだけどなー。
やっぱりDockerが良いのかなー。

とりあえず後はrootフォルダに乗っければ公開出来るっぽい。
その前にちょこちょこ設定する必要はありそうだけど。

httpsにもしたいけど、すぐには難しそう。
覚える事が尽きない。

【PHP】array_count_values関数

月別アーカイブを作ってる時にこの関数めっちゃ便利だったのでご紹介。

配列の値をキーとして、値の個数をカウントして連想配列にしてくれる関数です。
PHP: array_count_values - Manual

月別アーカイブを作成時、一度すべての記事作成日時をcreated_atカラムから取り出し配列に入れたのですが、ここから重複を省いてカウントする方法ないかなーと探していたらドンピシャこの関数がありました。

    private function archive() {
        // 月別アーカイブ処理
        $posts = Post::all(); // DBから全ファイル取得

        $monthList = []; // 空リスト作成
        // ループで空リストに追加
        foreach($posts as $post) { 
            $monthList[] = $post->created_at->format("Y-m");
        }
        // array_count_valuesを使って連想配列化
        $countArray = array_count_values($monthList);

        return $countArray;
    }

あとはビュー側で中身を取り出して表示さればOKですね。
てかこれ書いてて思ったのですが、ループさせなくてもモデルの操作で日付のデータを配列で取得出来たような…
ちょっと後でやってみようかな。

array_count_valuesはいろんな場面で使えそうなので覚えておいて損はなさそうです。

デプロイの前に

なんかページネーションを実装するのにLaravelだとデフォルトでBootstrapでデザインが作られてるようです。
しばらく気づかなかったのですが、フォントの感じが変に感じまして、よく見たら色々微妙におかしくなっていました。
仕方ないのでBootstrapのCSSを切って修正しました。

ついでに月別アーカイブのリンクを作って該当月の記事だけを抽出するアクションを作ろうとやってみたのですが、これが思いの他苦戦しました。
Railsにはall_monthメソッドという便利メソッドがあって簡単に実装できました。

qiita.com

詳しくはこの辺をみると良いと思います。
Laravelにもあるだろうと思っていたのですが、どうやら同じような物はないらしい…
ただ、年、月を整数で渡すと該当するデータを引っ張ってくる関数がありました。
ちょっとごちゃっとしたけどこいつを使ってなんとか実装出来ました。

co.bsnws.net

たぶんこの辺が参考になると思います。
日付で検索することは割とあるような気がするので覚えておいて損はないですね。

わからない事だらけだけど、調べながら徐々に進んでいく感じはゲームを攻略している感覚に似ています。
イライラすることも多々あるけど、少しづつ力がついてきてるなーと実感してます。

てことで、デプロイ調査開始。

おっしゃほぼ完成した!

相変わらずコメント機能がなかったり、一部リンクを実装してなかったりはしますが概ね完成でしょう。
認証機能がどうなるか心配だったけど、割と簡単に出来て良かった。
もちろんめっちゃ調べたけど。
コーディング2割、調べてる時間8割くらいある気がする。

さて、これからデプロイという山を登らないといけないと思うとそれだけで心折れそうだけど頑張ろう...
また心が折れてしまったら...もう立ち直れないかもしれない...
いや、Djangoでもう一回挑戦する手もあるか...

いやいや、何としても今回はやり遂げたい。
webサーバーApatchでDBは最近割と仲が良いmysqlを使おう。

てか、思ったんだけどプログラマーポートフォリオってローカル環境で出来てれば良い説ある?なんかgithubとかに公開しておけば良いっぽいんだけど、どうゆう事なの。
私はデプロイして公開する事でポートフォリオになるのかと思ってたんけど。
わざわざLinux覚えるためにVPSまで借りてコマンドだったり初期設定だったり勉強したんだけどなぁ...
無駄にはならないと思うけど、すんごい遠回りした感はある。

次はスクレイピングを使った簡単なサイト作りたい。

デプロイ頑張る。

共通処理を普通に関数でまとめた

さて、昨日記事にした内容なのですが、とりあえず関数でまとめました。

修正前の月別アーカイブとコントローラーはこんな感じでした。

// namespaceとかは省略。ファンクションから

    public function index() {
        $posts = Post::latest()->get();

        // 最新記事5件
        $five = Post::latest()->take(5)->get();

        // 月別アーカイブ処理
        $posts = Post::all();
        $monthList = [];
        foreach($posts as $post) {
            $monthList[] = $post->created_at->format("Y-m");
        }
        $countArray = array_count_values($monthList);
       

        return view("posts.index", compact("posts", "five", "countArray"));
    }

    public function show($post) {
        $post = Post::find($post);

        // 最新記事5件
        $five = Post::latest()->take(5)->get();

        // 月別アーカイブ処理
        $posts = Post::all();
        $monthList = [];
        foreach($posts as $post) {
            $monthList[] = $post->created_at->format("Y-m");
        }
        $countArray = array_count_values($monthList);
        

        return view("posts.show", compact("post", "five", "countArray"));
    }

月別アーカイブの処理をindexアクションとshowアクションで同じ記述をしています。
これを一つにまとめたい。まとめて簡単にオンオフみたいなので処理を流したい。
そんな機能はないだろうか?と思って探してみたのですが、ありませんでした。

なので普通にそれ用の関数作って呼び出す事にしました。

    private function archive() {
        // 月別アーカイブ処理
        $posts = Post::all();
        $monthList = [];
        foreach($posts as $post) {
            $monthList[] = $post->created_at->format("Y-m");
        }
        $countArray = array_count_values($monthList);

        return $countArray;
    }

    public function index() {
        $posts = Post::latest()->get();

        // 最新記事5件
        $five = Post::latest()->take(5)->get();

        // 月別アーカイブ呼び出し
       $archive = $this->archive();

        return view("posts.index", compact("posts", "five", "archive"));
    }

    public function show($post) {
        $post = Post::find($post);

        // 最新記事5件
        $five = Post::latest()->take(5)->get();

        // 月別アーカイブ呼び出し
        $archive = $this->archive();

        return view("posts.show", compact("post", "five", "archive"));
    }

viewに渡す変数名が最初と変わってるので読みづらいかもしれません。
変数名つけるのほんと苦手...
とまぁこんな感じで一応スッキリはしたのですが、それでもやっぱり同じ処理をアクション毎に書くのってスマートじゃない気がするんだけど、これはしょうがないのかな?
最新5件表示の処理に関してもやっぱりその都度書かないとならないし。

railsのbefore_actionって処理を作ったらその処理をどのアクションで適用するか設定出来た気がするんだけど、記憶違いかな?
そんな機能があったらもっとスッキリするんだけどなぁ。
まぁこの辺は今後のブラッシュアップの課題としますか。

さて、残る機能はログイン、編集、削除、ページネーションですか。
Laravelはどうしても調べる時間が長くなっちゃって中々進まないなー。

あ、そう言えば月別アーカイブ作ってる時に出会っためっちゃ便利な関数array_count_valuesを今度紹介しよう。そうしよう。

共有処理

ブログを作っているので、ヘッダー、サイドバー、フッターは常に表示されます。
テンプレートを作って共通ページ項目を常に表示させてるわけですが、その中の処理をまとめられなくて困っています。

月別アーカイブも無事できたのですが、indexページで表示させるサイドバーの処理と、
記事単体ページ(show)ページでのサイドバーの処理が内部的に分かれています。
コントローラーでアクション毎に月別アーカイブの処理を書いているのですが、全然スマートじゃない...
ミドルウェア使うと出来るのかなと思い、色々試してみたのですが思った挙動をしません。
ググってるんですけどそれらしきページにも行き着かず。
機能的には問題なく動いてるので良いんですけど、すっごい気になる...
てか、ブログレベルのシステムなら大したことないけど、何かページが膨大に増えていくようなサイトだったらこんなの都度書いてたらとんでもない事になってしまう。

他の機能を実装しつつ、この問題も解決させたいな。
てか、なんかLaravel難しいんだよなー。
まだまだ勉強が足りないんかな。

がんばろ。