Laravelチュートリアル＋その機能の追加

　webアプリケーションを開発したい時に使う言語とフレームワークは何かと考えた時に、思いつくのは`RubyのRails`、`phpのLaravel`ではないでしょうか？
　RailsであればRailsチュートリアルというかなりボリュームのあるチュートリアルがあります。Laravelもチュートリアル自体はありますが、その内容はRailsチュートリアルほどのボリュームはないでしょう。

　そこで、今回は、僕自身が所属しているヒラマサで出されてた課題とそれを実装する際に自分が参考にしたサイトなどを紹介して行こうかなと思います。この記事が少しでもプログラミング初学者の役に立てばいいなと思います。
　課題3はQiita記事を書くだけだったので省いてます。

##現在使ってるPCとOS
　MacBookPro13inc 2018モデル
　macOS Catalina バージョン 10.15.2

##目次
課題1 Laravelチュートリアル
課題2 MySQLへの書き換えとユーザー名の編集機能
課題4 TODOシェア機能
課題5 タスク詳細ページと画像アップロード機能
課題6 リマインダ機能
課題7 全文検索

##課題1 Laravelチュートリアル
　まずは、無料で公開されている`Laravelチュートリアル`をです。これを最初は一週間でやってくれと言われましたが、環境構築とかをやったことない人が一週間でこれをやるのは結構厳しいと思うので、二週間ぐらいでやれれば十分かなと思います。
　環境構築の方法もこの作者の方が書かれている記事の中にはあるのですが、ちょっとわかりづらいところもあるので僕が少し前に書いた記事も載せときます。この記事は`Macの方用`なので、windowsの方は申し訳ない。ちなみにawsでやる方法も電子書籍で販売されていますので、そちらの方もリンク載せときます。こっちのはLaravelの`バージョンが違う`のでお気をつけて。
[Laravelチュートリアル](https://www.hypertextcandy.com/laravel-tutorial-introduction)
[Laravel6.0チュートリアル 電子書籍](https://leanpub.com/laravel-primer)


自分の記事↓
[MacでLaravel5.8の開発環境を構築しよう（下準備）](https://qiita.com/miya_sho/items/4b79c9a74fecb42768f6)
[MacでLaravel5.8の開発環境を構築しよう（開発）](https://qiita.com/miya_sho/items/6e6635555fcb0af9fa66)

##課題2 MySQLへの書き換えとユーザー名の編集機能
　ここから少しづつ機能を追加していきます。MySQLの書き換えというのはLaravelチュートリアルでは`postgreSQL`というデータベースで開発していくので、それを`MySQL`に書き換えるというものです。
　ユーザー名の編集機能はLaravelチュートリアルでのタスク名の編集とかを応用すればいいだけなのでそこまで難しくないです。ここら辺から課題ごとにプルリクエストを作成して、レビューをしてもらっていたので、わからなければそれを参考にしてもらっても大丈夫です。

[GitHubのプルリクエスト](https://github.com/miyagi-sho/laravel-study/pull/1)

##課題4 TODOシェア機能
　シェア機能というのは、自分しか見られなかったものを他の人も見られるようにするというものです。具体的な課題に関していえば、ここでの課題は大きく分けて２つありました。

　１つ目は、`シェア機能の追加`です。タスクの期限日の横にシェアできるボタンを追加して、そのボタンを押したらurlが生成されて、そのurlを踏むと`ログインしてない人` でも、タスク名、期限日、状態を確認できるというものです。これを実装する方法はそれなりにありそうな気がするんですが、僕自身がやった方法について軽く説明していこうと思います。

　まず、タスクのシェアボタンを押したら、`urlを生成`する必要があります。これは、タスクを公開する用のurlなので、`ランダム`なものがいい。そして、他のタスクurlと`被らないように処理`をしなければいけない。
　次にtasksテーブルに`share_urlカラム`を作成して、生成したurlをtasksテーブルに保存する。
　最後にログインしていない人でもタスクを見れるように、tasksテーブルに`保存されているurlと一致するもの`があれば、そのurlを持っているタスクの情報を見れるようにする。

　ここまで分解すれば、Laravelチュートリアルの応用である程度できると思います。ただ、引っかかりそうな部分があります。`ランダムなurlを生成`する部分、あとは引数の部分とかでしょうか。ランダムな文字列を生成する方法は[Laravel公式ドキュメント](https://readouble.com/laravel/5.7/ja/helpers.html#method-str-random)にあるのでそこを参照してみてください。次に、引数の部分ですが、ルーティングに使用される引数というのに使えるものというのは`数字だけではない`です。ランダムな文字列でも入れられます。ただ、持ってくる時に型を`string`にする必要があります。まあ、よくわからなかったら、その時のプルリクのリンクを貼っとくのでそちらをみてください。

　２つ目は、`ビジネスロジックをリポジトリパターンで分ける`、というようなこともやってくれと言われました。何言ってるかわからなん！となると思います。僕自身もこれを実装する時になんのこと言ってるかあんまり理解してませんでした。ここら辺の説明と具体的な実装方法に関してはわかりやすい記事がありますので、そちらを参照してください。ヒラマサではcontroller内のデータベース関連のものをLogicというディレクトリ内のファイルに書くようになってます。
[GitHubのプルリクエスト](https://github.com/miyagi-sho/laravel-study/pull/2)
[Laravelリポジトリパターンの実装](https://qiita.com/bmf_san/items/c8d7b38b5f1f5747c2fd)
[ヒラマサでのフォルダ構成](https://qiita.com/miya_sho/items/30e14c85027c50670835)

##課題5 タスク詳細ページと画像アップロード機能
　ここで実装したものは以下３つです。

**・タスク詳細の作成、編集、閲覧できるようにする。**
　→ここでいう詳細というものは、メモ的なものです。
**・タスクに画像を添付、変更、閲覧できるようにする。**
　→画像をs3に保存するようにする。
**・ログインしてる人だけがみれるタスク詳細画面を作成する。**
　→ここでは、タスク名、状態、期限日、タスク詳細、画像がみれて、シェア、編集リンクがある。
　シェアされているタスクであればそのurlを踏んだユーザーによって表示する画面が変わる。
　`ログインしている人:タスク詳細画面へ`
　`ログインしていない人:公開タスク画面へ`→シェア、編集リンクがない。

　課題４までしっかりこなされている方であれば、引っかかるのは`画像の添付機能`ぐらいでしょう。それ以外であれば、多分Laravelチュートリアル見返せばできると思います。`s3`とはなんぞやと思う方もいるかもしれないです。s３とは`Amazonが提供するクラウド上の画像保管庫`で、12ヶ月ぐらいは無料で利用できます。これとアプリケーションをつなげるには少し面倒な処理が必要なのですが、そこらへんについては下記記事がわかりやすく書かれています。
　後、画像がアップロードされなかった時にはエラーが表示されて欲しい。ですが、そのままだと表示されないので、エラーをまず作成して、その時にエラーメッセージを表示するようにしたい。それをどう処理すればいいのかというのがわからないと思うので、それに関する記事ものせておきます。

[Rails, Laravel(画像アップロード)向けAWS(IAM:ユーザ, S3:バケット)の設定](https://qiita.com/nobu0717/items/4425c02157bc5e88d7b6)
[LaravelでAWS S3へ画像をアップロードする](https://qiita.com/nobu0717/items/51dfcecda90d3c5958b8)

[【PHP超入門】クラス～例外処理～PDOの基礎](https://qiita.com/7968/items/6f089fec8dde676abb5b)]
[laravelでビューにエラーメッセージを渡す方法 （フォーム）](https://thai-bangkok.info/programming/php-laravel/laravel%E3%81%A7%E3%83%93%E3%83%A5%E3%83%BC%E3%81%AB%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E6%B8%A1%E3%81%99%E6%96%B9%E6%B3%95-%EF%BC%88%E3%83%95%E3%82%A9)


[GitHubのプルリクエスト]
(https://github.com/miyagi-sho/laravel-study/pull/3)
##課題6 リマインダ機能
　毎日13時になったら、翌日までの未完了・着手中のタスクを探し出して、その作成ユーザーに対してメールでそのタスクを通知する、というものです。
　この実装に関してネックになる部分というのは、どうやって`毎日13時`に作動するようにするか、どのようにやって`翌日までの未完了・着手中のタスク`を探し出すのか、どうやって`メール送信`するのか、というところでしょうか。

　具体的な実装方法について話していきたいと思います。どうやって13時に作動するようにするかというところなのですが、これはLaravelの`タスクスケジュール`を使って実装していきます。このタスクスケジュールに`コマンド`を設定して13時に作動するようにします。この`コマンド`に翌日までの未完了・着手中タスクを探し出して、メール送信する処理を書き込みます。
　未着手・着手中タスクを探し出す時に`where`と`orwhere`を使うことになります。ただ、これを複数組み合わせる時に少し気を付けなければならないです。具体的にどういうところに気をつける必要があるかはこちらから[参照](https://umebius.com/laravel/querybuilder%E3%81%AB%E3%82%88%E3%82%8Band%E6%A4%9C%E7%B4%A2%E3%81%A8or%E6%A4%9C%E7%B4%A2%E3%81%AE%E8%A4%87%E5%90%88/)してください。メールの送信についてはLaravelチュートリアルの`パスワードリセット`の際に使った方法を応用すれば実装できると思います。

　まあ、偉そうにいってますが、自分はコマンドまでしかうまくいってなくて、タスクスケジュールがうまく作動してないです。動かし方がわかったら、書きます。

[Laravel 5.8 タスクスケジュール](https://readouble.com/laravel/5.8/ja/scheduling.html)
[サンプルコードで学ぶLaravelのメール送信機能](https://www.hypertextcandy.com/send-email-with-laravel#%E9%80%81%E4%BF%A1%E8%A8%AD%E5%AE%9A)
[Eloquent/QueryBuilderによるAnd検索とOr検索の複合](https://umebius.com/laravel/querybuilder%E3%81%AB%E3%82%88%E3%82%8Band%E6%A4%9C%E7%B4%A2%E3%81%A8or%E6%A4%9C%E7%B4%A2%E3%81%AE%E8%A4%87%E5%90%88/)
[GitHubのプルリクエスト](https://github.com/miyagi-sho/laravel-study/pull/6)

##課題7 全文検索
　**フォルダ名、タスク名、タスク詳細の３つを対象として、検索できる。検索はスペース区切りでand検索ができる。**

会社員の方なら[Laravel Scout](https://readouble.com/laravel/5.8/ja/scout.html) で[Algolia](https://www.algolia.com/)を使ったら簡単に実装できるとは思います。ただ、自分は無職なもんで、使えないんですよね。`elasticsearch`もなんかうまく使えなかったので、独自で作りました。


　文章で書くとすごく簡単ですが、`隠れている指示`があります。ただ実装するだけなら、さほど難しくないのですが、データベースの処理というのは出来るだけ少なくしなければ、処理速度がすごく遅くなってしまいます。それで、できる限り処理は少なくしなければならないということです。その上で処理を多くしている用件が２つあります。
　１つ目は、`対象が３つ`あること。対象が１つ、例えばフォルダ名だけであれば検索ワードを取得して、それをフォルダ名から探し出すだけでいい。ただ、３つあるとそれを3回処理しなければならない。ここまでであれば、多少処理が多くなるだけなのでさほど問題にはなりません。次のことがあるから、処理が難しくなります。
　２つ目は、`検索ワードの上限が決めらてない`ことです。これはなかなかシビアです。検索ワードが１個なら３の処理ですみますが、検索ワードが100個なら300の処理が必要となるわけです。これを複数のユーザーが行うとしたら、相当重くなることは想像に難くないでしょう。

　では、具体的にどうすればいいかというと、1つ目の対象を１つにします。

　「え？いやいやそれじゃあ、フォルダ名、タスク名、タスク詳細の３つから調べられないじゃん。」
　そう思うかもしれないです。ただ、それは可能です。あらかじめその`３つを結合させたテキスト`を作っておけばいいのです。こうすれば、検索の際に発生する処理は１つで済むわけです。そうすれば検索ワードが100個の時でも100の処理で済むわけです。

　「確かにそうだけど、それってどうやるの？」
　どうやるかというと、検索するためのテーブルをあらかじめ作っておいて、一定の時間になったら自動で更新されるようにすればいい。これは課題６でも出てきた`Laravelのタスクスケジュール`を使って実装します。で、ここで作るテーブルはあくまで検索する用のテーブルなので、保存するデータは最小限に留めないと、また処理が重くなる原因になってしまいます。何を格納するかというと、`フォルダのid`、`タスクのid`、`検索用のテキスト`、`作成日`、`更新日`ぐらいでいいと思います。

　「これだけじゃ、検索してもデータ取れないじゃん！」
　確かに検索用のテーブルだけじゃ、フォルダ名とかを取り出すことは難しいです。ただ、これは検索の時に`フォルダテーブルとタスクテーブルに検索用のテーブルを結合`させて、検索してしまえばいい。そうすれば、検索自体は検索用テキストでして、その条件にあったものをフォルダテーブルやタスクテーブルから持ってくることができます。

　さて、ここまで来れば課題６まで進められた方であれば、実装できると思います。ただ、詰まるところもあると思うので、データベース処理に関するサイトとかを参照しておきます。
　

[Laravel 5.8 Laravel Scout]
(https://readouble.com/laravel/5.8/ja/scout.html)
[Laravel 5.8 データベース：クエリビルダ]
(https://readouble.com/laravel/5.8/ja/queries.html)
[Laravel・データベースからデータ取得する全実例]
(https://blog.capilano-fw.com/?p=665)

検索ワードをスペース区切りで配列化するときに使ったサイト
[php exprodeについて](https://www.php.net/manual/ja/function.explode.php)

[GitHubのプルリクエスト](https://github.com/miyagi-sho/laravel-study/pull/7)

##最後に
　今回の記事は一種のまとめ記事なので、今までの記事と比べるとわかりづらいかもしれません。ここがわかりづらい等ありましたら、教えてください！