---
# System prepended metadata

title: Laravel購物車實作遇到常用方法

---

# 購物車實作遇到常用方法
# 命名auth及驗證套件
```php=
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
```

# 產出Controller
php artisan make:controller Controller名稱



# 假資料建立

php artisan make:seeder OrdersTableSeeder
{Model名稱複數型}TableSeeder.php

# Form表單POST Controller驗證方式
1. 為controllers/ShopController.php示範接收到的值
```php=
            $validator=Validator::make($request->all(),[
                'receive_name' => 'required|string|max:50',
                'receive_phone' => 'required|string|max:50',
                'receive_address' => 'required|string|max:250',
                'pay_type_id' => 'required|integer',
                'remark' => 'required|string|max:250'
            ]);
            if($validator->fails()){
                return redirect('/checkCart')->withErrors($validator)->withInput(); //錯誤處理
                // withErrors ->將錯誤欄位帶入Session
                //withInput ->返回頁面時會將原資料帶入
            }
```
# 直接從Controller新增至資料庫方式
1. Order::為資料庫要先至Controller最上面先use App\Models\Order;
```php=
$order = Order::create([
    'user_id' => $userID,
    'receive_name' => $request->receive_name,
    'receive_phone' => $request->receive_phone,
    'receive_address' => $request->receive_address,
    'pay_type_id' => $request->pay_type_id,
    'total'=> $row->price * $row->quantity ,
    'remark' => $request->remark,
])->id;
```
2. 第二種新增方式
```php=
order_info = new OrderInfo();
                $order_info -> order_num = $this->generateOrderNum();
                $order_info -> user_id = $request->session()->get('id');
                foreach($request_order_only as $field){
                    if(isset($request->$field)){
                        $order_info -> $field = $request->$field;
                    }
                }
                if(isset($request->same_order_checkin)){
                    $order_info -> same_order_checkin = 1;
                    $order_info -> checkin_name = $request->order_name;
                    $order_info -> checkin_phone_number = $request->order_phone_number;
                    $order_info -> checkin_email = $request->order_email;
                    $order_info -> checkin_zip_code = $request->order_zip_code;
                    $order_info -> checkin_county = $request->order_county;
                    $order_info -> checkin_district = $request->order_district;
                    $order_info -> checkin_address = $request->order_address;
                }else{
                    $order_info -> same_order_checkin = 0;
                }
                $order_info->save();
$id = $order_info->id;
```
4. 記得先將Order資料表先新增白名單
路徑為models/Order.php
```php=
    protected $fillable = [
        'user_id',
        'pay_type_id',
        'remark',
        'receive_name',
        'receive_phone',
        'receive_address',
        'total',
    ];

    protected $hidden = [//隱藏欄位
        'password',
        'remember_token',
    ];

    protected $casts = [ //日期專用
        'email_verified_at' => 'datetime',
    ];
```
# Controller需要利用Model Common Function用法
1. models/Product.php
```php=
    public function getQuantityStock($cartContent){
        foreach ($cartContent as $row) {
            $product = Product::find($row->id);
            if($product->quantity - $row->quantity < 0){
                flash($product->name."目前商品數量只剩".$product->quantity)->error();
                return false;
            }
        }
        return true;
    }
```
2. ShopController.php
```php=
    $userID    = Auth::user()->id;
    $cartContent = \Cart::session($userID)->getContent();
    $product = new Product;
    if($product->getQuantityStock($cartContent)!==true){
        return redirect('/');
    }
```
1. 也可再Controll用
controller.php
```php=
protected function orderInfoDataToChinese($datas){
        foreach($datas as $key=>$array){
            if($array["payment"]=="credit_card"){
                $datas[$key]["payment_chinese"]="信用卡";
            }else{
                $datas[$key]["payment_chinese"]="匯款";
            }
            if($array["status"]=="ordered"){
                $datas[$key]["status_chinese"]="尚未付款";
            }elseif($array["status"]=="payment_failed"){
                $datas[$key]["status_chinese"]="付款失敗";
            }elseif($array["status"]=="payment_success"){
                $datas[$key]["status_chinese"]="付款成功";
            }elseif($array["status"]=="order_completed"){
                $datas[$key]["status_chinese"]="訂單完成";
            }
     
        }
        return $datas;
    }
IndexController.php
$order_number=parent::orderInfoDataToChinese($order);
```
parent::
# 訊息套件
composer require laracasts/flash
# 購物車
## 購物車套件
composer require "darryldecode/cart"
修改購物車套件config/app.php(⾮必須)
加入以下到Service Provider Array
    Darryldecode\Cart\CartServiceProvider::class
加入以下到Alias Array
'Cart' =>
Darryldecode\Cart\Facades\CartFacade::class

## 購物車套件將資料加入用法
1. id及name...等key值不能修改會出錯
2. id及name和price和quantity不可為空值也會出錯
```php=
\Cart::session($userID)->add(array(
    'id' => $productId,
    'name' => $item->name,
    'price' => $item->price,
    'quantity' => $request->quantity,
    'attributes' =>  array(),
    'associatedModel' => $item
));
```
## 購物車套件將資料移除
```php=
//$rowId=資料的id
\Cart::session($userID)->remove($rowId);
```
## 購物車套件抓取資料及數量用法
```php=
$cartContent = \Cart::session($userID)->getContent();//購物車儲存的資料
$cartQty= \Cart::session(Auth()->user()->id)->getTotalQuantity();//購物車的總數量
```
## 購物車在view可直接查看總金額

    ${{ \Cart::getTotal() }}

