スクリーンショット_2020-02-09_16

Laravel6.0(PHP7.3)+MySQL+Laradockで簡易的なECサイトを作る⑥

お疲れ様です。

いよいよこのLaravel6でのECサイト作成のチュートリアルも
ラストの記事となりました。

今までの記事はこちらです。

■最初の記事↓
https://note.com/mukae9/n/n12cc13fd4f90

■2番目の記事↓
https://note.com/mukae9/n/naf7dff31b4db

■3番目の記事↓
https://note.com/mukae9/n/n2ed6be437f0d

■4番目の記事↓
https://note.com/mukae9/n/n103587d08ef2

■5番目の記事↓
https://note.com/mukae9/n/n18125664d380

これまでの記事の中で
Laravelの基本的な動きやライブラリが分かってきたのではないでしょうか。

ただし、Laravelにはまだまだ色々な仕組みがありますし
かなり有能なライブラリも多数あります。

Vue.jsと組み合わせてSPA(シングルページアプリケーション)を作るのも容易です。

この記事が終わってからもLaravelのこと色々と勉強してみてくださいね。



1、課題の答え合わせ

①/cartdeleteにPOSTでアクセスした場合にShopContorllerのdeleteCartメソッドを発動させる。
②Eloquantを使ってカートテーブルから該当の商品かつログインユーザーのidと一致するレコードを削除する。
③削除後にカートを表示する。
$messageに「商品をカート内から削除しました」と表示させる。

とのことでした。
全体的に前回の記事で詳しく説明している部分がほとんどの復習になりますので駆け足で進めていきます。
もしわからないところがあれば今までの記事で復習してみてくださいね。

課題①/cartdeleteにPOSTでアクセスした場合にShopContorllerのdeleteCartメソッドを発動させる。

前回作成したカート画面で「カートから削除」のボタンを押すと発動するルートです。
ルーティングを記述するのはもちろん何回も出てきた

routes/web.php

です。

以下を追加します。

Route::POST('/cartdelete','ShopController@deleteCart')

Route::Deleteという選択肢もありますが、ここではPOSTで行きましょう。
気になる方は調べてね。(正直どっちでもいい)

課題②Eloquantを使ってカートテーブルから該当の商品かつログインユーザーのidと一致するレコードを削除する。

この課題はもちろん①で作ったdeleteCartメソッドの処理内容です。
ShopController.phpにdeleteCartメソッドを作ります。

以下の処理を追記します。

    public function deleteCart(Request $request,Cart $cart)
   {

       //カートから削除の処理
       $stock_id=$request->stock_id;
       $message = $cart->deleteCart($stock_id);

       //追加後の情報を取得
       $my_carts = $cart->showCart();

       return view('mycart',compact('my_carts' , 'message'));

   }

引数でリクエストとcartモデルを使えるようにしています。
//追加後の情報を取得
$my_carts = $cart->showCart();
は他のメソッドでも使っている処理ですね。

こうやって関数化することで同じ処理を使い回しています。
使い回すという言い方だと手抜き感ありますが、

プログラミングの世界では反復する処理の関数化は基本的に正義です。

①仕様変更の際に関数化してる部分だけを修正すればOK
②コードが見やすくなる

特に①に関しては今回のケースでも、もしこのshowCart()内の処理に変更があった場合は、関数化していればそこだけの編集で全部に対応できますが、
もしaddCartやmyCartにそのままコピペして処理の中身を記述していた場合はもうすでに関数化している場合の3倍の修正が必要となるわけです。

今回のような簡易的なチュートリアルではまだいいですが、
これを実際の職場でしてしまうと

①修正に時間が何倍もかかって後輩に引かれる(そもそもどこで使ってたかも忘れてる)
②修正漏れが発覚して先輩に引かれる
③業務を引き継いだ新入社員や別会社の人に呪われる(これよくあるやつ)


っていう自体を起こしかねません。

リーダブルコードという名著にも書いてありますが、

一連の処理をコピペした瞬間に自分を疑ってください。

さて脱線しましたが
コントローラーの記述が終わったので
Cartモデルに
deleteCartメソッドの処理を書いていきます。

Models/Cart.phpを開いてdeleteCartメソッドを追加します。