## 購物車放入全域變數
1.  app/Providers/AppServiceProvider.php
2. 前面記得放use Illuminate\Support\Facades\Auth;
```php=
    public function boot()
    {
        view()->composer('*',function($view) {
            if(Auth::check()){
                $cartContent = \Cart::session(Auth()->user()->id)->getContent();
                $cartQty= \Cart::session(Auth()->user()->id)->getTotalQuantity();
                $view->with('user', Auth::user());
                $view->with('cartContent', $cartContent); 
                $view->with('cartQty', $cartQty); 
            }
        });
    }
```
    
# E-Mail寄信
1. 進入Gmail信箱按照下圖產生應用程式密碼，將產生的密碼為ENV的信箱密碼
![](https://i.imgur.com/JFIoeaG.png)
2. 修改.env 他是根據config/mail.php的預設
    MAIL_MAILER=smtp
    MAIL_HOST=smtp.googlemail.com
    MAIL_PORT=465
    MAIL_USERNAME=信箱
    MAIL_PASSWORD=信箱密碼
    MAIL_ENCRYPTION=ssl

3. php artisan make:mail Contact 
產出來在app/Mail底下

修改Contact.php
```php=
    protected $params;
    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($params)
    {
        $this->params = $params;
    }
    /**
     * Get the message content definition.
     *
     * @return \Illuminate\Mail\Mailables\Content
     */
    public function content()
    {
        return new Content(
            view: 'mail.email_contact',
            with:['params' => $this->params],
        );
        <!-- return $this->view('mail.system_message')
                    ->with(['params'=>$this->params
                ]); -->
    }
```
4. 接下來至web.php增加Route
Route::post('/contact', [MailController::class, 'contactSendMail'])->name('contactSendMail');;
5. 請至Controller修改程式內容
    * 必須至Controller最上面加入兩段
    ```php=
        use Mail;
        use App\Mail\Contact;
    ```
    * 依照上路徑為controller/MailController 的contactSendMail Function修改
    ```php=
    public function contactSendMail(Request $request)
    {
        $to = collect([['name' => '客服信箱','email'=>'peter777200067@gmail.com']]);
        $params = ['name' => $request->name,
                'phone'=>$request->phone,
                'email'=>$request->email,
                'message'=>$request->message,
        ];
        Mail::to($to)->send(new Contact($params));
    }
    ```
6. 請新增好view視圖
依照上面為範例view為views/mail/emai_contact.blade.php
```php=
              <div class="mb-4">
                <h1 class="h3 mb-3 fw-normal">聯絡我們</h1>
              </div>
              <div class="form-floating form-outline mb-4">
                <label for="floatingInput">姓名:{{ $params['name'] }}</label>
              </div>

              <div class="form-floating form-outline mb-4">
                <label for="floatingInput">電話:{{ $params['phone'] }}</label>
              </div>

              <!-- Password input -->
              <div class="form-floating form-outline mb-4">
                <label for="floatingEmail">郵件:{{ $params['email'] }}</label>
              </div>

              <div class="form-floating form-outline mb-4">
                <label for="floatingTextarea">訊息內容:{{ $params['message'] }}</label>
              </div>
```
## 本地化Localized

### 本地化Localized用法
1. 修改config/app.php
應⽤的預設語⾔被存在 config/app.php 設定檔內。可修改這個值以適合應⽤的需求
'locale' => ‘zh_TW',//修改預設為繁體中文
'fallback_locale' => 'en',//為替代語系一樣在config/app.php內


2. 兩種方式新增資料夾至lang/底下
    1. 短key方式php，如中文resources/lang/zh_TW/message.php
    php可隨意命名
    Blade檔使用時為{{ __('message.name') }}
    前面為php檔案後面為陣列key值
    ```php=
    <?php 
	    return 
	    ['name'=>'姓名',
        ....];
    ?>
    ```
    2. 長key方式Json，新增檔案至resources/lang/zh_TW.json
    新增檔案zh_TW.json
    需大小寫相符
    Blade檔使用時為{{ __('name') }}
    ```json=
    {
        "name" : "姓名",
    }
    ```
### Localized函式

1. 取得當前語系
```php=
$locale = App::getLocale();
```
2. 是否為英文語系
```php=
if (App::isLocale('en')) {
    //預設語系確實為en
}
```
3. 後端引用本地化文字
檔名.陣列key
```php=
<?php
trans('auth.failed');
```
trans('auth.failed')跟 __('auth.failed');一樣
4. 切換語系
```php=
<?php
App::setLocale('en');
```

### Localized在說明文字裡面加入資料
純說明文字用翻譯當然很簡單，不過如果說明文字還需要加上一些資料，比方說 嘗試登入次數太多次
```php=
<?php
'throttle' => '嘗試登入太多次，請 :seconds 秒後再嘗試',
```
裡面的 :seconds

這個部分，我們可以在 trans() 轉換時，透過陣列的方式傳入。
```php=
<?php
Route::get('/test', function(){
    return trans('auth.throttle', ['seconds' => 5]);
});
```