public function deleteCart($stock_id)
{
       $user_id = Auth::id(); 
       $delete = $this->where('user_id', $user_id)->where('stock_id',$stock_id)->delete();
       
       if($delete > 0){
           $message = 'カートから一つの商品を削除しました';
       }else{
           $message = '削除に失敗しました';
       }
       return $message;
}

$user_id = Auth::id(); は何回も出てきているログインユーザーのid取得です。

$delete=$this->where('user_id', $user_id)->where('stock_id',$stock_id)->delete();

が今回のキモですが、
->where('user_id', $user_id)はよくあるSQLのwhere句です。
cartsテーブルのuser_idに$user_idと同じ値が入っていれば抽出してくれます。
さらにそこに連結させて、
->where('stock_id',$stock_id)をすることで
user_idが一致して、stock_idも一致するレコードを抽出します。
SQLのAND+whereと同じ働きですね。

もちろん
->orWhere()
というOR+whereと同じ働きをするのも準備されています。

そして
->delete();
で該当のレコードをバシュッと削除します。

削除を終えると
$deleteには
->delete()が影響を与えたレコードの数を返します。

つまり該当のレコードが一つ消えるはずなので、
「1」が格納されることになります。

なので条件分岐で
if($delete > 0){
    $message = 'カートから一つの商品を削除しました';
}else{
    $message = '削除に失敗しました';
}
このようになってるわけですね。

あとは削除した場合としていない場合のメッセージをコントローラーに返してあげます。

return $message;

これであとはいつも通りカートページが表示されます。

スクリーンショット 2020-02-07 3.05.11


2、カート内に合計金額を表示させよう

カート機能がだいぶ完成してきました。
今はカート内に商品が表示されているだけなのでカート内の合計金額を表示させたいと思います。

色々なやり方があるかと思います。

・コントローラーに書く?
・モデルに書く?
・ビューに書く?

結構周りのエンジニアでもどこに書くかは迷ってますね。
今回はモデル側のshowCartメソッドに追記することにしました。
(すでに共通化出来てるし!showの一部だし!)

もしViewのロジックなんだから独立させたいとかいうこだわりがある方は
LaravelにはViewComposerというviewロジックを分離して記述する機能があります。(今回レベルだとやりすぎ感は否めないですが)

興味ある方はのぞいて見て下さい。
ViewComposerについて

https://qiita.com/youkyll/items/c65af61eb33919b29e97

showCartメソッドに合計金額を取得する処理を追記します。

    public function showCart()
   {
       $user_id = Auth::id();
       $data['my_carts'] = $this->where('user_id',$user_id)->get();

       $data['count']=0;
       $data['sum']=0;
       
       foreach($data['my_carts'] as $my_cart){
           $data['count']++;
           $data['sum'] += $my_cart->stock->fee;
       }
       return $data;
   }

ここではすでに
$this->where('user_id',$user_id)->get();
でマッチするカート情報は取得しているのでそれの情報を元に合計値と個数を取得しました。
もちろんSQLをもう一度発行して、COUNTやSUMで個数や合計金額を取得するのも正解です。

コレクションのメソッドを使いたい方は
->count()などを使ってもいいかと思います。

自分はこのようにしていますが、
現場の慣習などに従えばOKです。
(処理速度などを突き詰めて行けば完全なる正解はあるのかもしれませんが、それよりもチームでやり方を統一できているか、理解しやすいかなどが大事かと思います。)

また少しそれますが、SQLの発行を減らすために余力がある方はEager Loadingについても知っておくといいかもしれません。
$my_cart->stock->fee;
などでは、->stockというリレーションのあるテーブルから情報を取得するタイミングで実はSQLがもう一度発行されています。
なのでカート内データが100個あったらそれだけSQLが増えてしまいます。
それを避けるための仕組みがEager Loadingです。
この記事では情報量が増えすぎてしまうので、割愛しますが大量のデータを扱う場合はEager Loadingを思い出してください。

https://qiita.com/shosho/items/abf6423283f761703d01

話を戻して、
returnでカート情報、個数、合計金額をすべてコントローラーに返すために$data[]に格納して返してあげています。

その結果ShopControllerを少しいじってあげる必要が出てきました。
ViewComposerが一瞬恋しくなりましたね。こういうことです。


ShopController.php

まずはmycartメソッドを編集します。

   public function myCart(Cart $cart)
   {
       $data = $cart->showCart();
       return view('mycart',$data);
   }

$my_cartが$dataに代わり、
compact()も使用しなくなりました。

compact()はPHPの関数で、変数を配列にする関数でした。
つまりすでに$dataには先ほどモデルのshowCartメソッドで配列として情報を格納しているのでこのままの形でOKなんです。

逆にスッキリしました。

addMycartとdeleteCartは少し追記が必要です。
先ほどは商品情報が詰まった$data配列をviewに送ってあげるだけでよかったですが、この二つのメソッドではカート処理の結果を表示する$messageもviewに連れて行きたいですね。

$data['message']=$message;

とするのもありですが、
商品情報を格納した$dataのなかにカートの処理結果のメッセージを格納するのも違和感がありますね。

こんな時は->with()を使って別口で値をviewに送ってみましょう。

   public function addMycart(Request $request,Cart $cart)
   {

       //カートに追加の処理
       $stock_id=$request->stock_id;
       $message = $cart->addCart($stock_id);

       //追加後の情報を取得
       $data = $cart->showCart();

       return view('mycart',$data)->with('message',$message); //追記

   }

   public function deleteCart(Request $request,Cart $cart)
   {

       //カートから削除の処理
       $stock_id=$request->stock_id;
       $message = $cart->deleteCart($stock_id);

       //追加後の情報を取得
       $data = $cart->showCart();

       return view('mycart',$data)->with('message',$message);//追記

   }

これでView側に全てのデータを送ることができました。

View側で受け取りの処理をしましょう。
せっかくなので次に実装する購入ボタンも記述します。

mycart.blade.phpの全容です。

@extends('layouts.app')

@section('content')
<div class="container-fluid">
   <div class="">
       <div class="mx-auto" style="max-width:1200px">
           <h1 class="text-center font-weight-bold" style="color:#555555;  font-size:1.2em; padding:24px 0px;">
           {{ Auth::user()->name }}さんのカートの中身</h1>

           <div class="card-body">
               <p class="text-center">{{ $message ?? ''}}</p><br>
               

                   @foreach($my_carts as $my_cart)
                       <div class="mycart_box">
                           {{$my_cart->stock->name}} <br>                                
                           {{ number_format($my_cart->stock->fee)}}円 <br>
                           <img src="/image/{{$my_cart->stock->imgpath}}" alt="" class="incart" >
                           <br>
                           <form action="/cartdelete" method="post">
                               @csrf
                               <input type="hidden" name="delete" value="delete">
                               <input type="hidden" name="user_id" value="{{ Auth::user()->id }}">
                               <input type="hidden" name="stock_id" value="{{ $my_cart->stock->id }}">
                               <input type="submit" value="カートから削除する">
                           </form>
                       </div>
                   @endforeach

{{-- 追加 --}}
                   <div class="text-center p-2">
                       個数:{{$count}}個<br>
                       <p style="font-size:1.2em; font-weight:bold;">合計金額:{{number_format($sum)}}円</p>  
                   </div>  
                   <form action="/checkout" method="POST">
                       @csrf
                       <button type="submit" class="btn btn-danger btn-lg text-center buy-btn" >購入する</button>
                   </form>

{{-- ここまで --}}
       
               <a href="/">商品一覧へ</a>


           </div>

           </div>
       </div>
   </div>
</div>
@endsection

これで
・カート内個数
・購入するボタン
も表示されるようになりました。

スクリーンショット 2020-02-07 10.04.19




これでOK!
と思いますが少し問題があります。


試しにカート内の商品を全て削除してみましょう。

スクリーンショット 2020-02-07 10.04.43

これはよくないですね。

カート内に商品が存在しないにも関わらず合計金額が出てたり
購入するボタンまで存在します。

bladeファイルはこういう時にとってもクールに条件分岐が可能です。
今回のケースだと、
ログインしているユーザーのカート情報が「あるかないか」で分岐ができそうですね。

■あった場合→今と同じ表示
■ない場合→「カートは空っぽです」

と表示させる。

で行きましょうか!

mycart.blade.phpを再編集します。

@extends('layouts.app')

@section('content')
<div class="container-fluid">
   <div class="">
       <div class="mx-auto" style="max-width:1200px">
           <h1 class="text-center font-weight-bold" style="color:#555555;  font-size:1.2em; padding:24px 0px;">
           {{ Auth::user()->name }}さんのカートの中身</h1>

           <div class="card-body">
               <p class="text-center">{{ $message ?? ''}}</p><br>
               
{{-- 追加 --}}
               @if($my_carts->isNotEmpty()) 
{{-- ここまで --}}
                   @foreach($my_carts as $my_cart)
                       <div class="mycart_box">
                           {{$my_cart->stock->name}} <br>                                
                           {{ number_format($my_cart->stock->fee)}}円 <br>
                           <img src="/image/{{$my_cart->stock->imgpath}}" alt="" class="incart" >
                           <br>
                           <form action="/cartdelete" method="post">
                               @csrf
                               <input type="hidden" name="delete" value="delete">
                               <input type="hidden" name="user_id" value="{{ Auth::user()->id }}">
                               <input type="hidden" name="stock_id" value="{{ $my_cart->stock->id }}">
                               <input type="submit" value="カートから削除する">
                           </form>
                       </div>
                   @endforeach
                   <div class="text-center p-2">
                       個数:{{$count}}個<br>
                       <p style="font-size:1.2em; font-weight:bold;">合計金額:{{number_format($sum)}}円</p>  
                   </div>  
                   <form action="/checkout" method="POST">
                       @csrf
                       <button type="submit" class="btn btn-danger btn-lg text-center buy-btn" >購入する</button>
                   </form>
       
{{-- 追加 --}}
               @else
                   <p class="text-center">カートはからっぽです。</p>
               @endif
{{-- ここまで --}}       
               <a href="/">商品一覧へ</a>
           </div>

           </div>
       </div>
   </div>
</div>
@endsection

@if($my_carts->isNotEmpty())
//$my_cartsに値が入っているとこの処理
@else
//入ってない時の処理
@endif

となっています。
ちょっと複雑な話になりますが
$my_cartsはコレクションなので
issetなどでは空かどうかを判別できません。

ちなみに先ほど一瞬出てきたコレクションのメソッドのcount()などは
コレクションの機能の一つです。

かなり機能豊富なので
余力がある方はのぞいてみてください。
https://readouble.com/laravel/6.x/ja/collections.html

とりあえずこれで
カート内に商品がある場合と


ない場合の処理を分けることができました。


3、購入機能の実装

カート機能がほとんど完成したところで、
カートからの購入機能を実装します。

①購入するボタンを押すと購入完了画面に遷移する
②カートテーブルから該当の商品を削除する
③Mailの送信内容を記入する
④Mailhogで擬似のメールを送信する。

でいきたいと思います。

Laravelに慣れてきた方は、②の項目で新規で購入履歴を保存するテーブルを作成して、カートテーブルから削除したデータを購入履歴テーブルに移管させてみてください。
今回は実装の予定はありませんが、購入者が自分の注文履歴を確認したり管理者側が販売の傾向などを知ることができる情報が蓄積されることになります。

4、購入するボタンを押すと購入完了画面に遷移する

とにもかくにもルーティングです。
すでに

/checkout

で購入が完了することになっているので、
web.phpで以下を追記します。

Route::post('/checkout', 'ShopController@checkout');

続いてShopControllerにcheckoutメソッドを作成します。

   public function checkout(Cart $cart)
   {
       return view('checkout');
   }

これでcheckout.blade.phpの表示まで出来ました。

checkout.blade.phpをresouces/viewsフォルダに作成します。
ファイルの中身は単純なものにしておきます。

checkout.blade.php

@extends('layouts.app')

@section('content')
<div class="container-fluid">
   <div class="">
       <div class="mx-auto" style="max-width:1200px">
           <h1 class="text-center font-weight-bold" style="color:#555555;  font-size:1.2em; padding:24px 0px;">
           {{ Auth::user()->name }}さんご購入ありがとうございました</h1>

           <div class="card-body">
               <p>ご登録頂いたメールアドレスへ決済情報をお送りしております。お手続き完了次第商品を発送致します。</p>
               <a href="/">商品一覧へ</a>
           </div>

           </div>
       </div>
   </div>
</div>
@endsection

特に説明は不要かと思いますのでこのまま進みます!

これでカートページの購入するボタンを押すと決済完了画面への遷移が出来ました!

スクリーンショット 2020-02-09 11.27.00


5、カートテーブルから該当の商品を削除する


ただ今のままではもちろん画面が遷移するだけです。
購入が完了したのでカート内から商品の削除をする必要がありますね。
shopControllerでとりあえずModelのメソッドの実行を記入します。

   public function checkout(Cart $cart)
   {
       $checkout_items = $cart->checkoutCart();       
       return view('checkout');
   }

実際の中身をcartモデルに書いていきましょう。

   public function checkoutCart()
   {
       $user_id = Auth::id(); 
       $checkout_items=$this->where('user_id', $user_id)->get();
       $this->where('user_id', $user_id)->delete();

       return $checkout_items;     
   }

と言ってもほとんど以前作ったdeleteCartの中身と差はありません。
ログインユーザーのIDを取得してそのIDと合致するレコード全てを削除しています。
今回は戻り値に削除した商品の情報を載せました。
$checkout_items=$this->where('user_id', $user_id)->get();で先に情報を取得してからカート内を削除しています。
あとでメールに記載するためのものです。

この状態でもう一度カートから削除するをクリックしてみましょう。


購入削除確認


これでカート情報の削除が完了しました!



6、購入完了のメールを送信する

ここまでで画面遷移とカート内削除は完了しました。
ここからは肝心なメールの送信機能を作っていきます。

今回はどんな環境でもメールが送信できてるかを確認できるように外部の機能を使わせてもらいます!

ローカル環境でのメール送信のテストにちょうどいいMailtrapくんです。

https://mailtrap.io/

アクセスしてから
なんでもいいのでサインインをすると、

いきなりこの画面になるかと思います。

スクリーンショット 2020-02-09 12.54.02

ここのDemo inboxをクリックしてもらって

スクリーンショット 2020-02-09 12.49.03

こんな画面になるのでオレンジの枠の上の部分を
「Laravel」に変更してください。

そして下のオレンジで囲まれた部分をコピーして
.envに上書きします。
.envはLaravelフォルダ自体の直下にいますよ!
(隠しファイルですのでVscodeなどから確認してください!)

.envの中にはすでにMAIL_DRIVERなどの設定をする部分があるのでそこに上書きします。
自分は最終的にこうなりました。


MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=xxxxxxxxxxx //mailtrapに書いてるやつ
MAIL_PASSWORD=xxxxxxxxxxx //mailtrapに書いてるやつ
MAIL_FROM_ADDRESS=Larashop@example.com
MAIL_FROM_NAME=Larashop
MAIL_ENCRYPTION=null

これでmailtrapを使う設定は完成しました!
早い!

次に送信するメール自体を作っていきます。
 appフォルダ(Laravel自体フォルダ)上でターミナルを開いて

php artisan make:mail Thanks --markdown="mails.thanks"

のコマンドを打ちます。

すると
①app/Mails/Thanks.php
②resouces/views/mails/thanks.blade.php

が出来上がります。
①がメールの送信機能を司るファイル
②がメールの本文が記載されるファイルです。

まずはShopControllerでメール送信を実行する記述をしましょう。

ShopControllerのcheckoutメソッドに以下を追記します。

    public function checkout(Cart $cart)
   {

     $cart->checkoutCart();
       Mail::to('test@example.com')->send(new Thanks); //追記
       return view('checkout');

   }

またShopControllerの頭の部分にも追記します。

use App\Models\Stock;
use App\Models\Cart;

use Illuminate\Support\Facades\Mail; //追記
use App\Mail\Thanks;//追記

これでメール送信の根幹であるMailファサードと、
さっき作ったThanks.phpが使えるようになりました。
今までと同じくもしMailファサードの動きを知りたい方はVenderフォルダへダイブしてください。(初学者はまだいいと思う)

なおMailtrapはあくまで開発用のツールなので送信履歴(Laravelの送信が成功したか)だけを確認できます。
toのtest@example.comのところに実際のアドレスとかを書いても実際には送信されないのでご留意を。

ちなみに普通ならここにはログインユーザーのメールアドレスが格納された変数などを入れます!

さてこの段階で実際にカートから購入ボタンを押してみましょう!
カートに好きな商品を入れて購入をやってみてください!
ちょっとだけ画面遷移の時に時間がかかりませんでしたか?

Mailtrapのdemo inboxを見ると、、、。

スクリーンショット 2020-02-09 13.15.58

すでにメール送信ができていましたね!
本番ではMailtrapでやっていたことを
本番のメール送信用のサーバーにやってもらいます。
.envの先ほど追記した項目を本番用に変えるだけです!

結構簡単にメール送信ができちゃいました!
あとはメールの内容を加筆するだけです!

7、購入完了のメール内容を編集する


いよいよ大詰めです!
購入完了メールには
・ユーザー名
・購入した商品
・決済誘導のボタン(決済機能はこの記事では実装しないよ)

があれば十分かなと思います。

Views/mails/thanks.blade.phpを丸っと置き換えます。

@component('mail::message')

{{ $user }}様<br>
この度はLarashopでのご購入ありがとうございます。<br>

お客様が購入した商品は<br>

@foreach ($checkout_items as $item)
・{{ $item->stock->name }}|{{ $item->stock->fee }}円
<br>
@endforeach

となります。<br>

下記の決済画面より決済を完了させてください。<br>

@component('mail::button', ['url' => ''])
決済画面へ
@endcomponent

<br>
{{ config('app.name') }}
@endcomponent

先に値を受け取りたい変数を準備しました。
$userで購入したユーザーの名前
$checkout_itemsで購入した商品情報を受け取りそれをforeachで展開しています。

なのでコントローラー側から
ユーザー名と購入した商品の情報をThanks.phpを経由して送ってあげましょう。

ShopControllerのcheckoutメソッドを修正します。


    public function checkout(Request $request,Cart $cart)
   {

       $user = Auth::user();
       $mail_data['user']=$user->name; //追記
       $mail_data['checkout_items']=$cart->checkoutCart(); //編集
       Mail::to($user->email)->send(new Thanks($mail_data));//編集
       return view('checkout');

   }
   

大体は一度見たことあるものばかりです。
Mail::to($user->email)->send(new Thanks($mail_data));
のnew Thanks($mail_data)と引数にメールに表示させてあげたい情報を持たせてあげています。
またせっかくなので$user->emailでログインユーザーのメールアドレスに送信されるようにしました。


続いて
Mail/Thanks.phpを編集しましょう。

    public function __construct($mail_data) //編集
   {
       $this->mail_data = $mail_data; //追記
   } 

   /**
    * Build the message.
    *
    * @return $this
    */
   public function build()
   {
       return $this->markdown('mails.thanks',$this->mail_data) //編集
                   ->subject('Larashopでのご購入ありがとうございます'); //追記
   }

まずはもともとあったpublic function __construct()に先ほど
コントローラーが引数で渡している値を受け取るために$mail_dataを追加しています。

そしてそのデータを他のメソッドでも使えるように、
$this->mail_data = $mail_data; 
としています。

そのおかげて今度は public function build()内で

$this->markdown('mails.thanks',$this->mail_data)

という形で$this->mail_data(コントーラーから送られてきた値)が
メールの本文となるthanks.blade.phpに送られているわけです。

またメールの件名を->subjectで指定することにしています。

それでは実際にまたカートに商品を入れて
購入ボタンを押してみましょう!

スクリーンショット 2020-02-09 15.46.14

できましたね〜。
件名
宛先
ユーザー名
購入商品
全てちゃんと表示されています。

なお、Thanks.phpっている??って思った方もいらっしゃると思いますが、

今回は処理が少なかったのでShopController側でメールに表示する情報の処理をやってしまったのでThanks.php(メールクラス)の出番が少なめでしたが、
メールに記載する内容をThanks.phpでやってもらえばShopControllerの記述がどんどん増えていわゆるファットコントローラーになっていくことを避けれます。

何でもかんでもShopControllerに書くのもダメだし、
今回みたいな少量の処理のためにThanks.php側で処理をするためにまたファサードを準備したりするのも何とも言えないし、
綺麗なコードを書くって永遠の課題ですね。

8、全体の調整

さてこれでショッピングサイトの大まかな機能は実装できました。

最後に細かい調整をしていきたいと思います。

まず

Laravel自体フォルダ直下の
config/app.phpを開いてください。

ここにはタイムゾーンなどの基本情報の設定が可能です。

timezone…UTCからAsia/Tokyoに変更
locale…enをjaに変更

該当の場所を探して編集してください。

これで時間設定が日本の時間になり、ブラウザでGoogle様が必要に翻訳をしようとし来るのをある程度避けられるはずです。

次にルーティングです。

routes/web.phpを開いてください。

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', 'ShopController@index');
Route::get('/mycart', 'ShopController@myCart')->middleware('auth');
Route::post('/mycart', 'ShopController@addMycart');
Route::post('/cartdelete', 'ShopController@deleteCart');
Route::post('/checkout', 'ShopController@checkout');

Auth::routes();

順番などは気にしなくていいのでこんな形になっているかと思います。

まず気づくのが

Route::post('/mycart', 'ShopController@addMycart');
Route::post('/cartdelete', 'ShopController@deleteCart');
Route::post('/checkout', 'ShopController@checkout');

たちが
->middleware('auth');がついていないのでログアウトしててもアクセスできてしまっています。
全部に->middleware('auth')をつけるのもありですがここは、もっとかっこよくルーティングしましょう。

Route::get('/', 'ShopController@index');

Route::group(['middleware' => ['auth']], function () {

    Route::get('/mycart', 'ShopController@myCart');
    Route::post('/mycart', 'ShopController@addMycart');
    Route::post('/cartdelete', 'ShopController@deleteCart');
    Route::post('/checkout', 'ShopController@checkout');
   
});

Auth::routes();

Routeをグループ化して、そのグループにauthミドルウェアを適用しました。

なお、コントローラーのコンストラクターでミドルウェアを呼び出してそのコンローラー内のメソッドを使うときはミドルウェアを使う〜とかの戦法も取れます。

最後に!

全ページにフッターをつけることを忘れていました。
(故意にと言っておきます)

今回は全ページがViews/layout/app.blade.phpを引き継いでいますので
そこに以下を追記してください。

〜省略〜

<main class="py-4">
   @yield('content')
</main>

{{-- 追記 --}}
<footer class="footer_design">

       @guest
           <p class="nav-item" style="display:inline;">
               <a class="nav-link" href="{{ route('login') }}" style="color:#fefefe; display:inline;">{{ __('ログイン') }}</a>

           @if (Route::has('register'))

                   <a class="nav-link" href="{{ route('register') }}" style="color:#fefefe; display:inline;">{{ __('会員登録') }}</a>
               </p>
           @endif
       
       @endguest
       <br>
       <div style="margin-top:24px;">
       なんでも売ります<br>
       <p style="font-size:2.4em">Larashop</p><br>
       </div>

       <p style="font-size:0.7em;">@copyright @mukae9</p>

   </footer>
{{-- ここまで --}}
    </div>
</body>
</html>

スクリーンショット 2020-02-09 16.28.32

フッターできましたね。

今回はview側の話でしたけど、
もしこのフッターの追加、、、

view側の共通部分を分離せずに各ページに記述してたらどうなるでしょうか??

考えただけでもメンドくさいですね。
今まで作ったページ全てに書いていく必要があります。

何回もこの記事でも書きますが、
こうして補修や点検がしやすいコードを目指すことは
大正解とは言えるかは分かりませんが、失敗することは基本的にはないと思います。

プログラム側の方も同じで共通化部分をクラス化したり、機能を分離することは現在進行で作っている自分からしたら少々めんどくさい、難しいっと思ってしまうかもしれませんが、

「いつか補修する」
「いつか引き継ぐ」
「いつかチームで作る」

って考えると割と必須な部分になってくるかと思います。
いきなりは難しいと思いますが、
補修しやすいコードを書くってのも大事なんだよと頭の隅に置いておくといいかもしれません。

9、最後に

ここまでお付き合いくださった皆様ありがとうございました。
まだまだLaravelのことで話せてないことの方が圧倒的に多いのですが、とりあえずLaravelの動きを知るためのチュートリアルとしての役割が果たせたのであれば幸いです。

このショッピングサイトですが
・Apiを使ったSNSログイン
・商品検索
・決済機能
・ショップ側の商品追加機能

などなどまだまだ拡張できる要素があります。

あと間違ったURLでのリダイレクトとか、トランザクションとか購入ページのリロード問題とか、

そこらへんの記事もまた近々書くと思われますのでその時はぜひまたよろしくお願いします。(多分有料にする!数百円だけど!)

ただnoteに書くかわからんので
Twitterフォローしてくれたら喜びます。

https://twitter.com/Mukae9

あとめっちゃ書くのに時間かかったので今までの記事に全部いいねしていってください…笑

それではまた別の記事でお会いいたしましょう〜。
ありがとうございました!



この記事が気に入ったらサポートをしてみませんか?