264

Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

  • Upload
    others

  • View
    50

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example
Page 2: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

1.1

1.2

1.2.1

1.2.2

1.3

1.3.1

1.3.2

1.3.2.1

1.3.2.2

1.3.2.3

1.3.2.4

1.3.3

1.3.3.1

1.3.3.2

1.3.3.3

1.3.4

1.3.4.1

1.4

1.4.1

1.4.2

1.4.2.1

1.4.3

1.4.3.1

1.5

1.6

1.6.1

1.6.2

目錄

介紹

環境

.env檔案

Homestead

資料庫

Migration(遷移)

EloquentModel(模型)

設定

關聯

魔術函式

使用Eloquent

常見問題

無法取得查詢Log

使用大量資料的方式新增時無法新增

使用中繼模型繼承Eloquent模型造成無法使用大量資料新增

PostgreSQL

安裝PostgreSQLODBCdriver

HTTP

請求

路由(Route)

子網域路由

中介層(Middleware)

ETagMiddleware

視圖(View)

服務

認證登入(Auth)

郵件(Mail)

2

Page 3: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

1.6.2.1

1.6.2.2

1.6.3

1.6.3.1

1.6.3.2

1.6.4

1.6.4.1

1.6.5

1.6.5.1

1.6.6

1.6.6.1

1.6.6.2

1.6.6.3

1.6.7

1.6.8

1.6.9

1.6.10

1.6.10.1

1.7

1.7.1

1.7.2

1.7.3

1.7.3.1

1.7.4

1.8

1.8.1

1.8.1.1

1.8.2

1.8.2.1

1.8.3

使用Gmail寄信

使用Mailgun寄信

隊列(Queue)

database

非同步(async)

輔助方法(Helpers)

自定義輔助方法

單元測試(UnitTest)

PostCSRF錯誤

錯誤與日誌

在單元測試顯示例外

日誌記錄層級

日誌巨集

加密

雜湊

任務排程

Elixir

使用Elixir合併CSS與JS

設計模式

服務容器

PSR

Model模型

架構設計準則

學習資源

套件

Debug

Artisantail

工具

Carbon

設計模式

3

Page 4: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

1.8.4

1.8.5

1.8.6

1.8.6.1

1.8.6.1.1

1.8.6.1.2

1.8.6.1.3

1.8.6.1.4

1.8.6.1.5

1.8.6.2

1.9

1.9.1

1.9.2

1.9.3

1.9.4

1.9.5

1.9.6

1.9.7

1.10

1.10.1

1.10.2

1.10.3

1.11

1.11.1

1.11.2

1.11.3

1.11.4

1.11.5

1.11.6

1.11.7

文字

視圖

認證

OAuth2

ClientCredentials

PasswordGrant

RefreshToken

PasswordGrantwithScope

驗證AccessToken

JWT

正式主機環境

安裝Nginx

安裝php7

安裝composer

安裝MySQL5.7

安裝Memcached

安裝Redis

安裝Let'sEncrypt

其他常見問題

CalltoundefinedmethodgetCachedCompilePath()

變更專案目錄名稱導致View無法讀取

Laravel5.1目錄結構異動

學習資源

官方

社群

會議議程

工作

文件

文章

套件

4

Page 5: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

1.11.8

1.11.9

1.11.10

1.11.11

1.11.12

1.11.13

服務工具

教學影片

教學網站

編輯開發

主機

成功案例

5

Page 6: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Laravel5學習筆記

作者:KeJyun

書籍網址

項目 網址

GithubPage http://kejyun.github.io/Laravel-5-Learning-Notes-Books/

GitBook http://kejyuntw.gitbooks.io/laravel-5-learning-notes/

聯絡資訊

項目 網址

Email [email protected]

LinkedIn https://tw.linkedin.com/in/kejyun

Github https://github.com/kejyun

Facebook http://fb.me/kejyunTaiwan

Blog http://blog.kejyun.com

所有KeJyun著作

HighScalingWebsitesStructureLearningNotes大型網站架構學習筆記

Laravel4學習筆記

Laravel5學習筆記

SEO學習筆記

gulp學習筆記

WebDeveloperLearningResource網頁開發學習資源

MacOSX新手入門

RubyonRails學習筆記

介紹

6

Page 7: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

介紹

7

Page 8: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Laravel5環境

這裏會介紹一些Laravel5會用到的機器環境相關問題

環境

8

Page 9: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

.env檔案

Laravel4.env檔案

在Laravel4的時候,我們通常會在 /bootstrap/start.php中,去設定我們的

hostname是屬於哪一種開發環境,再針對不同的開發環境有不同的設定檔

( .env.*.php)

<?php

$env=$app->detectEnvironment(array(

'local'=>array(

'KeJyun-Macbook'

),

'dev'=>[],

'testing'=>[],

'staging'=>[],

));

.env.*.php設定檔通常放在根目錄下,這些檔案不會在版本控制當中

app/

bootstrap/

public/

vendor/

.env.php

.env.local.php

.env.dev.php

.env.testing.php

.env.staging.php

在Laravel4.env設定檔案長的會像是這樣:

.env檔案

9

Page 10: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

return[

'DB_USERNAME'=>'root',

'DB_PASSWORD'=>'password',

];

我們的 config檔案就可以使用 $_ENV去讀取當前環境的設定檔資料

<?php

$_ENV['DB_USERNAME']

$_ENV['DB_PASSWORD']

Laravel5.env檔案

在Laravel5使用 .env檔案的方式跟Laravel4有很大的不同,在Laravel5中就只有 .env與 .env.example這兩個檔案而已, .env檔案不會在版本控制

中, .env.example則會在版本控制中

自己可以根據自己的環境設定目前的.env狀況,而.env.example則是可以讓大家

參考.env的範例用的,自己根據自己目前的環境設定是什麼樣到開發還境

(local、dev、stage、production...etc)。

在Laravel5.env設定檔案長的會像是這樣:

APP_ENV=local

APP_DEBUG=true

APP_KEY=VDqhX1LiHKEReHH16YNEzxUZziOdZVtT

DB_HOST=localhost

DB_DATABASE=homestead

DB_USERNAME=homestead

DB_PASSWORD=secret

CACHE_DRIVER=file

SESSION_DRIVER=file

.env檔案

10

Page 11: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

然後我們在設定檔中,我們可以使用 env()函式去取得我們設定檔案中的設定,

會設定像是這樣的設定

//config/app.php

[

'debug'=>env('APP_DEBUG',false),

]

//config/database.php

[

'pgsql'=>[

'driver'=>'pgsql',

'host'=>env('DB_HOST','localhost'),

'database'=>env('DB_DATABASE','forge'),

'username'=>env('DB_USERNAME','forge'),

'password'=>env('DB_PASSWORD',''),

'charset'=>'utf8',

'prefix'=>'',

'schema'=>'public',

],

]

env()中第一個參數是 .env檔案中的設定鍵值名稱,第二個參數是預設值,

若讀取不到環境設定鍵值則會使用預設值

這樣在每個人的開發環境只要去管理自己的 .env檔案就好,不需要像Laravel4需要在config資料夾中建立各種環境變數設定的資料夾,像是

config/local/database.php或 config/stage/database.php。

參考資料

EnvironmentsandConfiguration-Laravel5Fundamentals

.env檔案

11

Page 12: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Homestead常常我我們需要開發WebApplication時候,都需要花很長的時間把環境建置起來,

而Homestead以讓我們透過簡單的設定檔,輕鬆的建置好整個執行環境,讓我們能

夠更專注於在開發上

OSXElCapitan10.11.3

Laravel5.2

Vagrant1.8.1

Virtualbox5.0.14

安裝Virtualbox從VirtualBox官方網站下載並安裝VirtualBox

下載連結:http://download.virtualbox.org/virtualbox/5.0.14/VirtualBox-5.0.14-105127-OSX.dmg

安裝Vagrant從Vagrant官方網站下載並安裝Vagrant

下載連結:https://releases.hashicorp.com/vagrant/1.8.1/vagrant_1.8.1.dmg

安裝HomesteadVagrantBox在VirtualBox及Vagrant安裝完後,使用下列指令將Homestead加入您的虛擬主

機中

vagrantboxaddlaravel/homestead

Homestead

12

Page 13: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用Git複製Laravelhomestead並建立Homestead設定檔

$gitclonehttps://github.com/laravel/homestead.gitHomestead

$cdHomestead

~/Homestead$bashinit.sh

建立sshkey

$ssh-keygen-trsa-C"kejyun@homestead"

編輯Homestead設定檔

$vim~/.homestead/Homestead.yaml

確認設定檔中sshkey有對應到正確的路徑

authorize:~/.ssh/id_rsa.pub

keys:

-~/.ssh/id_rsa

設定虛擬主機提供者

vagrant支援 virtualbox, vmware_fusion或 vmware_workstation這幾個

虛擬主機,我們使用VirtualBox所以就填入virtualbox

provider:virtualbox

設定本機程式碼路徑對應到測試環境的路徑共用資料夾

Homestead

13

Page 14: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

map:本機路徑

to:Vagrant測試機路徑

程式路徑

folders:

-map:~/Code

to:/home/vagrant/Code

-map:~/laravel52

to:/home/vagrant/laravel52

網站路徑

sites:

-map:kejyun.app

to:/home/vagrant/laravel52/public

Homestead

14

Page 15: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

設定 /ect/hosts對應本機網址到Vagrant

$sudovim/etc/hosts

加入下列設定

Homestead

15

Page 16: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

192.168.10.10kejyun.app

IP位址為Homestead.yaml設定中的ip設定值,kejyun.app則是參照設定檔

中的sitesmap設定有哪些則加進去hosts設定檔中

啟動Vagrant

~/Homestead$vagrantup

在剛剛使用Git複製下來的homestead資料夾中執行vagrantup指令,會自動下

載virtualbox相關的虛擬主機設定,並依照設定檔設置虛擬主機。

設定完成後可以開啟瀏覽器到http://kejyun.app看看Homestead是否有正常啟動,

若看到下列畫面表示可以正常運作了!!!

Homestead

16

Page 17: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

備註

若要關閉Homestead虛擬機器,則可以使用下列指令關閉

vagranthalt

若設定檔有修改要重新讀取,則可以使用下列指令重新讀取設定

vagrantprovision

SSLread:error:00000000:lib(0):func(0):reason(0),errno60

Homestead

17

Page 18: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

若在啟動homestead時出現SSLread的錯誤訊息的話,可以重新加入新的

homesteadvagrandbox

$vagrantup

Bringingmachine'default'upwith'virtualbox'provider...

==>default:Box'laravel/homestead'couldnotbefound.Attempt

ingtofindandinstall...

default:BoxProvider:virtualbox

default:BoxVersion:>=0.4.0

==>default:Loadingmetadataforbox'laravel/homestead'

default:URL:https://atlas.hashicorp.com/laravel/homestead

==>default:Addingbox'laravel/homestead'(v0.4.4)forprovide

r:virtualbox

default:Downloading:https://atlas.hashicorp.com/laravel/bo

xes/homestead/versions/0.4.4/providers/virtualbox.box

Anerroroccurredwhiledownloadingtheremotefile.Theerror

message,ifany,isreproducedbelow.Pleasefixthiserrorand

try

again.

SSLread:error:00000000:lib(0):func(0):reason(0),errno60

加入新的homesteadvagrandbox

vagrantboxadd--insecure-claravel/homesteadhttp://atlas.has

hicorp.com/laravel/boxes/homestead

Homestead

18

Page 19: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$vagrantboxadd--insecure-claravel/homesteadhttp://atlas.h

ashicorp.com/laravel/boxes/homestead

==>box:Loadingmetadataforbox'http://atlas.hashicorp.com/la

ravel/boxes/homestead'

Thisboxcanworkwithmultipleproviders!Theprovidersthatit

canworkwitharelistedbelow.Pleasereviewthelistandchoos

e

theprovideryouwillbeworkingwith.

1)virtualbox

2)vmware_desktop

Enteryourchoice:1

==>box:Addingbox'laravel/homestead'(v0.4.4)forprovider:v

irtualbox

box:Downloading:https://atlas.hashicorp.com/laravel/boxes/

homestead/versions/0.4.4/providers/virtualbox.box

==>box:Successfullyaddedbox'laravel/homestead'(v0.4.4)for

'virtualbox'!

加入完成後,再重新啟動homestead即可

$vagrantup

參考資料

SayHellotoLaravelHomestead2.0Laravel-HomesteadVirtualboxVagrantVagrant常用指令

SSLread:error·Issue#401·Varying-Vagrant-Vagrants/VVVVagrant:Fixforerror60/SSLread-Slick

Homestead

19

Page 20: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Homestead

20

Page 21: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

資料庫

這裏會介紹一些Laravel使用的資料庫

資料庫

21

Page 22: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Migration這裏會介紹如何在Laravel5使用Migration管理資料庫

Migration指令

建立Migration

$phpartisanmake:migrationcreate_users_table--create="users"

Migration建立之後的檔案會放在

database/migrations/2015_04_11_134630_create_users_table.php

Migration檔案最前面的日期會依照你建立Migration的時間自動產生,所以每

個人看到的檔名皆會不同在後面加了 --create的參數可以告訴

Migration,我們要做建立 user資料表的動作,檔案內容會像這樣:

Migration(遷移)

22

Page 23: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

//database/migrations/2015_04_11_134630_create_users_table.php

useIlluminate\Database\Schema\Blueprint;

useIlluminate\Database\Migrations\Migration;

classCreateUsersTableextendsMigration{

/**

*Runthemigrations.

*

*@returnvoid

*/ㄒ

publicfunctionup()

{

Schema::create('users',function(Blueprint$table)

{

$table->increments('id');

$table->timestamp();

});

}

/**

*Reversethemigrations.

*

*@returnvoid

*/

publicfunctiondown()

{

Schema::drop('users');

}

}

異動資料表欄位資料

如果我們要在 users資料表中加欄位(或是其他改變資料表結構),我們可以用

這樣的指令去建立Migration

Migration(遷移)

23

Page 24: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$phpartisanmake:migrationadd_email_to_users_table--table="u

sers"

在後面加了 --table的參數可以告訴Migration,我們要做異動 user資料

表的動作,檔案內容會像這樣:

Migration(遷移)

24

Page 25: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

//database/migrations/2015_04_12_154720_add_email_to_users_tabl

e.php

useIlluminate\Database\Schema\Blueprint;

useIlluminate\Database\Migrations\Migration;

classAddEmailToUsersTableextendsMigration{

/**

*Runthemigrations.

*

*@returnvoid

*/

publicfunctionup()

{

Schema::table('users',function(Blueprint$table)

{

$table->string('email',180);

});

}

/**

*Reversethemigrations.

*

*@returnvoid

*/

publicfunctiondown()

{

Schema::table('users',function(Blueprint$table)

{

$table->dropColumn('email');

});

}

}

原先的建立資料表會用 Schema::create(),而異動資料表則會用

Schema::table()去做異動

Migration(遷移)

25

Page 26: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

列出目前所有Migration狀態

$phpartisanmigrate:status

執行Migration

$phpartisanmigrate

恢復上一版本的Migration

$phpartisanmigrate:rollback

清除所有版本的Migration

$phpartisanmigrate:reset

清除所有版本的Migration並重新執行

$phpartisanmigrate:refresh

備註

欄位異動

若做欄位異動Migration後需要rollback,若丟出例外錯誤時,則使用composer安裝 doctrine/dbal後即可解決rollback的問題

$composerrequiredoctrine/dbal

Migration(遷移)

26

Page 27: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安全性

在剛開始開發產品的時候,有時候資料表有做小小的修改或異動,為了圖方便,我

們常常會使用 migrate:reset或 migrate:refresh去清空我們的資料,重建

資料表。

但如果產品已經上線了,這個指令就會是一個非常危險的指令,企業產品最重要的

資產就是 資料,這個指令會導致所有的資料都被清除,所以請上線後小心謹慎去

使用。

參考資料

遷移和資料填充-Laravel.twMigrations-Laracasts

Migration(遷移)

27

Page 28: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

EloquentModel這裏會介紹如何在Laravel5使用EloquentModel管理資料庫

EloquentModel(模型)

28

Page 29: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Eloquent設定

設定可以大量新增的欄位

Eloquent為了避免特定欄位(像是id,created_at...)被使用者故意傳入大量

(Mass)資料去進行修改,所以Eloquent會自動保護欄位不被大量異動(MassAssignment),像是:

//新增

App\User::Create([

'first_name'=>'KeJyun',

'last_name'=>'Hong',

'email'=>'[email protected]',

]);

//更新

$user=App\User::find('1');

$user->update([

'email'=>'[email protected]',

]);

如果我們需要異動這些欄位,需要在Model裡面設定 $fillable的欄位,這樣

就可以使用大量資料的方式,去新增或異動資料表欄位資料。

classUserextendsModel{

protected$fillable=['first_name','last_name','email'];

}

設定需要被保護的欄位

設定

29

Page 30: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

我們也可以使用 $guarded指定某些欄位需要被保護,能被大量新增或異動

classUserextendsModel{

protected$guarded=['id','password'];

}

我們也可以設定所有欄位都不能被大量新增或異動

classUserextendsModel{

protected$guarded=['*'];

}

設定欄位為時間資料欄位

我們可以很簡單的使用Carbon去做時間的資料處理,預設的 created_at與updated_at是使用Carbon當作儲存的資料格式

設定

30

Page 31: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$article=\App\Article::find(1);

//created_at='2014-03-1823:59:59'

//取得created_at年份

//2014

dd($article->created_at->year);

//取得created_at月份

//03

dd($article->created_at->month);

//取得created_at6天後的時間

//2014-03-2423:59:59

dd($article->created_at->addDays(6));

//取得created_at格式化為Y-m的時間

//2014-03

dd($article->created_at->format('Y-m'));

//取得created_at格式化為人可閱讀的時間

//1yearago

dd($article->created_at->diffForHumans());

若我們自己新增了時間的欄位像是 published_at,則Model沒有自動將此欄位

的資料設為Carbon的資料格式

我們可以在Model中設定 $dates欄位中的資料,可以指定欄位資料格式為

Carbon的資料格式

classArticleextendsModel{

protected$dates=['published_at'];

}

設定資料庫的連線

設定

31

Page 32: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

我們也可以使用 $connection指定模型需要用哪個資料庫連線去做查詢

classUserextendsModel{

protected$connection='custom_connection_name';

}

設定主鍵不要自動新增

使用Eloquent去建立模型(Model)時,預設主鍵會使用自動新增(Auto-increment)的方式去新增,若要自行定義主鍵時,則要設定 $incrementing為false,將自動新增的功能關閉~

classUserextendsModel{

public$incrementing=false;

}

設定主鍵欄位名稱

使用Eloquent去建立模型(Model)時,預設會將主鍵欄位名稱設為 id,若有

需要異動主鍵欄位名稱的話,則要設定 $primaryKey變數,設為自行定義的欄

位名稱

classUserextendsModel{

protected$primaryKey='my_primary_column_name';

}

參考資料

Eloquent101-Laracast

設定

32

Page 33: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Dates,Mutators,andScopes-LaracastEloquentORM-Laravel.tw

設定

33

Page 34: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Eloquent關聯

假如我們有兩個模型,「文章(Article)」及「使用者(Users)」,假設一個情

境,1個使用者可以寫多篇的文章,但1篇文章只能被1個使用者發表

如果我們想要透過關聯關係,從使用者模型去取得使用者的文章,就像:

//取得使用者編號1的物件

$user=\App\Users::find(1);

//取得使用者的所有發表的文章

$user->articles();

我們會想要使用者模型內設定這樣的關聯關係,就像:

classUsersextendsModel{

//設定使用者擁有許多文章

publicfunctionarticles(){

return$this->hasMany('App\Article');

}

}

如果我們想透過關聯關係,從文章模型去取得是哪一個使用者發表文章,就像:

//取得文章編號1的物件

$article=\App\Article::find(1);

//取得發表文章的使用者資訊

$user=$article->user();

關聯

34

Page 35: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

classArticleextendsModel{

//設定文章屬於某一的使用者

publicfunctionuser(){

return$this->belongsTo('App\User');

}

publicfunctionowner(){

return$this->belongsTo('App\User');

}

publicfunctionwriter(){

return$this->belongsTo('App\User');

}

}

設定關聯屬性的函式名稱可以自訂,看自己覺得什麼樣的名稱適合自己就可以了,

自訂完後一樣可以使用關聯的方式,撈取出發表文章使用者的資訊

//取得文章編號1的物件

$article=\App\Article::find(1);

//取得發表文章的使用者資訊

$owner_user=$article->owner();

$writer_user=$article->writer();

設定完之後,必須確定文章(Article)資料表有使用者編號(user_id)的外來鍵欄

關聯

35

Page 36: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

//database/migrations/2015_04_13_154720_create_article_table.php

useIlluminate\Database\Schema\Blueprint;

useIlluminate\Database\Migrations\Migration;

classCreateArticleTableextendsMigration{

publicfunctionup()

{

Schema::table('article',function(Blueprint$table)

{

//發表文章使用者編號

$table->integer('user_id')->unsigned();

//設定外來鍵

$table->foreign('user_id')

->references('id')

->on('users')

->onDelete('cascade');

});

}

publicfunctiondown()

{

Schema::drop('users');

}

}

參考資料

EloquentRelationships-Laracasts

關聯

36

Page 37: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Eloquent魔術函式

預先處理被異動的欄位資料

在使用Eloquent新增或異動資料時,我們可能想要對輸入的資料做預先的處理,

我們可以使用Laravel提供的魔術函式 setNameAttribute()去預先處理欄位資

料。

如果我們要預先處理文章模型(Article)的發布時間欄位(published_at),我們

的魔術函式就會是像:

classArticleextendsModel{

publicfunctionsetPublishedAtAttribute($date){

//將傳入的Y-m-d時間設為datetime格式的現在時間

$this->attributes['published_at']=Carbon::createFromFo

rmat('Y-m-d',$date);

//將傳入的Y-m-d時間設為datetime格式的凌晨零時00:00:00

$this->attributes['published_at']=Carbon::parse($date)

;

}

}

魔術函式 setNameAttribute()中,若遇到欄位名稱有底線的狀況,則將名

稱設為駝峰式大小寫(Camel-Case),像是 published_at則變成

PublishedAt

自定義query處理函式

假如我們要讀取發表的文章,但是發表的時間 published_at必須過去的時間,

設定於未來發表時間的文章不能被撈取出來,我們可以用這樣的方式去撈取:

魔術函式

37

Page 38: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//取得已經發表的文章,依照發表時間降冪(Desc)排序

$article=\App\Article::latest('published_at')

->where('published_at','<=',Carbon::now())

->get();

我們可以簡化這個query,把它寫在Model用函式的方式做處理,這樣我們就可以

用這樣去取得以發表的文章:

//取得已經發表的文章,依照發表時間降冪(Desc)排序

$article=\App\Article::latest('published_at')

->published()

->get();

而Model裡面我們用 scopeName魔術函式的方式去設定 published():

classArticleextendsModel{

publicfunctionscopePublished($query){

$query->where('published_at','<=',Carbon::now());

}

}

若我們想要取得尚未被發表的文章資訊,我們模式函式也可以設定成:

classArticleextendsModel{

publicfunctionscopeUnpublished($query){

$query->where('published_at','>',Carbon::now());

}

}

這樣我們就可以用 unpublished()去設定取得文章資訊了

魔術函式

38

Page 39: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//取得已經發表的文章,依照發表時間降冪(Desc)排序

$article=\App\Article::latest('published_at')

->unpublished()

->get();

這樣的優點是:

1. 簡化程式的長度

2. 讓我們在不同的地方不需要寫同樣落落長的查詢

3. 讓查詢的可讀性增加, published()與 unpublish()我們不需要看查詢

的語法條件就可以知道這個地方是要做什麼樣的查詢了

參考資料

Eloquent101-LaracastDates,Mutators,andScopes-LaracastEloquentORM-Laravel.tw

魔術函式

39

Page 40: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用Eloquent

新增資料

大量指定新增資料

//新增

\App\User::Create([

'first_name'=>'KeJyun',

'last_name'=>'Hong',

'email'=>'[email protected]',

]);

填入要新增的資料

//使用者的資料

$user_data=[

'first_name'=>'KeJyun',

'last_name'=>'Hong',

'email'=>'[email protected]',

];

$user=new\App\User;

//填入要新增的資料

$user->fill($user_info);

//儲存資料

$user->save();

使用Eloquent

40

Page 41: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

資料庫常見問題

這裏會列出一些Laravel5在處理資料庫會遇到的一些常見的問題

問題列表

無法取得查詢Log使用大量資料的方式新增時無法新增

使用中繼模型繼承Eloquent模型造成無法使用大量資料新增

常見問題

41

Page 42: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

資料庫常見問題:無法取得查詢Log在Laravel4為了要確定下的SQL語法有符合我們預期,我們常常在做完資料庫查

詢後,使用 DB::getQueryLog();去取得做資料庫查詢的QeuryLog,但因為

Laravel會把這些Log都記錄在記憶體中,如果做了大量的新增的查詢,記憶體會

使用過多可能會造成系統Crash。

所以Laravel5預設把記錄QueryLog的機制關閉,若需要做QueryDebug,需要

自行打開QeuryLog功能

<?php

//啟用QueryLog功能

DB::connection()->enableQueryLog();

這樣我們就可以使用 DB::getQueryLog();去取得做資料庫查詢的QeuryLog摟!!要得到執行過的查詢紀錄陣列,你可以使用getQueryLog方法:

<?php

//取得資料庫查詢的QeuryLog

$queries=DB::getQueryLog();

var_dump($queries);

參考資料

資料庫使用基礎查詢日誌記錄-Laravel.twHowtogetthequeryexecutedinLaravel5?DB::getQueryLogreturningemptyarray

無法取得查詢Log

42

Page 43: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用大量資料的方式新增(MassAssignment)時無法新增

在Laravel若沒有在模型(Model)中 同時設定「可以新增的欄位變數

$fillable」及「需要保護的欄位變數 $guarded」時,為了安全性著想,在

做大量的新增或異動資料時(MassAssignment),會無法正確的去新增或異動資

料。

設定「可以新增的欄位變數 $fillable」

設定你覺得允許做大量新增的欄位名稱

classUserextendsModel{

protected$fillable=['first_name','last_name','email'];

}

設定「需要保護的欄位變數 $guarded」

我們可以指定某些欄位,不能被使用大量新增或異動,去變更欄位的資料值

classUserextendsModel{

protected$guarded=['id','password'];

}

若我們想要讓模型(Model)可以被大量新增,且我們沒有需要保護的欄位時,我

們還是需要設定 $guarded變數為空陣列 [],否則Laravel預會保護所有的欄

位資料,讓你無法進行大量的新增或異動資料

使用大量資料的方式新增時無法新增

43

Page 44: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

classUserextendsModel{

protected$fillable=['id','password','first_name','last

_name','email'];

protected$guarded=[];

}

參考資料

EloquentORM新增、更新、刪除-Laravel.twLaravelEloquentSavetoDBUsingCreate-UnhelpfulErrorEloquentCreateMethod-Alwaysinsertsblankentries.UnabletocreateamodelwithEloquentcreatemethod.ErrortellingMassAssignMentException

使用大量資料的方式新增時無法新增

44

Page 45: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用中繼模型繼承(extends)Eloquent模型造成無法使用大量資料新增(MessAssignment)大部份的情況可能專案較小,所以我們會直接使用模型(Model)去新增資料,但

若專案較大時,且不同的模型之間有共用的方法的話,我會會希望這些模型繼承同

一個Eloquent模型的中繼類別物件,就像這樣:

Eloquent模型的中繼類別物件

classCustomBaseModelextendsModel

{

public$someVariable=null;

publicfunctiondoSomething()

{

}

}

使用者模型繼承「Eloquent模型的中繼類別物件」

classUserextendsCustomBaseModel{

protected$fillable=['first_name','last_name','email'];

}

使用這樣的中繼類別時,如果我們只有 設定變數或 實作中繼模型類別方法時,我

們可以運作的很正常,但是如果我們需要實作中繼類別的 建構子

__construct()時,我們必須要時做原本EloquentModel類別的建構子,否鑿會

無法正常的運作原有的Eloquent模型

vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php

Eloquent模型的檔案中,我們可以看到 建構子__construct()有需要傳入資料

使用中繼模型繼承Eloquent模型造成無法使用大量資料新增

45

Page 46: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

表欄位的屬性值 $attributes。

//vendor/laravel/framework/src/Illuminate/Database/Eloquent/Mod

el.php

abstractclassModelimplementsArrayAccess,Arrayable,Jsonable

,JsonSerializable,QueueableEntity,UrlRoutable{

publicfunction__construct(array$attributes=array())

{

$this->bootIfNotBooted();

$this->syncOriginal();

$this->fill($attributes);

}

}

這個部分是用來做大量資料新增或異動時(MassAssignment)需要用到的資料,

所以如果我們在中繼類別沒有實作這個 建構子__construct(),會讓我們的完整

EloquentModel出現問題

所以在Eloquent中繼類別中我們必須要時作的 建構子__construct()會長的像這

樣:

classCustomBaseModelextendsModel

{

public$someVariable=null;

function__construct(array$attributes=array())

{

parent::__construct($attributes);

//做中繼類別建構子想要做的事

$this->someVariable='5566';

}

}

使用中繼模型繼承Eloquent模型造成無法使用大量資料新增

46

Page 47: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

我們的中繼類別,需要傳入資料表欄位的屬性值 $attributes,並執行母類別

EloquentModel的建構子,這樣我們的Eloquent模型就能夠正常運作了!

使用中繼模型繼承Eloquent模型造成無法使用大量資料新增

47

Page 48: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

PostgreSQL這裏會介紹如何在Laravel使用PostgreSQL資料庫

PostgreSQL

48

Page 49: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝PostgreSQLODBCdriver環境:OSX日期:2015-03-29PHP:5.6

在我們在Laravel使用PostgreSQL去做Migration的時候,我們會看到像下面這

樣的錯誤訊息:

$phpartisanmigrate

[PDOException]

couldnotfinddriver

$

這表示我們沒有相關的連線驅動程式去連線到PostgreSQL,所以我們需要安裝我

們所需要的驅動程式

在OSX的PHP相關環境我是用brew去安裝的,如果你也是用brew去安裝,可

以先看看自己的套件是用哪一個版本的PHP

$brewlist

autoconfgitlibpngmhashphp56readli

nezlib

freetypeicu4clibtoolnvmphp56-mcryptunixod

bc

gettextjpegmcryptopensslpostgresqlwget

然後搜尋現在brew支援的PostgreSQL驅動程式

$brewsearchpgsql

osm2pgsqlphp54-pdo-pgsqlphp55-pdo-pgsqlphp56-pdo-pgsql

我們找到我們php5.6版本的驅動程式了,可以用下面的指令去安裝

$brewinstallphp56-pdo-pgsql

安裝PostgreSQLODBCdriver

49

Page 50: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝完成後就可以正常的使用Migration或相關的DB指令去存取PostgreSQL了~~!!

參考資料

Laravel:Error[PDOException]:CouldnotFindDriverinPostgreSQL

安裝PostgreSQLODBCdriver

50

Page 51: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

HTTP這裏會介紹如何在Laravel5處理HTTP請求

HTTP

51

Page 52: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

HTTP請求

這裏會介紹如何在Laravel5驗證HTTP請求的資料

建立新的請求驗證

如果我們有文章(Article)的模型,我們在每次請求過程中想要驗證傳入的資料,

我們可以使用系列指令建立要驗證的請求:

$phpartisanmake:requestCreateArticleRequest

請求驗證的檔案會被建立在 app\Http\Requests目錄下,建立的檔案內容如下

<?phpnamespaceApp\Http\Requests;

//app\Http\Requests\CreateArticleRequest.php

useApp\Http\Requests\Request;

classCreateArticleRequestextendsRequest{

/**

*Determineiftheuserisauthorizedtomakethisrequest.

*驗證使用者是否要登入狀態

*

*@returnbool

*/

publicfunctionauthorize()

{

returntrue;

}

/**

*Getthevalidationrulesthatapplytotherequest.

*驗證請求的資料規則

*

*@returnarray

請求

52

Page 53: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

*/

publicfunctionrules()

{

return[

//使用|設定驗證規則

'title'=>'required|min:3',

'body'=>'required|min:30',

//使用陣列設定驗證規則

'published_at'=>[

'required',

'date',

],

];

}

}

在驗證請求的CreateArticleRequest中的rules()函式,除了僅回傳驗證規則外,

你也可以判斷不同的狀況去加入不同的規則再回傳,像是:

請求

53

Page 54: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?phpnamespaceApp\Http\Requests;

//app\Http\Requests\CreateArticleRequest.php

useApp\Http\Requests\Request;

classCreateArticleRequestextendsRequest{

publicfunctionrules()

{

$rules=[

//使用|設定驗證規則

'title'=>'required|min:3',

'body'=>'required|min:30',

//使用陣列設定驗證規則

'published_at'=>[

'required',

'date',

],

];

//其他條件判斷

if($condition){

$rules['something_else']='required';

}

return$rules;

}

}

指定Controller函式處理指定的請求驗證

在我們使用Controller去處理請求時,我們可以再傳入變數內設定要怎麼處理請

求:

請求

54

Page 55: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

classArticleControllerextendsController{

//新增文章

publicfunctionstore(App\Http\Requests\CreateArticleRequest

$request)

{

Article::create(Request:all());

//OR

//Article::create($request->all());

returnredirect('articles');

}

}

這樣設定之後,所有的HTTP請求的Input資料都會經過

App\Http\Requests\CreateArticleRequest驗證,如果有經過驗證才會繼續

執行後面的新增文章動作,否則的話則會丟出驗證錯誤的物件到原頁面。

驗證錯誤訊息

這裏要注意到,視圖(View)的每一頁Laravel都會將驗證錯誤物件

(Illuminate\Support\ViewErrorBag)包成 $errors變數,所以你可以在每一頁

去印出 $errors值, $errors變數儲存的是任何資料驗證錯誤的結果

判斷是否有任何的錯誤並顯示錯誤訊息

//任一blade視圖(View)皆可以接收此錯誤變數

@if($errors->any())

//有錯誤訊息

<ul>

$foreach($errors->all()as$error)

<li>{{$error}}</li>

@endforeach

</ul>

@endif

請求

55

Page 56: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用Controller內建的validate驗證請求的資料

除了建立驗證Request物件,也可以直接使用Controller內建的validate去驗證請

如果不想要使用內建處理HttpResponseException的例外,你也可以自己trycatch並自己處理例外狀況

classArticleControllerextendsController{

//新增文章

publicfunctionstore(Requests$request)

{

try{

$this->validate($request,[

'title'=>'required|min:3',

'body'=>'required|min:30',

'published_at'=>'required|date',

]);

}catch(Exception$e){

//自己處理例外狀況

}

Article::create(Request:all());

//OR

//Article::create($request->all());

returnredirect('articles');

}

}

參考資料

FormRequestsandControllerValidation-Laracasts

請求

56

Page 57: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

請求

57

Page 58: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

路由(Route)這裡會介紹一些路由的相關技巧

路由(Route)

58

Page 59: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

子網域路由(Sub-DomainRoute)我們可能會因為有多個子網域,而我們希望各個不同的子網域有自己的路由設定,

像是我們希望各個子網域的首頁能夠藍道不同的頁面,這個時候我們可以透過子網

域路由去幫我們達成這樣的工作

加入您的子網域到hosts設定

如果是正式環境則不用做此設定,如果是測試環境也想要達到子網域路由的效果,

則必須做此設定

開啟 /etc/hosts檔案,並加入您需要的子網域

127.0.0.1resume.kejyun.dev

127.0.0.1book.kejyun.dev

Homestead加入此子網域的虛擬主機設定

sites:

-map:resume.kejyun.dev

to:/home/vagrant/Code/KeJyunProject/public

-map:book.kejyun.dev

to:/home/vagrant/Code/KeJyunProject/public

重新讀取Homestead設定

若設定檔有修改要重新讀取,則可以使用下列指令重新讀取設定

vagrantprovision

加入子網域路由

子網域路由

59

Page 60: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

在 route.php檔案中加入子網域路由

Route::group(['domain'=>'resume.kejyun.dev'],function()

{

Route::get('/',function(){

return'KeJyunResume';

});

});

Route::group(['domain'=>'book.kejyun.dev'],function()

{

Route::get('/',function(){

return'KeJyunBook';

});

});

這樣我們就可以在http://resume.kejyun.dev及http://book.kejyun.dev這兩個子網

域看到不同的首頁了!

參考資料

HomesteadandSubdomains

子網域路由

60

Page 61: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

中介層(Middleware)這裏會介紹如何在Laravel5使用中介層處理資料,Middleware在Laravel4叫做

Filter,他可以在處理資料之前,先過濾條件判斷,符合條件的再繼續處理之後的

Http請求。

就像實作一個部落格,使用者發表文章的時候,一定要登入,否則就會被導到登入

頁(或首頁),判斷登入條件的部分在Laravel5可以用中介層去實現。

檢視中介層類別

我們可以看看內建的驗證使用者是否有登入的Authenticate中介層

<?phpnamespaceApp\Http\Middleware;

//app\Http\Middleware\Authenticate.php

useClosure;

useIlluminate\Contracts\Auth\Guard;

classAuthenticate{

protected$auth;

/**

*Createanewfilterinstance.

*建立過濾器實例,建構時注入Guard類別並存到auth變數

*

*@paramGuard$auth

*@returnvoid

*/

publicfunction__construct(Guard$auth)

{

$this->auth=$auth;

}

/**

中介層(Middleware)

61

Page 62: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

*Handleanincomingrequest.

*處理request

*

*@param\Illuminate\Http\Request$request

*@param\Closure$next

*@returnmixed

*/

publicfunctionhandle($request,Closure$next)

{

if($this->auth->guest())

{

if($request->ajax())

{

returnresponse('Unauthorized.',401);

}

else

{

returnredirect()->guest('auth/login');

}

}

return$next($request);

}

}

有設定HttpRequest中介層時,所有的請求都會丟給中介層的 handle()函式做

處理,第一個變數傳入的是Request本身,第二個變數是若檢查驗證成功之後要執

行的函數,並把Request丟給下一層處理 $next($request)。

註冊中介層變數

中介層設定好之後,必須要到 app\Http\Kernel.php去註冊你的中介層

<?phpnamespaceApp\Http;

//app\Http\Kernel.php

中介層(Middleware)

62

Page 63: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

useIlluminate\Foundation\Http\KernelasHttpKernel;

classKernelextendsHttpKernel{

/**

*Theapplication'sglobalHTTPmiddlewarestack.

*全域中介層堆疊

*

*@vararray

*/

protected$middleware=[

'Illuminate\Foundation\Http\Middleware\CheckForMaintenan

ceMode',//檢查應用程式是不是維護中

'Illuminate\Cookie\Middleware\EncryptCookies',

//加密Cookies

'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse'

,//加入QueuedCookies到Response

'Illuminate\Session\Middleware\StartSession',

//開啟Session

'Illuminate\View\Middleware\ShareErrorsFromSession',

//從Session中共享錯誤資訊

'App\Http\Middleware\VerifyCsrfToken',

//驗證CSRFToken

];

/**

*Theapplication'sroutemiddleware.

*路由中介層

*

*@vararray

*/

protected$routeMiddleware=[

'auth'=>'App\Http\Middleware\Authenticate',

'auth.basic'=>'Illuminate\Auth\Middleware\Authenticate

WithBasicAuth',

'guest'=>'App\Http\Middleware\RedirectIfAuthenticated'

,

];

}

中介層(Middleware)

63

Page 64: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

在 app\Http\Kernel.php類別中, $middleware變數是設定全域中介層堆疊

清單,每一個HttpRequest都會依序經過 $middleware所有的中介層做判斷

$middleware中介層判斷完後都沒問題,才丟給路由中介層

$routeMiddleware做處理(若路由有設定要使用哪個中介層的話,沒有設定則

略過)。

當我們有自己的中介層,我們可以依自己需求看要將中介層設定加到哪一個變數設

定中,如果需要每一個Request都做檢查的話,則將中介層設定到

$middleware,否則設定在。 $routeMiddleware並指定中介層名稱即可。

在Controller使用中介層

我們可以強制設定,當使用者要存取文章的資源時都必須要登入,所以在

ArticleController控制器的建構子,我們可以用 $this->middleware('auth');設定全部ArticleController中的函式皆使用 auth中介層。

auth中介層名稱是參照 app\Http\Kernel.php中的

$routeMiddleware變數設定

classArticleControllerextendsController{

publicfunction__construct(){

$this->middleware('auth');

}

//新增文章

publicfunctionstore(Requests$request)

{

}

}

我們也可以使用 only方式,指定中介層只有在指定的函式中才使用,或是使用

except方式指定除了某些函式不使用中介層外,其他都要使用中介層當作過濾

中介層(Middleware)

64

Page 65: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//只有設定的函式使用中介層

$this->middleware('auth',['only'=>'create']);

//只有設定的函式"不要"使用中介層

$this->middleware('auth',['except'=>'index']);

在Route使用中介層

//app\Http\routes.php

Route::get('about',[

'middleware'=>'auth',

'uses'=>'HomeController@about'

]);

建立自己的中介層

我們可以使用指令建立自己的Middleware,假如我建立一個 KeJyunMiddleware為名稱的中介層,可以在命令列輸入:

$phpartisanmake:middlewareKeJyunMiddleware

建立的中介層會放在 app\Http\Middleware\KeJyunMiddleware.php中

中介層(Middleware)

65

Page 66: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?phpnamespaceApp\Http\Middleware;

//app\Http\Middleware\KeJyunMiddleware.php

useClosure;

classKeJyunMiddleware{

publicfunctionhandle($request,Closure$next)

{

return$next($request);

}

}

建立好自訂的中介層之後,到 app\Http\Kernel.php註冊中介層後即可使用

<?phpnamespaceApp\Http;

//app\Http\Kernel.php

classKernelextendsHttpKernel{

protected$routeMiddleware=[

'kejyun'=>'App\Http\Middleware\KeJyunMiddleware',

];

}

參考資料

OgresAreLikeMiddleware-Laracasts

中介層(Middleware)

66

Page 67: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

ETagMiddleware在我們的網站若資料未變更,我們會希望告訴請求資源的使用者,本資源未修改

(304NotModified),所以不用重複讀取資料,這樣可以節省我們傳輸資料頻寬

我可以用Middleware來達到ETag的效果

建立ETagMiddlewareApp\Http\Middleware\ETagMiddleware.php

ETagMiddleware

67

Page 68: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

namespaceApp\Http\Middleware;

useClosure;

classETagMiddleware{

/**

*ImplementEtagsupport

*

*@param\Illuminate\Http\Request$request

*@param\Closure$next

*@returnmixed

*/

publicfunctionhandle($request,Closure$next)

{

//Getresponse

$response=$next($request);

//如果是getrequest

if($request->isMethod('get')){

//產生回應內容的etag

$etag=md5($response->getContent());

$requestEtag=str_replace('"','',$request->getETa

gs());

//檢查etag是否變更

if($requestEtagAND($requestEtag[0]==$etagOR$re

questEtag[0]=='W/'.$etag)){

//若etag相同,設定表頭為資料未修改

$response->setNotModified();

}

//設定etag

$response->setEtag($etag);

}

//傳送回應

return$response;

}

}

ETagMiddleware

68

Page 69: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

設定EtagMiddlewareapp/Http/Kernel.php

<?php

namespaceApp\Http;

useIlluminate\Foundation\Http\KernelasHttpKernel;

classKernelextendsHttpKernel

{

protected$middlewareGroups=[

'web'=>[

\App\Http\Middleware\ETagMiddleware::class,

],

];

這樣我們就完成EtagMiddleware的設定了!

參考資料

SettingEtagsinLaravel5-MatthewDaly'sBlog

ETagMiddleware

69

Page 70: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

視圖

這裏會介紹如何在Laravel5處理視圖(View)

Laravel的視圖是放在 resource/views目錄內

建立共用的視圖

我們網頁常常會出現header跟footer在不同的視圖中為相同的狀況,唯一有變的

只有中間的內容隨著不同的請求而有變動,如果有這樣的設計需求,我們可以替所

有視圖建立共用的視圖,假設我們把這個共用的視圖放在

resource/view/app.blade.php下,其內容可能是:

<!--resource/view/app.blade.php-->

<!doctypehtml>

<htmllang="zh-TW">

<head>

<metacharset="UTF-8">

<title>我的網站</title>

</head>

<body>

<divclass="container">

@yield('content')

</div>

@yield('other_info')

</body>

</html>

如果我們要顯示文章的資訊在 content中,文章的說明在 other_info中,我

們可以在blade中這樣設定:

視圖(View)

70

Page 71: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<!--resource/view/article.blade.php-->

@extend('app')

@section('content')

<h1>文章標題</h1>

<p>

Loremipsumdolorsitamet,consecteturadipisicingelit

,seddoeiusmod

temporincididuntutlaboreetdoloremagnaaliqua.Ute

nimadminimveniam,

quisnostrudexercitationullamcolaborisnisiutaliqui

pexeacommodo

consequat.

</p>

@stop

@section('other_info')

其他資訊

@stop

這樣Laravel就會幫我們把相對應的資訊塞到 app.blade.php當中相對應的位置

引入共用的視圖

假如我們要在特定的某幾頁使用Facebook留言板,像是:

視圖(View)

71

Page 72: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<divid="fb-root"></div>

<script>(function(d,s,id){

varjs,fjs=d.getElementsByTagName(s)[0];

if(d.getElementById(id))return;

js=d.createElement(s);js.id=id;

js.src="//connect.facebook.net/zh_TW/sdk.js#xfbml=1&version=

v2.3&appId=12345566";

fjs.parentNode.insertBefore(js,fjs);

}(document,'script','facebook-jssdk'));</script>

<divclass="fb-comments"data-href="http://laravel5-book.kejyun.

com/"data-numposts="5"data-colorscheme="light"></div>

但我們不想要這些相同的程式碼片段散落在各個不同的視圖中,我們可以把它整理

在 resource/views/vendor/_fbcomment.blade.php當中

然後在文章視圖當中我們就可以這樣去引入Facebook留言板:

<!--resource/view/article.blade.php-->

@extend('app')

@section('content')

<h1>文章標題</h1>

<p>

Loremipsumdolorsitamet

</p>

@include('vendor/_fbcomment')

@include('vendor._fbcomment')

@stop

@section('other_info')

其他資訊

@stop

傳入變數到引用的視圖當中

視圖(View)

72

Page 73: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

在我們新增與編輯文章的視圖當中,幾乎所有的視圖都是一樣的,不一樣的地方可

能只有「表單處理的action不同(create&edit)」、「送出的按鈕文字不同(新

增違章&編輯文章)」

但我們還是希望兩個視圖能夠一起被引用,把其他不同的地方當作變數傳入,就可

以達到視圖重構的效果,避免類似的視圖重複出現在不同地方,像是:

<!--resource/view/partials/articles/_form.blade.php-->

{!!Form::label('title','標題')!!}

{!!Form::text('title',null)!!}

{!!Form::label('content','內文')!!}

{!!Form::text('content',null)!!}

{!!Form::submit($submitButtonText)!!}

當我們要引用表單的視圖,則必須把按鈕的文字傳送給表單,像是:

<!--resource/view/article.blade.php-->

@extend('app')

@section('content')

@include('partials/articles/_form',['submitButtonText'=>'新

增文章'])

@include('partials/articles/_form',['submitButtonText'=>'編

輯文章'])

@stop

@section('other_info')

其他資訊

@stop

備註

引用或載入視圖路徑

視圖(View)

73

Page 74: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

在使用blade中的 @extend()或 @include()函數,他所參照的視圖相對位置

是從 resource/views/開始的

所以如果你的視圖是放在 resource/views/partials/other.blade.php中,

你要引用或載入的話則可以用 .或 /去指定相對的視圖位置,像是:

<!--引用-->

@extend('partials._other')

@extend('partials/_other')

<!--載入-->

@include('partials._other')

@include('partials/_other')

設計模式

樣板檔案名稱

通常若不是完整的視圖,僅是部分的視圖,通常會將檔案名稱最前面加上底線

_,用來告知團隊程式設計師這個blade視圖不是完整的視圖

參考資訊

ViewPartialsandFormReuse-Laracasts

視圖(View)

74

Page 75: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

服務(Services)這裏介紹一些Laravel5提供的一些服務

服務

75

Page 76: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

認證登入(Auth)

設定

Laravel內建認證的設定檔案放在 config/auth.php中,預設會使用

App\User的類別當作驗證的Eloquent模型

[

'model'=>App\User::class,

]

如果我們用Model模型設計模式去設計我們的程式架構,我們User實體模型的程

式可能會放在 App\KeJyunApp\User\Entities\User.php中,這時候我們的認

證模型設定可以設定成像這樣(依照命名空間去設定):

[

'model'=>App\KeJyunApp\User\Entities\User::class,

]

這樣Laravel內建的認證就可以用我們指定的實體模型去進行認證了!!

手動登入認證

Laravel內建的認證使用Auth去進行身份認證,如果我們要用使用者的「email」及「密碼」做登入,我們的登入程式可能會像:

$email='[email protected]';

$password='1234';

if(Auth::attempt(['email'=>$email,'password'=>$password]))

{

//已登入成功!!!

}

認證登入(Auth)

76

Page 77: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用 Auth:attempt()的方式去驗證使用者時,Laravel會先到User資料表透過

Email抓取使用者的資料,產生出來的SQL會像:

SELECT*FROM"users"WHERE"email"='[email protected]'LIMIT1

;

抓取完使用者之料後再將password欄位用雜湊的 Hash::check()方式去比對驗

證密碼是否正確,再記錄使用者的SESSION資料

如果我們的使用者有限制啟用帳號的人才可以登入,所以我們要用使用者的

「email」、「密碼」及「啟用狀態」做登入,我們的登入程式可能會像:

$email='[email protected]';

$password='1234';

$status='active';

if(Auth::attempt(['email'=>$email,'password'=>$password,'

status'=>$status]))

{

//已登入成功!!!

}

產生出來的SQL會像:

SELECT*FROM"users"WHERE"email"='[email protected]'AND"st

atus"='active'LIMIT1;

Laravel一樣是先抓取使用者資料後,再做密碼驗證的動作!

使用記住我的方式登入

認證登入(Auth)

77

Page 78: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$email='[email protected]';

$password='1234';

$remember_me=true;

if(Auth::attempt(['email'=>$email,'password'=>$password],

$remember_me))

{

//已使用記住我登入成功!!!

}

如果你是自己建立自己User資料表的Migration,記得在自己的Migration中加入 $table->rememberToken();的設定,加入 remember_token欄位,

這個欄位可以讓Laravel使用 記住我的方式去記住使用者的sessiontoken

判斷使用者是否已登入

我們可以使用 Auth::check()的方式,判斷使用者是否已登入

if(Auth::check()){

//已登入

}

取得登入使用者的物件

$user=Auth::user();

//KeJyun

var_dump($user->name);

使用特定使用者的ID登入

$user_id='1';

Auth::loginUsingId($user_id);

認證登入(Auth)

78

Page 79: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

登出

Auth::logout();

參考資料

認證-Laravel.tw

認證登入(Auth)

79

Page 80: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

郵件

這裏會介紹Laravel5使用郵件寄信的相關說明

郵件(Mail)

80

Page 81: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用Gmail寄信

在測試機測試的時候,為了節省郵件服務的開銷,我們可以使用Gmail當作我們測

試的郵件服務,所以我們來介紹如何使用Gmail寄信

設定 config/mail.php

driver設為 smtp

host設為 smtp.gmail.com

port設為 587

username設為你要用來寄信的Gmail帳號 [email protected]

password設為Gmail帳號的密碼

pretend設為 true,這樣才可以正常使用Gmail寄送

設定完後會像這樣:

//config/mail.php

return[

'driver'=>'smtp',

'host'=>'smtp.gmail.com',

'port'=>587,

'from'=>['address'=>'[email protected]','name'=>'K

eJyun'],

'encryption'=>'tls',

'username'=>'[email protected]',

'password'=>'abcdefghijklmnopqrstuvwxyz123456',

'sendmail'=>'/usr/sbin/sendmail-bs',

'pretend'=>false,

];

測試使用Gmail寄信

使用Gmail寄信

81

Page 82: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Mail::raw('測試使用Laravel5的Gmail寄信服務',function($message)

{

$message->to('[email protected]');

});

這樣我們就可以使用Gmail去當作我們的郵件寄送服務了!!!

參考資料

AttemptingtogetEmailtoworkinLaravel5郵件-Laravel.tw

使用Gmail寄信

82

Page 83: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用Mailgun寄信

Mailgun對於初期的產品是一個不錯的郵件服務,每個月可以免費寄送10000封信,對於初期的應用應該是綽綽有餘,而且Laravel5預設有支援Mailgun的服

務,所以我們來介紹如何使用Mailgun寄信

設定 config/mail.php

driver設為 mailgun

host設為 smtp.mailgun.org

port設為 587

username設為 [email protected],這個帳號可以登入後

到Domains頁選擇你設定的Domains,找到 DefaultSMTPLogin就可以

看到這個帳號

password設為你自己的密碼,Mailgun顯次的欄位為 DefaultPassword,密碼長度為32碼

pretend設為 true,這樣才可以正常使用Mailgun寄送

設定完後會像這樣:

使用Mailgun寄信

83

Page 84: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//config/mail.php

return[

'driver'=>'mailgun',

'host'=>'smtp.mailgun.org',

'port'=>587,

'from'=>['address'=>'[email protected]','name'=>'K

eJyun'],

'encryption'=>'tls',

'username'=>'[email protected]',

'password'=>'abcdefghijklmnopqrstuvwxyz123456',

'sendmail'=>'/usr/sbin/sendmail-bs',

'pretend'=>false,

];

設定 config/services.php

domain設定為你自己定義的domain,若沒有自己定義domain的話,可以使

用Mailgun替你產生的domain,可以看看 DefaultSMTPLogin後面的

sandboxXXXXXX.mailgun.org,這個為Mailgun產生的domain

secret設為Mailgun提供的 APIKey,會長的像 key-abcdefghijklmnopqrstuvwxyz123456

設定完後會像這樣:

//config/services.php

[

'mailgun'=>[

'domain'=>'mailgun.kejyun.com',

'secret'=>'key-abcdefghijklmnopqrstuvwxyz123456',

],

]

測試使用Mailgun寄信

使用Mailgun寄信

84

Page 85: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Mail::raw('測試使用Laravel5的Mailgun寄信服務',function($messa

ge)

{

$message->to('[email protected]');

});

這樣我們就可以使用Mailgun去當作我們的郵件寄送服務了!!!

參考資料

MailgunSettingupMailgunwithLaravel5郵件-Laravel.tw

使用Mailgun寄信

85

Page 86: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

隊列(Queue)這裏會介紹一些Laravel5使用隊列(Queue)的方法

Laravel隊列的設定檔在 config/queue.php,在這裡你可以設定你想要用什麼

樣的隊列(Queue)服務去執行你的隊列,而Laravel預設有支援

database、Beanstalkd、IronMQ、AmazonSQS、Redis這幾種隊列的服務。

我們通常會將一些需要花比較久時間處理的工作丟給隊列去背景執行,讓使用者能

夠快速的的到網站的回應,像是我們在寄送帳號認證信件時,因為透過郵件伺服器

去寄送可能會花費比較久的時間,所以我們會將這類的工作丟到隊列去執行,所以

使用者的認證信件就會延遲的發送到他們的信箱,但是使用者在瀏覽網站時卻可以

有更好的體驗!

指令

在使用Queue去幫我們做工作的時候,我們在系統背景需要執行傾聽Queue是否

有工作的指令,像是 phpartisanqueue:listen,這樣Queue中有新工作需

要做,才能夠正常的去執行。

$phpartisanqueue:listen

執行Queue指令有一些相關的參數,可以依照自己的環境去調校

$phpartisanqueue:listen[--queue[="..."]][--delay[="..."]][-

-memory[="..."]][--timeout[="..."]][--sleep[="..."]][--tries[

="...”]]

隊列(Queue)

86

Page 87: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

參數 說明 指令

queue 設定優先執行的工作順序phpartisan

queue:listen--

queue=high,low

delay 在執行的工作發生錯誤時,要延遲多久重新執行(單位:秒),預設0秒

phpartisan

queue:listen--

delay=10

memory 執行工作最多能夠使用的記憶體上限(單位:MB),預設128MB

phpartisan

queue:listen--

memory=1024

timeout 執行的工作做長執行的時間是多長(單位:秒),預設60秒

phpartisan

queue:listen--

timeout=3600

sleep在沒有找到可以做的工作時,需要間隔多少秒再去檢查有無新的工作(單位:秒),預設3秒

phpartisan

queue:listen--

sleep=10

tries 工作執行失敗時,最多重新嘗試執行幾次(單位:次數),預設0,不重新嘗試

phpartisan

queue:listen--

tries=3

隊列(Queue)

87

Page 88: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

資料庫隊列(DatabaseQueue)我們可以使用 database的隊列設定,在自己的資料庫建立隊列資料表

產生隊列資料表

我們可以使用 phpartisanqueue:table指令去產生隊列的Migration

$phpartisanqueue:table

所以執行命令後,你可以找到像是

database/migrations/2015_05_26_225627_create_queue_jobs_table.php

這樣的隊列Migration檔案

Migration檔名日期 2015_05_26_225627每個人皆不同,會依照你建立當時

的時間去產生

產生的隊列Migration會長的像這樣:

database

88

Page 89: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useIlluminate\Database\Schema\Blueprint;

useIlluminate\Database\Migrations\Migration;

classCreateQueueJobsTableextendsMigration{

/**

*Runthemigrations.

*

*@returnvoid

*/

publicfunctionup()

{

Schema::create('jobs',function(Blueprint$table)

{

$table->bigIncrements('id');

$table->string('queue');

$table->text('payload');

$table->tinyInteger('attempts')->unsigned();

$table->tinyInteger('reserved')->unsigned();

$table->unsignedInteger('reserved_at')->nullable();

$table->unsignedInteger('available_at');

$table->unsignedInteger('created_at');

});

}

/**

*Reversethemigrations.

*

*@returnvoid

*/

publicfunctiondown()

{

Schema::drop('jobs');

}

}

database

89

Page 90: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

建立隊列資料表

執行 phpartisanmigrate將隊列資料表新增至資料庫

設定隊列驅動

在 config/queue.php檔案中設定資料庫隊列驅動設定,設定如下:

//config/queue.php

return[

'default'=>'database',

'connections'=>[

'database'=>[

'driver'=>'database',

'table'=>'jobs',

'queue'=>'default',

'expire'=>60,

'connection_name'=>'',

],

],

];

建立隊列工作

我們可以使用 \Queue::push('App\Commands\SendEmail@fire',$queue_data);的方法去新增要執行的隊列

第一個參數是執行隊列需要呼叫的類別名稱位置( App\Commands\SendEmail)

及方法( fire)

類別名稱需要正確的指定類別的命名空間(namespace),可以指定這個隊列要執

行的類別方法,只要將方法使用 @加在後方即可( @customMethod)

若沒有指定用哪個方法,Laravel預設會執行 fire的類別方法( @fire)

我們使用隊列來寄送Email,設定隊列的方式大概像這樣:

database

90

Page 91: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//需要傳送給隊列處理的資料

$queue_data=[

'email'=>'[email protected]',

'name'=>'KeJyun',

];

//建立隊列

$queue_id=\Queue::push('App\Commands\SendEmail@fire',$queue_d

ata);

在 App\Commands\Sendmail.php檔案大概會像這樣:

<?phpnamespaceApp\Commands;

classSendEmail{

/**

*執行隊列

*

*@returnvoid

*/

publicfunctionfire($job,$data)

{

//寄送Email

\Mail::send('emails.welcome',[],function($message)use

($data)

{

$message->to($data['email'],$data['name'])->subject(

'歡迎使用Laravel5資料庫隊列寄送Email!!!');

});

//執行成功,刪除隊列

$job->delete();

}

}

database

91

Page 92: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

fire方法中的 $job變數會接受該隊列的實例, $data變數會接收建立隊列

時傳入的資料

像我要使用隊列寄送Email,則會將使用者的相關資訊傳送到這個隊列來,讓隊列

能正確的發送正確的Email資訊給使用者!

在隊列執行完成無誤後,我們必須要使用 $job->delete();將隊列資料刪除,

若沒有刪除Laravel下次再出理到該資料時,則會視為隊列處理失敗,進而嘗試重

新處理

監聽隊列工作

我們會在shell中執行 phpartisanqueue:listen去持續的監聽隊列資料的狀

況,若有新增隊列到資料表時,Laravel則會開始處理隊列的資料

$phpartisanqueue:listen

這樣我們就可以正常的使用隊列去幫我們寄信摟!!

參考資料

隊列-Laravel.twQueuesinLaravelwithRedis

database

92

Page 93: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

非同步資料庫隊列(AsyncDatabaseQueue)在我們使用Laravel提供的資料庫隊列(DatabaseQueue)時,我們需要在命令列

執行 phpartisanqueue:listen指令,持續的去監聽是否有需要執行的

Queue。

barryvdh/laravel-async-queue隊列套件,可以讓我們不用持續的監聽隊列資料,

並在使用隊列時,立即的使用shell在背景執行隊列的工作。

目前(2015-06-01)套件0.4.x版本有支援Laravel5

安裝

$composerrequire'barryvdh/laravel-async-queue:0.4.*@dev'

加入ServiceProvider在 config/app.php檔案中加入 'Barryvdh\Queue\AsyncServiceProvider'

//config/app.php

return[

'providers'=>[

'Barryvdh\Queue\AsyncServiceProvider',

]

];

產生隊列資料表

barryvdh/laravel-async-queue隊列套件使用原生的資料庫隊列資料表(DatabaseQueue)去時做的,所以我們可以使用 phpartisanqueue:table指令去產生

隊列的Migration

非同步(async)

93

Page 94: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$phpartisanqueue:table

所以執行命令後,你可以找到像是

database/migrations/2015_05_26_225627_create_queue_jobs_table.php

這樣的隊列Migration檔案

Migration檔名日期 2015_05_26_225627每個人皆不同,會依照你建立當時

的時間去產生

產生的隊列Migration會長的像這樣:

非同步(async)

94

Page 95: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useIlluminate\Database\Schema\Blueprint;

useIlluminate\Database\Migrations\Migration;

classCreateQueueJobsTableextendsMigration{

/**

*Runthemigrations.

*

*@returnvoid

*/

publicfunctionup()

{

Schema::create('jobs',function(Blueprint$table)

{

$table->bigIncrements('id');

$table->string('queue');

$table->text('payload');

$table->tinyInteger('attempts')->unsigned();

$table->tinyInteger('reserved')->unsigned();

$table->unsignedInteger('reserved_at')->nullable();

$table->unsignedInteger('available_at');

$table->unsignedInteger('created_at');

});

}

/**

*Reversethemigrations.

*

*@returnvoid

*/

publicfunctiondown()

{

Schema::drop('jobs');

}

}

非同步(async)

95

Page 96: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

建立隊列資料表

執行 phpartisanmigrate將隊列資料表新增至資料庫

設定隊列驅動

在 config/queue.php檔案中設定非同步資料庫隊列(AsyncDatabaseQueue)驅動設定,設定如下:

//config/queue.php

return[

'default'=>'async',

'connections'=>[

'async'=>[

'driver'=>'async',

'table'=>'jobs',

'queue'=>'default',

'expire'=>60,

'connection_name'=>'',

],

],

];

建立隊列工作

我們可以使用 \Queue::push('App\Commands\SendEmail@fire',$queue_data);的方法去新增要執行的隊列

第一個參數是執行隊列需要呼叫的類別名稱位置( App\Commands\SendEmail)

及方法( fire)

類別名稱需要正確的指定類別的命名空間(namespace),可以指定這個隊列要執

行的類別方法,只要將方法使用 @加在後方即可( @customMethod)

若沒有指定用哪個方法,Laravel預設會執行 fire的類別方法( @fire)

我們使用隊列來寄送Email,設定隊列的方式大概像這樣:

非同步(async)

96

Page 97: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//需要傳送給隊列處理的資料

$queue_data=[

'email'=>'[email protected]',

'name'=>'KeJyun',

];

//建立隊列

$queue_id=\Queue::push('App\Commands\SendEmail@fire',$queue_d

ata);

在 App\Commands\Sendmail.php檔案大概會像這樣:

<?phpnamespaceApp\Commands;

classSendEmail{

/**

*執行隊列

*

*@returnvoid

*/

publicfunctionfire($job,$data)

{

//寄送Email

\Mail::send('emails.welcome',[],function($message)use

($data)

{

$message->to($data['email'],$data['name'])->subject(

'歡迎使用Laravel5資料庫隊列寄送Email!!!');

});

}

}

這樣我們就可以正常的使用隊列去幫我們寄信摟!!

目前(2015-06-01)barryvdh/laravel-async-queue在執行完隊列時,無法直

接刪除隊列資料,待作者修復這個bug

非同步(async)

97

Page 98: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

參考資料

隊列-Laravel.twQueuesinLaravelwithRedisbarryvdh/laravel-async-queue-packagistLaravel5AsyncQueueDriver-Github

非同步(async)

98

Page 99: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

輔助方法(Helpers)這裏介紹一些Laravel5的一些輔助方法用法

輔助方法(Helpers)

99

Page 100: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

自定義輔助方法

Laravel中有提供許多的輔助方法(Helpers),但有時候我們會想要自訂自己的輔

助方法,我們可以這樣做

加入自定義引用的 Helpers.php檔案到/app/Support/Helpers/Helpers.php路徑下

<?php

///app/Support/Helpers/Helpers.php

//Helper檔案路徑

$helpers=[

'CustomHelper.php'

];

//載入Helper檔案

foreach($helpersas$helperFileName){

include__DIR__.'/'.$helperFileName;

}

以後若有其他的Helper需要加入,僅需要加到 Helpers.php檔案中的

$helpers變數當中即可

在 composer.json中自動載入加入該Helper.php

自定義輔助方法

100

Page 101: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

/*composer.json*/

{

"autoload":{

"classmap":[

"database"

],

"psr-4":{

"App\\":"app/"

},

"files":[

"app/Support/Helpers/helpers.php"

]

}

}

重新編譯 autoload.php

$composerdump-autoload

Generatingautoloadfiles

這樣我們就可以自動的載入我們自定義的Helper函式了!!

BestpracticesforcustomhelpersonLaravel5

自定義輔助方法

101

Page 102: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

單元測試

這裏會介紹一些在Laravel5做單元測試的一些技巧

參考資料

AddLaravelUnitTestsDirectlyFromChrome-LaravelNews

單元測試(UnitTest)

102

Page 103: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

POSTCSRF錯誤

當我們在使用Unittest做POST測試時,測試的程式可能像:

<?php

classUserTestextendsTestCase{

/**

*測試註冊

*/

publicfunctiontestSignup()

{

$parameters=[

'email'=>'[email protected]',

'name'=>'KeJyun'

];

//傳送參數

$response=$this->call('POST','/signup',$parameters);

$this->assertEquals(200,$response->getStatusCode());

}

}

在執行單元測試後,你會收到一個 TokenMismatchException的例外錯誤,這個

部分是MiddlewareVerifyCsrfToken的驗證錯誤

這是因為Laravel5在所有的 POST、 PUT、 DELETE的路由方法中,都會預設

加入CSRFToken的檢查,他會檢查POST過來的資料中 _token的資料值與

Session中的token是否相符,或是驗證標頭中的 X-CSRF-TOKEN是否相符。

所以在我們每一次做 POST、 PUT、 DELETE的請求時,我們都必須要將

CSRFToken帶入檢查,才能執行後面的程式動作,我們可以用這樣的方式帶入

CSRFToken:

PostCSRF錯誤

103

Page 104: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

classUserTestextendsTestCase{

/**

*測試註冊

*/

publicfunctiontestSignup()

{

//開啟Session

Session::start();

//參數加入CSRFtoken

$parameters=[

'_token'=>csrf_token(),

'email'=>'[email protected]',

'name'=>'KeJyun'

];

//傳送參數

$response=$this->call('POST','/signup',$parameters);

$this->assertEquals(200,$response->getStatusCode());

}

}

在使用 csrf_token()方法時,都必須要先使用 Session::start();將Session開啟,以紀錄當時的CSRFToken做驗證,並將 _token當作參數傳送

到 POST、 PUT、 DELETE的路由當中,就可以正常執行單元測試了!

參考資料

HTTP路由-Laravel.twTestingLaravel5RouteswithCSRFProtectionUsingPHPUnit

PostCSRF錯誤

104

Page 105: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

錯誤與日誌

這裏介紹Laravel5處理一些錯誤例外的狀況

錯誤與日誌

105

Page 106: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

在單元測試顯示例外(ShowExceptioninCLI)在Laravel5做單元測試時,使用trycatch丟出例外時,Laravel5會自動地將例外

的錯誤訊息處理成網頁的樣式呈現,這樣的好處是在網頁中做操作發生例外狀況

時,可以直接看到例外的錯誤訊息,但是在寫單元測試(Unittest)時,他只會將這

些錯誤先記錄在log檔案裡面( storage/log/laravel-yyyy-mm-dd.log),我

們要看到這些錯誤的狀況必須要再另開終端機去執行 phpartisantail去觀看

這些例外Log的狀況,這樣在做測試的時候是相當麻煩的。

在Laravel5中所有的例外(Exception)都會被丟到

app/Exceptions/Handler.php中的 render()去處理

<?php

//app/Exceptions/Handler.php

classHandlerextendsExceptionHandler{

/**

*RenderanexceptionintoanHTTPresponse.

*將例外錯誤轉為HTTP回應

*

*@param\Illuminate\Http\Request$request

*@param\Exception$e

*@return\Illuminate\Http\Response

*/

publicfunctionrender($request,Exception$e)

{

returnparent::render($request,$e);

}

}

我們如果需要在CLI就顯示例外錯誤訊息的話,必須修改 render()函式,而我

想要保有原本在網頁做除錯的彈性,所以我在環境變數 .env檔案中加入例外處

理(Exception)顯示的開關,當有設定開啟時,才直接顯示例外訊息。

在單元測試顯示例外

106

Page 107: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<!--.env-->

EXCEPTION_DISPLAY_SWITCH=true

.env設定好後,就將 render()函式修改為這樣

<?php

//app/Exceptions/Handler.php

classHandlerextendsExceptionHandler{

/**

*RenderanexceptionintoanHTTPresponse.

*將例外錯誤轉為HTTP回應

*

*@param\Illuminate\Http\Request$request

*@param\Exception$e

*@return\Illuminate\Http\Response

*/

publicfunctionrender($request,Exception$e)

{

//預設不直接顯示例外訊息

$exception_display_switch=env('EXCEPTION_DISPLAY_SWITC

H',false);

if($exception_display_switch){

throw$e;

}

returnparent::render($request,$e);

}

}

這樣設定完後,也保留原本系統處理例外狀況的彈性,也可以讓我在單元測試

(Unittest)中可以正常的去顯示例外訊息了!!

參考資料

在單元測試顯示例外

107

Page 108: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

錯誤與日誌-laravel.twhowdoIcreatecustomerrorpageinlaravel5Laravel5.0-CustomErrorPages

在單元測試顯示例外

108

Page 109: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

日誌記錄層級

在系統發生例外錯誤時,我們會希望紀錄當時的例外訊息,以便之後我我們好進行

除錯,而Log紀錄的訊息會依照日期被放到像 storage/logs/laravel-2015-06-06.log的地方

Log記錄在Laravel有七個級別:debug、info、notice、warning、error、critical和alert,紀錄的方式會像這樣:

Log::debug('===Log訊息===');

Log::info('===Log訊息===');

Log::notice('===Log訊息===');

Log::warning('===Log訊息===');

Log::error('===Log訊息===');

Log::critical('===Log訊息===');

Log::alert('===Log訊息===');

他們在Log檔紀錄的樣子會像:

[2015-06-0616:22:00]testing.DEBUG:===Log訊息===

[2015-06-0616:22:00]testing.INFO:===Log訊息===

[2015-06-0616:22:00]testing.NOTICE:===Log訊息===

[2015-06-0616:22:00]testing.WARNING:===Log訊息===

[2015-06-0616:22:00]testing.ERROR:===Log訊息===

[2015-06-0616:22:00]testing.CRITICAL:===Log訊息===

[2015-06-0616:22:00]testing.ALERT:===Log訊息===

我們透過不同的記錄層級,讓我們容易找到層級比較嚴重的Bug先進行修復

參考資料

錯誤與日誌-Laravel.tw

日誌記錄層級

109

Page 110: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

日誌巨集

前言

我們會用Laravel內建的Response去回應服務的訊息,我們可能會用的回應會像

這樣:

//建立JSON回應

returnResponse::json(['name'=>'KeJyun','Country'=>'Taiwan'

]);

returnresponse()->json(['name'=>'KeJyun','Country'=>'Taiwa

n']);

//建立JSONP回應

returnResponse::json(['name'=>'KeJyun','Country'=>'Taiwan'

])

->setCallback($request->input('callback'));

returnresponse()->json(['name'=>'KeJyun','Country'=>'Taiwa

n'])

->setCallback($request->input('callback'));

//建立檔案下載的回應

returnresponse()->download($pathToFile);

returnresponse()->download($pathToFile,$name,$headers);

returnresponse()->download($pathToFile)->deleteFileAfterSend(tr

ue);

在這樣的使用下,我們可以很容易的回應訊息給使用者,但是在伺服器發生程式例

外錯誤(Exception)時,我們可能也需要回應像是這樣的資料:

日誌巨集

110

Page 111: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

returnResponse::json(['status'=>'failure','error_code'=>'5

566']);

returnresponse()->json(['status'=>'failure','error_code'=>

'5566']);

在我們用Laravel做API給手機用的時候,更需要有這些錯誤狀態的資料,所以我

們沒辦法直接像網頁一樣跳出整個的錯誤debug畫面

但我們若想在API回應給手機這樣的錯誤資訊時,也能夠將例外錯誤記錄下來,以

便我們進行除錯,我們可以做一個Response的巨集,去處理紀錄我們的回應

建立服務提供者

我們在命令列輸入 phpartisanmake:providerResponseServiceProvider建立回應的服務提供者

$phpartisanmake:providerResponseServiceProvider

該服務提供者檔案會被建立在 app/Providers/ResponseServiceProvider.php中,命名空間為 App\Providers\ResponseServiceProvider

我們不一定要將服務提供者的檔案放到 app/Providers目錄中,我們可以

依照自己專案的需求,將他移動到像是 app/KeJyun/Providers目錄中,這

樣命名空間就會變成

App\KeJyun\Providers\ResponseServiceProvider,檔案放置的位置隨

自己專案需求而定,只要遵照PSR-4的規定去設定命名空間及檔案位置即可

我新增了一個名稱為jsonLog的Response巨集,該巨集會回應json資料,並依

照記錄層級紀錄我們傳給他的資訊,ResponseServiceProvider程式會像這樣

<?phpnamespaceApp\KeJyun\Providers;

//app/KeJyun/Providers/ResponseServiceProvider.php

useIlluminate\Support\ServiceProvider;

useResponse,Log;

classResponseServiceProviderextendsServiceProvider{

日誌巨集

111

Page 112: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

/**

*Bootstraptheapplicationservices.

*

*@returnvoid

*/

publicfunctionboot()

{

/**

*註冊Response記錄錯誤巨集

*

*@paramArray$response_data

回傳的json資料

*@paramArray|Object|String$log_data

紀錄的資料

*@paramString$log_level

紀錄資料的等級(預設為info)

*

*@returnResponse$response

回應的json資料

*

*@accesspublic

*@[email protected]

*@date2015-06-06

*/

Response::macro('jsonLog',function(

$response_data,

$log_data='NoDataBelog!!!',

$log_level='info'

){

//增加Log檔案錯訊息間距以便閱讀

Log::debug("\n\n\n\n\n");

Log::debug($response_data);

Log::debug("\n\n");

switch($log_level){

case'debug':

Log::debug($log_data);

break;

case'notice':

日誌巨集

112

Page 113: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Log::notice($log_data);

break;

case'warning':

Log::warning($log_data);

break;

case'error':

Log::error($log_data);

break;

case'critical':

Log::critical($log_data);

break;

case'alert':

Log::alert($log_data);

break;

case'info':

default:

Log::info($log_data);

break;

}

//增加Log檔案錯訊息間距以便閱讀

Log::debug("\n\n\n\n\n");

returnResponse::json($response_data);

});

}

/**

*Registertheapplicationservices.

*

*@returnvoid

*/

publicfunctionregister()

{

//

}

}

日誌巨集

113

Page 114: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

設定服務提供者

設定完自己的jsonLog紀錄巨集後,我們需要到 config/app.php設定這個

Response服務提供者,我的命名空間為

App\KeJyun\Providers\ResponseServiceProvider,所以設定會像這樣:

//config/app.php

'providers'=>[

//其他的服務提供者

'App\KeJyun\Providers\ResponseServiceProvider',

],

設定完之後,Laravel在啟動時就會自動載入該服務提供者了

使用自定的Response巨集jsonLog在我們撰寫商業邏輯時若發生無法預期的例外狀況,我們會想要紀錄該例外狀況的

資料,我們就可以這樣使用ResponsejsonLog巨集:

try{

//商業邏輯處理

}catch(Exception$exception){

$response_data=[

'status'=>'failure',

'error_code'=>5566,

];

returnresponse()->jsonLog($response_data,$exception,'aler

t');

}

這樣在系統發生預期之外的例外時,我們也有參考的資料可以幫我們進行除錯

了!!

參考資料

日誌巨集

114

Page 115: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

HTTP回應:回應巨集-Laravel.tw服務提供者-Laravel.tw

日誌巨集

115

Page 116: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

加密

使用情境

我們若需要在資料庫儲存一些敏感資料(像是信用卡的資料),但我們又為了避免

資料庫遭到入侵,而導致所有使用者相關的敏感資料全都被竊取,我們可以使用

Laravel提供的「加密與解密」演算法,將我們的敏感資料加密儲存到資料庫,待

我們讀取資料的時候,再將其資料解密出來處理。

設定

在Laravel做「加密與解密」演算法時,會使用 config/app.php中的key值去

當作加解密的salt,自己的應用需要設定自己的key值,若沒有設定的話被加密過

的值還是有可能被暴力破解出來,所以要記得去設定,而這個key值若變更了,雜

湊的驗證也不會相同喔~

使用

//加密

$original_data='需要加密的資料';

$encrypt_data=Crypt::encrypt($original_data);

//解密

$decrypted=Crypt::decrypt($encrypt_data);

備註

重複加密相同的資料得到的密文不會一樣,所以不要使用像md5的方式去比對密

文資料是否相同

使用md5比較密文

加密

116

Page 117: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$original_data='需要加密的資料';

//第1次使用md5加密的資料

$first_md5_hash_data=md5($original_data);

//第2次使用md5加密的資料

$second_md5_hash_data=md5($original_data);

//資料相同

//true

var_dump($first_md5_hash_data===$second_md5_hash_data);

使用加密演算法比較密文

$original_data='需要加密的資料';

//第1次使用加密演算法加密的資料

$first_encrypt_data=Crypt::encrypt($original_data);

//第2次使用加密演算法加密的資料

$second_encrypt_data=Crypt::encrypt($original_data);

//資料不相同

//false

var_dump($first_encrypt_data===$second_encrypt_data);

參考資料

加密-Laravel.tw

加密

117

Page 118: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

雜湊

使用情境

使用者輸入的密碼,通常我們將其加密再存到資料庫中,但這類的資料我們通常不

需要反解回來處理,所以我們不需要使用加密的演算法去加密資料

因為加密演算法需要完整的解回原先的資料,所以若資料越長密文也會越長,但雜

湊不需要解回原先的資料,只需要驗證原先的資料,經過再雜湊的檢查是相同的就

好(輸入的密碼雜湊驗證與原先存在資料庫的雜湊資料相同),所以雜湊的資料可

以有固定的長度,像是md5的雜湊資料長度固定為32,而Laravel提供的Hash雜湊演算法,資料長度固定為60。

設定

在Laravel做「雜湊」演算法時,會使用 config/app.php中的key值去當作雜

湊的salt,自己的應用需要設定自己的key值,若沒有設定的話被加密過的值還是

有可能被暴力破解出來,所以要記得去設定,而這個key值若變更了,雜湊的驗證

也不會相同喔~

使用

雜湊

//雜湊

$original_password='密碼明碼';

$hash_password=Hash::make($original_password);

驗證

雜湊

118

Page 119: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//雜湊

$original_password='密碼明碼';

$hash_password=Hash::make($original_password);

//驗證

$check_result=Hash::check($original_password,$hash_password);

//true

var_dump($check_result);

備註

重複雜湊相同的資料得到的密文不會一樣,所以不要使用像md5的方式去比對密

文資料是否相同

使用md5比較密文

$original_password='密碼明碼';

//第1次使用md5加密的資料

$first_md5_hash_password=md5($original_password);

//第2次使用md5加密的資料

$second_md5_hash_password=md5($original_password);

//資料相同

//true

var_dump($first_md5_encrypt_password===$second_md5_encrypt_pas

sword);

雖然每次雜湊的結果都不一樣,但你可以放心的將任何一次雜湊的資料存放到資料

庫中,因為雖然密文不同,但Laravel的雜湊演算法,還是可以比對出來是不是由

相同的資料去做雜湊的

使用雜湊演算法比較資料是否相同

雜湊

119

Page 120: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$original_password='密碼明碼';

//第1次使用雜湊演算法雜湊的資料

$first_hash_password=Hash::make($original_password);

//第2次使用雜湊演算法雜湊的資料

$second_hash_password=Hash::make($original_password);

//資料不相同

//false

var_dump($first_encrypt_password===$second_encrypt_password);

//驗證雜湊資料true

$first_check_result=Hash::check($original_password,$first_has

h_password);

$second_check_result=Hash::check($original_password,$second_h

ash_password);

參考資料

雜湊-Laravel.tw

雜湊

120

Page 121: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

任務排程

我們通常會把一些每小時、每6小時、每日、每週、每月等等之類固定時間要做的

工作丟到Linux系統的crontab中去執行,通常像是每日要統計昨天網站的活動資

訊做數據分析之類的工作,這類的工作通常會花費比較久的時間

在Linux設定排程工作

我們通常會在命令列用 $crontab-e的方式去編輯排程工作

$crontab-e

在用到crontab的時候,我們需要瞭解怎麼設定排程工作的執行時間,整個的

crontab的設定可能會像這樣:

#每天凌晨3點統計昨天的Pageview

03***/usr/bin/php/home/kejyun/laravel4/artisancronjob:sta

tisticYesterdayPageview

在前方可以看到有5個數字可以做設定,依序分別代表的意思為:

分鐘(0-59)小時(0-23)每個月第幾天(1-31)月份(1-12)每週的第幾天(0-6)

0:星期日

1:星期一

2:星期二

3:星期三

4:星期四

5:星期五

6:星期六

任務排程

121

Page 122: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

這5個參數之間用空白隔開,每個參數除了設定單一個數字,也可以用逗號(,)去隔

開設定相同單位的時間設定,像是:

#每天凌晨4點及16點寄送廣告信

04,16***/usr/bin/php/home/kejyun/laravel4/artisancronjob:

sendCommercialMail

這裏有一些相關的設定範例可以當作參考:

#每小時的第18分鐘執行

18****

#8點10分執行

108***

#8點的每分鐘執行一次(共執行60次)

*8***

#在每個禮拜二每小時的第18分鐘執行

18***2

#你也可以每隔一段時間去執行crontab

#如果我們每15分鐘要去執行,你可以用這樣的格式*/15

#這樣的意思是將分鐘數,切割成(除以)每15分鐘執行

*/15****

#每2小時執行

0*/2***

#每2小時又20分鐘執行

*/20*/2***

小提醒

系統的crontab運作方式是 每分鐘會到設定的crontab找看看有沒有符合現

在這個時間的排程工作,所以像是 *8***這樣的設定,因為沒有明確指

定分鐘,在8點每分鐘檢查的60次都符合條件,所以會執行60次,若僅要8點時執行一次,請明確設定要執行的分鐘條件,像是 08***

任務排程

122

Page 123: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用Laravel5.2Scheduling設定排程工作

因為Linux每分鐘都會去檢查當時是否有排程需要執行的工作,符合條件的時間就

會執行,Laravel利用這個特性,告訴排程每分鐘都要執行Laravel的schedule:run的指令

*****php/path/to/artisanschedule:run>>/dev/null2>&1

之後Laravel每分鐘就會執行 app/Console/Command/Kernal@schedule的程

式,Laravel會依照 schedule裡面的設定時間,執行符合條件的排程工作

排程範例

假如我們有一個排程每分鐘都會紀錄他執行的時間,程式碼會放在

app/Console/Command/TestLog.php,程式碼會像是:

任務排程

123

Page 124: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

namespaceApp\Console\Commands;

useIlluminate\Console\Command;

useFile;

classTestLogextendsCommand

{

//命令名稱

protected$signature='test:Log';

//說明文字

protected$description='[測試]Log檔案';

publicfunction__construct()

{

parent::__construct();

}

//Console執行的程式

publicfunctionhandle()

{

//檔案紀錄在storage/test.log

$log_file_path=storage_path('test.log');

//記錄當時的時間

$log_info=[

'date'=>date('Y-m-dH:i:s')

];

//記錄JSON字串

$log_info_json=json_encode($log_info)."\r\n";

//記錄Log

File::append($log_file_path,$log_info_json);

}

}

任務排程

124

Page 125: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

以上排程的命令是 phpartisantest:Log,執行之後就會記錄當時執行的時間

排程程式建立好之後,在 app/Console/Command/Kernal.php定義此排程的工

作,並設定每分鐘執行一次,程式碼會像是:

<?php

namespaceApp\Console;

useIlluminate\Console\Scheduling\Schedule;

useIlluminate\Foundation\Console\KernelasConsoleKernel;

classKernelextendsConsoleKernel

{

//定義應用程式的Artisan指令

protected$commands=[

\App\Console\Commands\TestLog::class,

];

//定義應用程式的排程

protectedfunctionschedule(Schedule$schedule)

{

//每分鐘執行Artisan命令test:Log

$schedule->command('test:Log')->everyMinute();

}

}

這樣你就可以在 storage/test.log每分鐘看到像這樣的紀錄,這樣就表示你的

排程設定成功了!!

任務排程

125

Page 126: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

{"date":"2016-01-1122:12:05"}

{"date":"2016-01-1122:13:05"}

{"date":"2016-01-1122:14:05"}

{"date":"2016-01-1122:15:05"}

{"date":"2016-01-1122:16:05"}

{"date":"2016-01-1122:17:07"}

{"date":"2016-01-1122:18:09"}

{"date":"2016-01-1122:19:05"}

你也可以使用其他Laravel提供的時間方法去定義要執行的時間

方法 說明

->cron(''); 自訂Cron排成時間

->everyMinute(); 每分鐘執行

->everyFiveMinutes(); 每5分鐘執行

->everyTenMinutes(); 每10分鐘執行

->everyThirtyMinutes(); 每30分鐘執行

->hourly(); 每小時執行

->daily(); 每天執行

->dailyAt('13:00'); 每天13:00執行

->twiceDaily(1,13); 每天1:00及13:00執行

->weekly(); 每週執行

->monthly(); 每月執行

->yearly(); 每年執行

->sundays() 每週日執行

->mondays() 每週一執行

->tuesdays() 每週二執行

->wednesdays() 每週三執行

->thursdays() 每週四執行

->fridays() 每週五執行

->saturdays() 每週六執行

->when(Closure) 每當符合條件就執行(returntrue)

任務排程

126

Page 127: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

避免重複執行排程

排程預設每次符合條件就要執行,但若我們執行一個需要跑很久的程式,在下一次

符合條件的時間若上一個同樣的工作還沒有執行完,我們就不執行的話,我們可以

用 ->withoutOverlapping()方法去避免排程程式重複執行,像是

$schedule->command('emails:send')->withoutOverlapping();

輸出執行結果

我們的在執行Artisan指令時,我們通常會在畫面上列印一些執行狀態,像是

$this->info('把我顯示在畫面上');,如果我們想要知道排程執行時,這些顯示

在畫面的文字記錄下來,我們可以用

方法 說明

->sendOutputTo($filePath);將結果輸出到檔案(複寫該檔案)

->appendOutputTo($filePath);將結果附加在檔案後面(不複寫檔案)

-

>emailOutputTo('[email protected]');將結果寄送到指定Email

將結果輸出到檔案(複寫該檔案)

$schedule->command('emails:send')

->daily()

->sendOutputTo($filePath);

將結果附加在檔案後面(不複寫檔案)

$schedule->command('emails:send')

->daily()

->appendOutputTo($filePath);

將結果寄送到指定Email

任務排程

127

Page 128: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$schedule->command('foo')

->daily()

->sendOutputTo($filePath)

->emailOutputTo('[email protected]');

排程觸發

我們可以在排程執行前後,分別使用 ->before()或 ->after()去執行排程其

他的工作

$schedule->command('emails:send')

->daily()

->before(function(){

//在排程執行前觸發

})

->after(function(){

//在排程執行完成後觸發

});

參考資料

crontab.guru-thecronscheduleexpressioneditorAvisualcrontabeditorTaskScheduling-Laravel5.2

任務排程

128

Page 129: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Elixir這裏會介紹Laravel5使用NPM套件Elixir管理資源的相關說明

使用需求

因為Laravel的Elixir是透過Node.js的套件,去將Laravel目錄結構下的資源做整

合的工具,所以我們需要安裝Node.js的相關套件,需要安裝的有下列:

NPM(NodePackageManager)NPMgulp套件

NPMlaravel-elixir套件

安裝NPMNPM是Node.js的套件管理工具,Node.js在0.6.3版本開始內建npm,你可以透

過安裝Node.js的方式去安裝NPM,或是透過NPM官方網站提供的安裝指令去安

裝NPM

$curl-Lhttps://www.npmjs.com/install.sh|sh

安裝完NPM後,我們就可以使用NPM去安裝相關的套件了!

安裝NPMgulp套件

gulp是Node.js的自動建構的工具,可以透過它整合並建立資源

我們要到我們Laravel專案的根目錄,然後執行 npminstallgulp去安裝gulp

kejyun@KeJyundeMBP:~/Code/KeJyunLaravel5Proj$npminstallgulp

所有NPM安裝的套件會在專案跟目錄下的 node_modules目錄下,注意!

這個目錄不應該在專案的版本控制當中~

Elixir

129

Page 130: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝NPMlaravel-elixir套件

一樣在我們Laravel專案的根目錄,然後執行 npminstalllaravel-elixir去安裝laravel-elixir

$npminstalllaravel-elixir

這些套件安裝完後,我們就可以開始使用Elixir的開發好處了!!

參考資料

Node.jsnpmNPM套件管理工具

gulp.js-thestreamingbuildsystemLaravelElixir-laravel.tw

Elixir

130

Page 131: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用Elixir合併CSS與JSLaravelCSS與JS相關的資源預設是放在 resources/assets/scss與resources/assets/js下,我們需要把我們的CSS與JS放在這個目錄下,才

可以使用Elixir去編譯我們的CSS與JS檔案

使用Elixir之前請先安裝完所需要的軟體,詳情請點這裡

使用Elixir合併CSS

撰寫CSSresources/assets/scss/a.css

.a{

color:green;

}

resources/assets/scss/b.css

.b{

color:blue;

}

合併CSS資源

在我們專案根目錄 gulpfile.js檔案中,我們撰寫 mix.styles(['a.css','b.css']);,告訴laravel-elixir將我們的CSS資源整合起來

使用Elixir合併CSS與JS

131

Page 132: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//gulpfile.js

//載入laravel-elixir套件

varelixir=require('laravel-elixir');

//使用laravel-elixir套件合併CSS

elixir(function(mix){

mix.styles(['a.css','b.css']);

});

執行gulp整合CSS在我們專案根目錄下執行gulp指令,使用laravel-elixir整合所有CSS資源,大概

會像這樣:

kejyun@KeJyundeMBP:~/Code/KeJyunLaravel5Proj$gulp

[22:33:04]Usinggulpfile~/Code/KeJyunLaravel5Proj/gulpfile.js

[22:33:04]Starting'default'...

[22:33:04]Starting'styles'...

[22:33:04]Merging:resources/assets/css/a.css,resources/assets

/css/b.css

[22:33:04]Finished'default'after89ms

[22:33:04]Finished'styles'after122ms

預設會將CSS檔案整合至 public/css/all.css檔案中,你在 all.css會看

到我們整合CSS檔案的結果,就像這樣

.a{

color:green;

}

.b{

color:blue;

}

/*#sourceMappingURL=all.css.map*/

使用Elixir合併CSS與JS

132

Page 133: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

我們也可以在 gulpfile.js檔案中指定我們要編譯檔案的名稱目錄是什麼,就

像下面我把CSS編譯的檔案名稱目錄指定為 public/css/kejyun.css,laravel-elixir就會將編譯的檔案設為您指定的名稱目錄

//gulpfile.js

//載入laravel-elixir套件

varelixir=require('laravel-elixir');

//使用laravel-elixir套件合併CSS

elixir(function(mix){

mix.styles(['a.css','b.css'],'public/css/kejyun.css');

});

使用Elixir合併JS

撰寫JSresources/assets/js/a.js

vara=1;

resources/assets/js/b.js

varb=2;

合併JS資源

在我們專案根目錄 gulpfile.js檔案中,我們撰寫 mix.scripts(['a.js','b.js']);,告訴laravel-elixir將我們的JS資源整合起來

使用Elixir合併CSS與JS

133

Page 134: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//gulpfile.js

//載入laravel-elixir套件

varelixir=require('laravel-elixir');

//使用laravel-elixir套件合併JS

elixir(function(mix){

mix.scripts(['a.js','b.js']);

});

執行gulp整合JS在我們專案根目錄下執行gulp指令,使用laravel-elixir整合所有CSS資源,大概

會像這樣:

kejyun@KeJyundeMBP:~/Code/KeJyunLaravel5Proj$gulp

[22:47:21]Usinggulpfile~/Code/KeJyunLaravel5Proj/gulpfile.js

[22:47:21]Starting'default'...

[22:47:21]Starting'scripts'...

[22:47:21]Merging:resources/assets/js/a.js,resources/assets/j

s/b.js

[22:47:21]Finished'default'after86ms

[22:47:21]Finished'scripts'after122ms

預設會將JS檔案整合至 public/js/all.js檔案中,你在 all.js會看到我

們整合JS檔案的結果,就像這樣

vara=1;

varb=2;

//#sourceMappingURL=all.js.map

我們也可以在 gulpfile.js檔案中指定我們要編譯檔案的名稱目錄是什麼,就

像下面我把JS編譯的檔案名稱目錄指定為 public/js/kejyun.js,laravel-elixir就會將編譯的檔案設為您指定的名稱目錄

使用Elixir合併CSS與JS

134

Page 135: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//gulpfile.js

//載入laravel-elixir套件

varelixir=require('laravel-elixir');

//使用laravel-elixir套件合併JS

elixir(function(mix){

mix.scripts(['a.js','b.js'],'public/js/kejyun.js');

});

使用Elixir同時合併CSS與JS檔案

我們可以透過 JavascriptMethodChaining的方式連續的指定我們要合併的

資源,這樣我們執行gulp時,就可以同時整合這些資源

//gulpfile.js

//載入laravel-elixir套件

varelixir=require('laravel-elixir');

//使用laravel-elixir套件合併資源

elixir(function(mix){

mix

.scripts(['a.js','b.js'],'public/js/kejyun.js')

.styles(['a.css','b.css'],'public/css/kejyun.css');

});

laravel-elixir還可以整合其他的資源,像是Less、SCSS、SASS、CoffeeScript...等等之類的資源,詳情請看LaravelElixir-laravel.tw的說明即可!

參考資料

ElixirImprovementsLaravelElixir-laravel.tw

使用Elixir合併CSS與JS

135

Page 136: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

設計模式

這裏會介紹一些Laravel5會用到的設計模式

設計模式

136

Page 137: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

服務容器(ServiceContainer)Laravel的服務容器就像IoC容器一樣,可以讓你很容易的反轉控制物件

假如我們沒有注入類別去進行反轉控制,則我們每次使用Mail類別去寄送郵件時都

要去new它,如果這個Mail類別在裡面是會被很頻繁的使用時,這樣會讓我們很

惱人。

//通知類別

classNotification{

//通知會員有新訊息

publicfunctionnoticeNewMessage(){

$mail=newMail();

$mail->send();

}

//通知會員有新文章

publicfunctionnoticeNewArticle(){

$mail=newMail();

$mail->send();

}

}

為了能夠讓通知類別 Notification能夠隨時取用 Mail類別,我們會希望將

此類別直接注入,讓通知類別可以直接去進行反轉控制。

在我們使用反轉控制(IoC)時,我們時常需要在建構子 __construct()或方法

function()中注入需要反轉控制的類別,讓被注入的類別可以直接控制其物

件,就像:

服務容器

137

Page 138: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//通知類別

classNotification{

public$mail;

publicfunction__construct(Mail$mail){

$this->mail=$mail;

}

//通知會員有新訊息

publicfunctionnoticeNewMessage(){

$this->mail->send();

}

//通知會員有新文章

publicfunctionnoticeNewArticle(){

$this->mail->send();

}

}

我們在通知類別 Notification建構子中注入 Mail類別給內部 mail變數,之後要使用此Mail類別時,就直接使用傳送信件 send()的功能即可。

我們也可以在個別的函式中分別注入需要反轉控制的類別,就像:

//通知類別

classNotification{

//通知會員有新訊息

publicfunctionnoticeNewMessage(Mail$mail){

$mail->send();

}

//通知會員有新文章

publicfunctionnoticeNewArticle(Mail$mail){

$mail->send();

}

}

服務容器

138

Page 139: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

但是在Laravel4要注入類別之前,必須先對類別名稱對app進行綁定,讓

Laravel4認得這個要注入的類別是什麼物件

App::bind('Mail',function($app)

{

returnnewSomeEmailService;

});

但是在Laravel5除了可以用這樣手動綁定類別的方式,也有提供強大的自動綁定

功能,你不需要在app內事先定義所有的類別,當Laravel5在app內找不到該類

別的時候,就會自動找所有引入(include)的類別中有沒有此類別,自動進行注入

綁定!

參考資料

TheServiceContainer-Laracast服務容器-Laravel.twIoC容器

DependencyInjectionwithLaravel’sIoC

服務容器

139

Page 140: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

PSR(phpstandardrecommendations)為了讓大家開發的套件,能夠更輕鬆地整合到自己的專案當中,在PHP社群中大

家一起定義了一些標準的程式碼撰寫規則

但是Laravel5.0.x版本之前,Laravel都沒有真正的遵照PSR的規範去撰寫程式

碼,直到Laravel5.1LTS版本時,Laravel終於將所有的程式碼遵照PSR-2及PSR-4的程式碼撰寫規則了,詳細的規則說明大家可以自己參考相關的說明文件。

而為了讓自己專案的開發也能夠遵照PSR規則,除了自己一個檔案一個檔案自己

修改外,也可以用PHPCodingStandardsFixer套件去幫我們 自動地將程式修改

成遵照PSR規則的程式!

PHPCodingStandardsFixer安裝使用教學

使用compser下載套件

使用composer將php-cs-fixer安裝到全域(global)目錄下

$composerglobalrequirefabpot/php-cs-fixer

設定composerbin目錄到環境變數中

我們必須要將我們家目錄下的全域 ~/.composer/vendor/bin目錄,設到環境變

數中,這樣我們在命令列就可以直接執行 ~/.composer/vendor/bin下面的可執

行檔案了

$exportPATH="$PATH:$HOME/.composer/vendor/bin"

我們可以直接在命令列下這樣的指令就可以了,但每次開啟新的Terminal視窗

時,都要再重新的設定一次這樣的環境變數,所以我們也可以把這個設定寫在

~/.bash_profile檔案中,這樣每次執行Terminal時,就會自動將

~/.composer/vendor/bin設到環境變數中了!

PSR

140

Page 141: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用php-cs-fixer修正PHP檔案

設定完成後,我們就可以使用 php-cs-fixerfix/path/to/project--level=psr2這樣的指令去修正我們專案目錄下的檔案了

一些php-cs-fixer相關的指令會像這樣:

$php-cs-fixerfix/path/to/project--level=psr0

$php-cs-fixerfix/path/to/project--level=psr1

$php-cs-fixerfix/path/to/project--level=psr2

$php-cs-fixerfix/path/to/project--level=symfony

設定Sublime使用php-cs-fixer修正程式碼

在Sublime上方工具列 Tools\BulidSystem\NewBuildSystem我們可以新

增一個新的建立指令,指令中我們輸入像這樣的指令:

{

"shell_cmd":"php-cs-fixerfix$file--level=psr2"

}

將新的指令檔案名稱取為 php-cs-fixer.sublime-bulid,這樣我們回到

Sublime去開啟任一PHP檔案,只要按下 Command(⌘)+ B,Sublime就會自

動幫我們執行php-cs-fixer的shellscript指令,去修正我們的PHP檔案了!!

php-cs-fixer使用小技巧

我們可以將修改 ~/.bash_profile檔案,將使用php-cs-fixer修正Terminal目前目錄的PHP指令加入,這樣我們只要用Terminal瀏覽到我們想要做php-cs-fixer的目錄下,我們每次只需要下 phpCSFixerThisFolder指令就可以了,這

樣就不用記住也不用打那麼落落長的php-cs-fixer指令了!

aliasphpCSFixerThisFolder="php-cs-fixerfix./--level=psr2"

PSR中文文件

PSR

141

Page 143: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Model模型設計模式

我們在使用任何的Framework中,都會聽到MVC模型,V(View)是負責畫面顯

示,C(Controller)是負責控制程式呼叫模型的邏輯,而最重要的M(Model)是

負責整個資料庫的操作,以及撈取資料的邏輯

我們常常把模型用來作為處理資料的商業邏輯,不管是任何的「資料樣式的轉

換」、「資料撈取的邏輯」、「資料格式的驗證」、「資料處理的順序及商業邏

輯」...等等都是放在模型(Model)去處理

資料樣式的轉換

//2016-01-0100:00:00.123789

$now=Carbon::now();

//2016/01/01

$now_date=$now->format('Y/m/d');

資料撈取的邏輯

撈取所有的女會員資料,年紀小於30歲

User::where('gender'=>'female')

->where('age','<',30)

->get();

撈取所有的男會員資料,年紀大於30歲

User::where('gender'=>'male')

->where('age','>',30)

->get();

資料格式的驗證

Model模型

143

Page 144: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$validator=Validator::make(Request::all(),[

'title'=>'required|unique:posts|max:255',

'content'=>'required',

]);

資料處理的順序及商業邏輯

/**

*發送Email及簡訊給所有女會員

*/

//取得所有女會員資料

$users=User::where('gender'=>'female')

->get();

//發送Email

foreach($usersas$u){

Mail::send('emails.hello',['user'=>$u],function($mail)use

($u){

$mail->to($u->email,$u->name)

->subject('安安!');

});

}

//發送簡訊

foreach($usersas$u){

SMS::send('sms.hello',['user'=>$u],function($sms)use($u)

{

$sms->to($u->mobile_phone,$u->name)

->content('安安!');

});

}

如果把這些不同類別的資料全部丟到Model模型去處理會變得很亂,程式碼難以維

護,所以我們會用設計模式來降低程式碼的耦合性,讓程式變得容易維護,我們會

將Model分成:

實體(Entity)

Model模型

144

Page 145: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

資源庫(Repository)服務(Service)表單驗證(Form)

資料呈現(Presenter)ARCA架構檔案結構

實體(Entity)實體就是我們用來設定EloquentModel的相關設定,像是資料表名稱($table)、

主鍵名稱($primaryKey)等等,裡面除了Eloquent相關設定以外,不要擺任何的

商業邏輯或資料撈取方法

實體與資料表的關係是「1對1」的關係,有幾個資料表就有幾個實體

詳情請見EloquentModel(模型)-設定

資源庫(Repository)資源庫是我們要用來撈取資料表資料的各個邏輯,我們資料表會有不同的欄位,不

同的欄位條件代表不同的意義,像是:

撈取所有的女會員資料,年紀小於30歲

User::where('gender'=>'female')

->where('age','<',30)

->get();

撈取所有的男會員資料,年紀大於30歲

User::where('gender'=>'male')

->where('age','>',30)

->get();

這些不同的撈取資料邏輯,我會將它包在資源庫中,該資源庫長得會像這樣:

Model模型

145

Page 146: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

classUserRepository{

/**

*撈取所有的女會員資料,年紀小於30歲

*/

publicfunctiongetYoungFemale()

{

returnUser::where('gender'=>'female')

->where('age','<',30)

->get();

}

/**

*撈取所有的男會員資料,年紀大於30歲

*/

publicfunctiongetOldMale()

{

returnUser::where('gender'=>'male')

->where('age','>',30)

->get();

}

}

這樣我們撈取這些不同資料邏輯時就可以這樣去撈取:

$userRepository=newUserRepository();

//撈取所有的女會員資料,年紀小於30歲

$young_female_user=$userRepository->getYoungFemale();

//撈取所有的男會員資料,年紀大於30歲

$old_male_user=$userRepository->getOldMale();

這樣除了可以讓程式碼易讀性提高之外,撈取資料的邏輯也可以抽離出來,下次如

果有需要撈取同樣的資料時,就可以重複的去使用它,而且不會有重複的程式碼出

現在專案的各個地方,讓管理程式碼變得簡單

資源庫與實體的關係是「1對1」的關係,有幾個實體就有幾個資源庫,每個資源

庫是代表那個實體的各個不同的資料撈取邏輯

Model模型

146

Page 147: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

服務(Service)服務代表我們程式要處理資料的商業邏輯,我會將各個功能邏輯獨立成一個服務,

像是使用者「註冊身份驗證」是一個服務,而使用者「個人隱私設定」也是一個服

服務與資源庫的關係是「多對1」的關係,像是同樣使用者資料,有「註冊身份驗

證」及「個人隱私設定」2種不同類型的服務

使用者「註冊身份驗證」服務

/**

*使用者「註冊身份驗證」服務

*/

classUserAuthService

{

/**

*註冊

*/

publicfunctionsignup()

{

}

/**

*登入驗證

*/

publicfunctionsignin()

{

}

}

使用者「個人隱私設定」服務

Model模型

147

Page 148: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

/**

*使用者「個人隱私設定」服務

*/

classUserPrivacyServiceextendsAnotherClass

{

/**

*取得使用者隱私設定

*/

publicfunctiongetUserPrivacy()

{

}

/**

*設定使用者隱私

*/

publicfunctionsetUserPrivacy()

{

}

}

不同類型的服務,只要彼此耦合性很低,我傾向把他分成不同的服務去處理,這樣

可以很清楚的知道哪個個服務是專門處理哪一種商業邏輯,程式也比較好管理,在

異動程式時也比較不會影響到彼此,避免牽一髮動全身的狀況發生

表單驗證(Form)

我們設計後端程式的原則,是不要相信任何第三方傳來的資料,在資料做進一步處

理時都需要對資料格式做檢查,若於我們設定的資料格式相符,我們才會去做進一

步的資料商業邏輯處理

但是我們可能會在控制器(Controller)做表單資料的驗證,但是服務

(Service)、資源庫(Repository)或實體(Entity)為了保護自己的程式邏輯,

也有可能去做表單資料的驗證,若每一個階段都做表單資料的驗證,這樣不僅造成

Model模型

148

Page 149: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

了資料發生重複驗證的狀況,也會降低程式的執行速度,更慘的是會造成驗證程式

重複出現,如果有驗證規則要修改,我們就必須要確保所有有驗證表單資料的地

方,都有正確的被修改,不然程式的商業邏輯可能會沒辦法順利的去執行。

因為我們對模型做了分層地處理,所以模型的層級架構會像:

控制器(Controller)>服務(Service)>資源庫(Repository)>實體

(Entity)

控制器會根據他需要的商業邏輯,呼叫不同的服務來處理他的程式邏輯,而且每個

控制器,而且每個控制器可能會有不同類型的服務,可能會有使用者(User)的資

料、文章(Posts)的資料...等等需要做資料的驗證,所以驗證資料的規則複雜度會

很多。

我自己會傾向將所有的表單資料驗證都放在服務(Service)中去驗證,不同的商業

邏輯可能需要驗證的資料規則不同,但是我們可以確定的是,同一個服務會是同一

個類型的資料,像是使用者「註冊身份驗證」服務及使用者「個人隱私設定」服務

<裡面的資料一定是使用者相關的資料,若我們也有文章的服務(PostService),

我們也一定可以確保裡面的驗證資料一定是文章相關的資料。

所以除了服務(Service)層去做資料的驗證外,其他的層級都不需要做任何的資料

驗證!

資料呈現(Presenter)我們會將需要處理不同資料樣式的邏輯,使用laracasts/presenter去做實體

(Entity)的分層處理,不要將有程式邏輯的功能出現在實體(Entity)中

ARCA架構檔案結構

我會將Model的檔案結構依照Domain去區分,檔案結構大概會像這樣

Model模型

149

Page 150: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

/app

/KeJyunApp

/User

/Entities

User.php

UserPrivacy.php

/Repositories

UserRepository.php

UserPrivacyRepository.php

/Service

UserAuthService.php

UserPrivacyService.php

/Form

UserForm.php

UserPrivacyForm.php

/Presenter

UserPresenter.php

UserPrivacyPresenter.php

/Post

/Entities

Post.php

/Repositories

/Service

/Form

/Presenter

這樣區分的好處是,類似功能的程式可以方便集中管理,當我們在撰寫某一功能的

程式,我們可以很快地在同一個資料夾中找到這些檔案,若要找其他功能的程式

時,也可以在同一個資料夾很快地去找到

如果我們將程式檔案依照功能去放置,可能會像這樣

Model模型

150

Page 151: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

/app

/SomeApp

/Entities

User.php

Post.php

Tags.php

News.php

Event.php

...

/Repositories

/Service

UserAuthService.php

UserPrivacyService.php

UserStatisticService.php

PostManageService.php

PostRankService.php

PostStatisticService.php

TagsService.php

NewsService.php

EventService.php

...

/Form

/Presenter

當專案還小,只有少數幾個模型資料需要管理時,還沒有什麼大的問題,但是當我

們撰寫很多複雜功能時,這樣檔案管理的方式會是個很大的夢靨,像是服務

(Service)與資源庫(Repository)的關係是「多對1」的關係,所以服務

(Services)資料夾的檔案可能有40~50個以上,在我們要找相關的檔案時,就很

考驗我們的眼力了(工程師的眼睛是很珍貴的,我們要好好的珍惜~)

參考資料

在Laravel4使用資源庫(Repositories)及服務(Services)去降低程式的耦合

胖胖Model減重的五個方法byhowtomakeaturnPHP也有Day#16-胖胖Model減重的五個方法by尤川豪

Model模型

151

Page 152: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Model模型

152

Page 153: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

架構設計準則

傳統的MVC(Model,View,Controller)框架,當Controller收到請求之後,我們

會在Controller內直接透過Model去撈取資料庫的資料,並在Controller做資料驗

證、整合、快取、商業邏輯判斷...等等的工作。

當系統越來越大,會發現很多類似的商業邏輯的程式都散在各地,沒有辦法重複再

利用,當程式需要異動或修改的時候,就要去搜尋所有程式碼,把許多相同商業邏

輯的程式碼去做異動,但需要修改的地方若太多,往往會東漏西漏,導致系統出現

錯誤,並造成往後開發的時間成本增加。

所以我們會想要做到 減少重複的程式碼、 提高維護開發的效率,所以將程式碼依

照 分類及 分層抽出獨立控管,讓不同類型的程式專心處理自己相關的商業邏

輯,讓開發維護更容易。

隨著程式架構的演進會發展出更多不同的架構,所以這個設計架構準則也是會隨著

時間做演進的。

資料層級需求分析

Service(服務)

我們原本在Controller處理請求時,會針對使用者的請求,做不同商業邏輯的處

理,而同樣的商業邏輯可能會被不同的Controller存取,為了讓同個商業邏輯程式

能夠重複使用,所以我會分出一層 Service(服務),將這些商業邏輯放在裡

面,供不同的Controller存取。

在 Service方法中,會針對目前商業邏輯的資料進行蒐集與彙整,處理過後再回

傳給 Controller

Repository(資源庫)

在不同 Service可能會需要對資料庫撈取同樣的資料,為了避免撈取資料的邏輯

重複出現在不同的地方,我們會分出一層 Repository(資源庫),將同樣撈取

Model(模型)資料的邏輯都寫在一起,供不同的 Service存取。

架構設計準則

153

Page 154: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

在 Repository中,會在function名稱中指出這個方法是要撈什麼樣的資料,這

樣方法可以重用,也可以讓程式有可讀性,不需要再去看 Modelsql條件的邏

輯,判斷是在做什麼樣的處理

e.g.PostRepository->getWeekTopPosts();//取得本週熱門文章

Model(模型)

在Model中我們僅會寫對資料表對Eloquent相關的設定,像是 primaryKey(主鍵名稱)或 table(資料表名稱),讓Model能夠越乾淨越好,將一些撈取資料的

邏輯都往 Repository集中整理。

Presenter(資料呈現)

在Model我們有一些資料可能會想要有不同的呈現方式,像是文章發布時間

created_at我們可能會想要呈現出像是 5秒前、 15分鐘前、 6小時前這樣的資料,這些資料因為是隨著時間不同而去動態變化,所以需要用程式去計算與

created_at的時間差,再去看要如何呈現這筆資料。

為了能夠讓這些不同資料呈現方式的邏輯能夠重複使用,且不污染 Model的程

式,所以我會分出一層 Presenter(資料呈現)去輔助 Model資料的呈現

e.g.Post->presenter()->created_at_human_time;

laracasts/Presenter

Cache(快取)

在使用 Repositoy去對 Model做存取得時候,如果我們資料沒有做異動,我

們會將資料存放在快取中,直接讀取快取的資料,而減少對資料庫的存取,提高資

料的存取效率

而我們需要對 資料快取的設定、清除及 快取鍵值去做管理,快取像是協助

Repository做資料的存取,所以我會分出一層 Cache(快取)去輔助

Repository做快取的處理

Validator(驗證器)

為了讓資料驗證方法能夠重複使用,不需要在不同的Controller去驗證相同的東

西,這樣會造成驗證邏輯重複出現,若有需要異動驗證規則時,會難以維護。

架構設計準則

154

Page 155: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

而每個商業邏輯需要驗證的資料不同,有些欄位在不同商業邏輯會有必填與非必填

不同的差異,像是在做使用者身份驗證時,若有Email驗證及手機驗證,在Email驗證時,手機欄位為非必填欄位,在做手機驗證時,Email為非必填欄位,但兩者

皆為使用者的資料,無法強制使用者兩個欄位資料皆為必填,但在某些商業頁邏輯

是必要的,所以我沒有選擇將這些驗證的邏輯寫在 Repository或 Model中。

所以我會分出一層 Validator(驗證器)輔助 Service做資料驗證。

Concrete(服務組合)

我們會在 Controller去呼叫各個不同的 Service去做資料的判斷處理,有時

候不同的 Controller會有相同呼叫 Service的邏輯順序及組合的資料,為了

減少重複程式,所以我會分出一層 Concrete(服務組合)去協助 Controller去做不同 Service資料的整合撈取

像是我們在許多 Controller方法中,我們都要使用 $PostService->find($post_id);去找文章資料,並用 $UserService->find($post_user_id);去找文章作者相關資訊,這些在 Controller重複出

現的呼叫 Service邏輯我們就可以寫在 Concrete中去做呼叫

Constant(常數)

我們在做 Model資料的撈取或是條件判斷時,可能會需要用

Post::where('status',1)->get()或 $Post->status==1去做資料的存

取,但像 status為1這種資料對我們是難以做閱讀的,需要知道1代表是什

麼意思才知道此段程式的邏輯。

所以我會分出一層 Constant(常數)輔助做資料的識別,我會將狀態設為可識別

的靜態變數,像是 PostConstant::STATUS_PUBLISH=1;,所以在做程式判斷

時,可以用 Post::where('status',PostConstant::STATUS_PUBLISH)->get()或 $Post->status==PostConstant::STATUS_PUBLISH去做判斷。

在 Constant的變數皆為 靜態變數,所以可以供任何類別去做存取。

Support(支援)

我可能會對一資源的資料做簡單的邏輯判斷,不需要依賴任何的 資料控制結構,

像是 Service、 Repository或 Model,所以我會分出一層 Support(常數)去做共用的輔助方法。

架構設計準則

155

Page 156: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

像是我們可以用 PostSupport::getAllPostStatus()去撈取文章的所有狀態,

或者用 GoogleAnalyticSupport::api()去對GA的API做存取。

在 Support的方法皆為 靜態方法,所以可以供任何類別去做存取。

ExceptionCode(例外代碼)

我們在做API的資料存取時,會針對不同的例外狀況回傳不同的 錯誤代碼

(error_code),而同一個錯誤代碼可能在不同的 Controller或 Service被回傳,像是文章找不到我們會回傳錯誤代碼 10000001,為了管理及閱讀性方

便,我會分出一層 ExceptionCode(例外代碼)去做共用的例外代碼管理。

像是找不到文章的代碼我會設為 PostExceptionCode::POST_NOT_FOUND=10000001;,所以在程式中只要看到 PostExceptionCode::POST_NOT_FOUND就可以馬上知道這個是找不到文章的錯誤代碼。

在 ExceptionCode的變數皆為 靜態變數,所以可以供任何類別去做存取。

資料層級結構

資料控制結構

Controller(控制器)Concrete(服務組合)

Service(服務)Repository(資源庫)

Model(模型)Presenter(資料呈現)

Cache(快取)Validator(驗證器)

獨立結構

Constant(常數)Support(支援)ExceptionCode(例外代碼)

架構設計準則

156

Page 157: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

架構圖

結構說明

資料控制結構

架構設計準則

157

Page 158: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

結構名稱 說明

Controller(控制器)

控制要使用哪些Service或Concrete的商業邏輯,去組合出使用者請求需要的資料,並做資料的資料交易控制(transaction)

Service(服務)

做資料的驗證,並組合不同的Repository資料成商業邏輯,供Controller或Concrete存取

Repository(資源庫)

撈取屬於自己Model不同條件下的資料,並做快取控制,供Service存取

Model(模型) 資料表存取相關設定

Presenter(資料呈現) 協助Model做資料呈現處理

Cache(快取) 協助Repository做快取資料的控制

Validator(驗證器) 協助Service做資料驗證

Concrete(服務組合) 協助Controller組合不同Service的資料成商業邏輯

獨立結構

結構名稱 說明

Constant(常數) 共用變數名稱設定

Support(支援) 共用方法

ExceptionCode(例外代碼) 共用例外代碼設定

架構使用原則

資料控制結構

存取限制

不能跨2階層以上存取

Controller不能存取RepositoryService不能存取Model

架構設計準則

158

Page 159: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

低階層的不能存取高階層的資料

Model不能存取RepositoryRepository不能存取Service

同一個資料類型,不能互相呼叫

避免同一類型類別呼叫,造成new物件的時候有無窮迴圈

PostService存取UserService,UserService存取PostsService造成無窮迴圈

Concrete不能呼叫ConcreteService不能呼叫ServiceValidator不能呼叫ValidatorRepository不能呼叫RepositoryCache不能呼叫Cache

結構名稱 可存取 可被存取

Controller(控制器) Concrete、Service、DBtrancsction -

Concrete(服務組合) Service Controller

Service(服務) Repository、Validator Controller、Concrete

Validator(驗證器) - Service

Repository(資源庫) 自己的Model、自己的Cache Service

Cache(服務) - Repository

Model(模型) 自己的Presenter Repository

Presenter(資料呈現) - Model

View(視圖)使用限制

View的職責是負責顯示資料,所有的資料應由 Controller準備好再傳給

View,所以 不要在 View內有複雜的程式判斷邏輯,在 View裡面只有

if, for, foreach跟 echo列印的程式,僅需要將資料呈現在對的HTML裡面,不要再對資料重複處理過。

架構設計準則

159

Page 160: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

像是文章的網址可能會因為類型不同會有不同的網址,像是一般文章網址可能為

http://kejyun.com/post/1,而影音文章網址可能為

http://kejyun.com/video/2,兩者的資料皆為Post資料表的資料,在

View中要顯示網址應為 echo$Post->post_url;將網址印出, post_url

則是在傳給 View之前就經過邏輯判斷的資料,而不是在 View中判斷不同文

章類型( PostConstant::POST_TYPE_NORMAL,PostConstant::POST_TYPE_VIDEO)在View中顯示不同的網址資料。

之後若文章網址邏輯需要修改,則需要到各個View中去修改,很容易漏改道造成

系統程式出錯

<ahref="{{$Post->post_url}}">{{$Post->Title}}</a>

結構範例說明

Controller(控制器)可以存取結構: Concrete、 Service、 DBtrancsction

可以被存取結構:無

處理HTTP請求的入口,依照需求呼叫Concrete或Service去做資料的存取,大

部分情況呼叫Service去組合需要的資料就好,若相同的組合邏輯在不同的

Controller都有用到,那就使用Concrete去組合不同的Service

要確保所有Service商業邏輯都正確跑完才允許對資料做異動,並避免Transaction在Controller及Service被重複呼叫,導致無法正確鎖定資料狀態,所以使用

Controller當作資料交易(Transaction)的控制點

classPostControllerextendsController

{

publicfunction__construct(

PostConcrete$PostConcrete,

CommentService$CommentService

)

{

$this->PostConcrete=$PostConcrete;

$this->PostService=$PostService;

架構設計準則

160

Page 161: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$this->CommentService=$CommentService;

}

//顯示文章

publicfunctionshow($post_id){

try{

//撈取文章

$Post=$this->PostConcrete->findPost($post_id);

//撈取文章留言

$Comment=$this->CommentService->getCommentByPostId

(post_id);

}catch(Exception$exception){

throw$exception

}

}

//更新文章

publicfunctionupdate($post_id){

try{

//交易開始

DB::beginTransaction();

//更新文章

$Post=$this->PostService->update($post_id,$update

_data);

//交易結束

DB::commit();

}catch(Exception$exception){

//交易失敗

DB::rollBack();

throw$exception

}

}

}

Concrete(服務組合)

可以存取結構: Service

可以被存取結構: Controller

架構設計準則

161

Page 162: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

使用不同Service撈取資料,將不同資料組合成商業邏輯,供Controller做存取

classPostConcrete{

publicfunction__construct(

PostService$PostService,

UserService$UserService

)

{

$this->PostService=$PostService;

$this->UserService=$UserService;

}

//撈取文章資料

publicfunctionfindPost($post_id){

try{

//撈取文章

$Post=$this->PostService->findPost($post_id);

//撈取文章作者資料

$user_id=$Post->user_id;

$Post->user=$this->UserService->findUser($user_id)

;

return$Post;

}catch(Exception$exception){

throw$exception

}

}

}

Service(服務)可以存取結構: Validator、 Repository

可以被存取結構: Controller、 Concrete

透過Validator驗證傳入的資料,並使用不同的Repository撈取資料,將不同資料

組合成商業邏輯使用Repository的Cache清除Service中撈取資料的快取

classPostService{

架構設計準則

162

Page 163: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

publicfunction__construct(

PostRepository$PostRepository,

PostTagRepository$PostTagRepository,

PostValidator$PostValidator

)

{

$this->PostRepository=$PostRepository;

$this->PostTagRepository=$PostTagRepository;

$this->PostValidator=$PostValidator;

}

//撈取文章

publicfunctionfindPost($post_id){

try{

//驗證傳入資料是否正確

$input=[

'post_id'=>$post_id

];

$this->PostValidator->validateFindPost($input);

//撈取文章

$Post=$this->PostRepository->find($post_id);

//撈取文章標籤

$Post->tag=$this->PostTagRepository->getByPostId($

post_id);

return$Post;

}catch(Exception$exception){

throw$exception

}

}

publicfunctionclearPostCache($post_id){

try{

//驗證傳入資料是否正確

$input=[

'post_id'=>$post_id

];

$this->PostValidator->validateClearPostCache($input)

;

$Post=$this->findPost($post_id);

架構設計準則

163

Page 164: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

//清除文章快取

$this->PostRepository->cache()->clearPostCache($Post

);

//清除文章標籤快取

$this->PostTagCache->clearPostTagCache($Post->tag);

}catch(Exception$exception){

throw$exception

}

}

}

Validator(驗證器)

可以存取結構:無

可以被存取結構: Service

協助Service驗證資料的正確性,若驗證錯誤則丟處例外,Controller根據例外代

碼去做處理

classPostValidator{

publicfunctionvalidatefindPost($input){

//驗證找尋文章資料是否正確

thrownewException(

'文章編號格式錯誤',

PostExceptionCode::POST_ID_FORMAT_ERROR

);

}

}

Repository(資源庫)

可以存取結構:自己的Model、自己的Cache

可以被存取結構: Service

僅能撈取屬於自己的Model資料,像 PostRepository僅能存取 PostModel(模型)的資料,並使用不同條件撈取Model的資料,供Service做存取

架構設計準則

164

Page 165: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

classPostRepository{

publicfunction__construct(

Post$Post,

PostCache$PostCache

)

{

$this->Post=$Post;

$this->PostCache=$PostCache;

}

publicfunctioncache(){

return$this->PostCache;

}

publicfunctionfind($post_id){

try{

$cache_key=$this->cache()->getPostCacheKey($post_i

d);

if(Cache::has($cache_key)){

//有快取資料

$Post=Cache::get($cache_key);

return$Post;

}

//撈取資料庫文章資料

$Post=$this->Post->find($post_id);

if(!is_null($Post)){

//紀錄快取

$this->cache()->putPost($Post);

}

return$Post;

}catch(Exception$exception){

throw$exception

}

}

publicfunctionfindLatestPost(){

try{

架構設計準則

165

Page 166: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$cache_key=$this->cache()->getLatestPostCacheKey($

post_id);

if(Cache::has($cache_key)){

//有快取資料

$$Posts=Cache::get($cache_key);

return$Post;

}

//撈取資料庫文章資料

$Post=$this->Post

->order('created_at','desc')

->first();

if(!is_null($Post)){

//紀錄快取

$this->cache()->putLatestPost($Post);

}

return$Post;

}catch(Exception$exception){

throw$exception

}

}

}

Cache(快取)

可以存取結構:無

可以被存取結構: Repository

協助Repository做快取資料的控制,快取鍵值的管理、資料讀取及清除

架構設計準則

166

Page 167: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

classPostCache{

publicfunctiongetPostCacheKey($post_id){

//撈取文章快取鍵值

}

publicfunctionputPost(Post$Post){

//紀錄文章快取

}

publicfunctionclearPostCache(Post$Post){

//清除文章快取

}

}

Model(模型)可以存取結構:無

可以被存取結構: Repository

Eloquent存取資料表相關設定,使用Eloquent直接存取資料表資料

classPostextendsModel

{

protected$table='post';

protected$fillable=[];

protected$primaryKey='id';

protected$dates=['created_at','updated_at'];

protected$presenter='PostPresenter';

}

Presenter(資料呈現)

架構設計準則

167

Page 168: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

可以存取結構:無

可以被存取結構: Model

提供Model的資料用其他方式呈現

classPostPresenterextendsPresenter

{

publicfunctioncreated_at_human_time()

{

return$this->created_at->diffForHumans();

}

}

Constant(常數)可以存取結構:無

可以被存取結構:無限制

資料皆為靜態變數,可以供所有資料層級(e.g.Controller、Service、Repository)做存取

classPostConstant{

constPOST_TYPE_PUBLIC='P';

constPOST_TYPE_DELETE='D';

}

Support(支援)可以存取結構:無

可以被存取結構:無限制

方法皆為靜態變數,可以供所有資料層級(e.g.Controller、Service、Repository)做存取

若有其他可供全域共用的方法皆寫在Support靜態方法供大家存取

架構設計準則

168

Page 169: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

classPostSupport{

//撈取所有文章類型

publicstaticfunctiongetAllPostType(){

$all_post_type=[

PostConstant::POST_TYPE_PUBLIC,

PostConstant::POST_TYPE_DELETE,

];

return$all_post_type;

}

}

ExceptionCode(例外代碼)可以存取結構:無

可以被存取結構:無限制

資料皆為靜態變數,可以供所有資料層級(e.g.Controller、Service、Repository)做存取

classPostExceptionCode{

constPOST_ID_FORMAT_ERROR=10000001;

constPOST_NOT_FOUND=10000002;

constPOST_TAG_NOT_FOUND=10000003;

}

架構設計準則

169

Page 170: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

學習資源

文章

框架不應該有「MODELS」資料夾

投影片

胖胖Model減重的五個方法byhowtomakeaturn

影片

PHP也有Day#16-胖胖Model減重的五個方法by尤川豪

學習資源

170

Page 171: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

套件

這裏會介紹一些Laravel5一些常用的套件

套件

171

Page 172: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Debug套件

這裏會介紹一些在Laravel5會用到的Debug套件

Debug

172

Page 173: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Artisantail在Laravel4我們常常用 phpartisantail去即時顯示系統的Log,以便我們

進行除錯,但在Laravel5預設是將這個套件拿到的,所以如果我們要繼續使用的

話,必須要手動的將套件加回去。

安裝Laraveltail套件

首先在命令列執行 composerrequirespatie/laravel-tail安裝tail套件

$composerrequirespatie/laravel-tail

接著在 config/app.php檔案中的 providers加入tailServiceProvider

//config/app.php

'providers'=>[

...

'Spatie\Tail\TailServiceProvider',

...

];

安裝完畢之後就可以繼續使用 phpartisantail去觀看你的Log了!

$phpartisantail

tail遠端主機Log檔tail命令可以讓我們即時觀看遠端的Log檔案,我們只要將遠端主機的相關設定加

入即可,可以使用下列指令建立 config/tail.php檔案

$phpartisanvendor:publish--provider="Spatie\Tail\TailService

Provider"

Artisantail

173

Page 174: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

之後只要在tail指令後面加入要觀看的主機名稱,即可立即觀看該主機的Log檔摟

$phpartisantailproduction

參考資料

ThemissingtailcommandforLaravel5

Artisantail

174

Page 175: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

工具套件

這裏會介紹一些Laravel5常用的一些套件工具

工具

175

Page 176: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Carbon時間套件

Carbon是一個很方便的轉換時間的工具,可以很方便地將時間進行轉換,取得我

們想要的特定日期或格式

安裝

Laravel5預設就會安裝Carbon套件,若沒有安裝的話可以透過下列的方式進行安

裝:

#使用Composer下載Carbon

$composerrequirenesbot/carbon

<?php

//載入composerautoload檔案

require'vendor/autoload.php';

//使用Carbon類別

useCarbon\Carbon;

printf("Now:%s",Carbon::now());

快速切換前後日期

Carbon

176

Page 177: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useCarbon\Carbon;

$now=Carbon::now();

echo$now;//2015-03-2600:36:47

$today=Carbon::today();

echo$today;//2015-03-2600:00:00

$tomorrow=Carbon::tomorrow('Europe/London');

echo$tomorrow;//2015-03-2700:00:00

$yesterday=Carbon::yesterday();

echo$yesterday;//2015-03-2500:00:00

建立特定日期的時間

Carbon

177

Page 178: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useCarbon\Carbon;

$timezone='Asia/Taipei';

//從「年月日」建立

Carbon::createFromDate($year,$month,$day,$timezone);

//從「時分秒」建立

Carbon::createFromTime($hour,$minute,$second,$timezone);

//從完整的「年月日時分秒」建立

Carbon::create($year,$month,$day,$hour,$minute,$second,$ti

mezone);

//從指定的格式建立

Carbon::createFromFormat($format,$time,$tz);

echoCarbon::createFromFormat('Y-m-dH','1975-05-2122')->toDat

eTimeString();//1975-05-2122:00:00

//從時間戳記建立

echoCarbon::createFromTimeStamp(-1)->toDateTimeString();

//1969-12-3118:59:59

echoCarbon::createFromTimeStamp(-1,'Europe/London')->toDateTim

eString();//1970-01-0100:59:59

echoCarbon::createFromTimeStampUTC(-1)->toDateTimeString();

//1969-12-3123:59:59

轉換日期

Carbon

178

Page 179: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useCarbon\Carbon;

//透過文字移動日期

$knownDate=Carbon::create(2001,5,21,12);//create

testingdate

Carbon::setTestNow($knownDate);//setth

emock

echonewCarbon('tomorrow');//2001-0

5-2200:00:00...noticethetime!

echonewCarbon('yesterday');//2001-0

5-2000:00:00

echonewCarbon('nextwednesday');//2001-0

5-2300:00:00

echonewCarbon('lastfriday');//2001-0

5-1800:00:00

echonewCarbon('thisthursday');//2001-0

5-2400:00:00

取得日期資料

<?php

useCarbon\Carbon;

$dt=Carbon::parse('2012-9-523:26:11.123789');

//取的指定時間資料的資訊(整數)

var_dump($dt->year);//

int(2012)

var_dump($dt->month);//

int(9)

var_dump($dt->day);//

int(5)

var_dump($dt->hour);//

int(23)

var_dump($dt->minute);//

Carbon

179

Page 180: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

int(26)

var_dump($dt->second);//

int(11)

var_dump($dt->micro);//

int(123789)

var_dump($dt->dayOfWeek);//

int(3)

var_dump($dt->dayOfYear);//

int(248)

var_dump($dt->weekOfMonth);//

int(1)

var_dump($dt->weekOfYear);//

int(36)

var_dump($dt->daysInMonth);//

int(30)

var_dump($dt->timestamp);//

int(1346901971)

var_dump(Carbon::createFromDate(1975,5,21)->age);//

int(39)calculatedvsnowinthesametz

var_dump($dt->quarter);//

int(3)

//回傳與UTC差異的秒數

var_dump(Carbon::createFromTimestampUTC(0)->offset);//

int(0)

var_dump(Carbon::createFromTimestamp(0)->offset);//

int(-18000)

//回傳與UTC差異的時數

var_dump(Carbon::createFromTimestamp(0)->offsetHours);//

int(-5)

//找出當天日否有日光節約時間

var_dump(Carbon::createFromDate(2012,1,1)->dst);//

bool(false)

var_dump(Carbon::createFromDate(2012,9,1)->dst);//

bool(true)

//判斷指定的的時區是否與預設的時區相同

Carbon

180

Page 181: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

var_dump(Carbon::now()->local);//

bool(true)

var_dump(Carbon::now('America/Vancouver')->local);//

bool(false)

//判斷是否為UTC的時區時間

var_dump(Carbon::now()->utc);//

bool(false)

var_dump(Carbon::now('Europe/London')->utc);//

bool(true)

var_dump(Carbon::createFromTimestampUTC(0)->utc);//

bool(true)

//取得時區實例

echoget_class(Carbon::now()->timezone);//

DateTimeZone

echoget_class(Carbon::now()->tz);//

DateTimeZone

//取得時區實例的名稱

echoCarbon::now()->timezoneName;//

America/Toronto

echoCarbon::now()->tzName;//

America/Toronto

設定時間資料

Carbon

181

Page 182: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useCarbon\Carbon;

$dt=Carbon::now();

$dt->year=1975;

$dt->month=13;//年份會強制+1,且月份變為1月

$dt->month=5;

$dt->day=21;

$dt->hour=22;

$dt->minute=32;

$dt->second=5;

$dt->timestamp=169957925;//這個設定不會變更時區

//透過字串或是DateTimeZone實例去設定時區

$dt->timezone=newDateTimeZone('Europe/London');

$dt->timezone='Europe/London';

$dt->tz='Europe/London';

//鏈結設定方式

$dt->year(1975)->month(5)->day(21)->hour(22)->minute(32)->second(

5)->toDateTimeString();

$dt->setDate(1975,5,21)->setTime(22,32,5)->toDateTimeString(

);

$dt->setDateTime(1975,5,21,22,32,5)->toDateTimeString();

$dt->timestamp(169957925)->timezone('Europe/London');

$dt->tz('America/Toronto')->setTimezone('America/Vancouver');

格式化時間資料

Carbon

182

Page 183: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useCarbon\Carbon;

$dt=Carbon::create(1975,12,25,14,15,16);

var_dump($dt->toDateTimeString()==$dt);//bool(true)

=>uses__toString()

echo$dt->toDateString();//1975-12-25

echo$dt->toFormattedDateString();//Dec25,19

75

echo$dt->toTimeString();//14:15:16

echo$dt->toDateTimeString();//1975-12-25

14:15:16

echo$dt->toDayDateTimeString();//Thu,Dec2

5,19752:15PM

//仍可以使用format()函式

echo$dt->format('ljS\\ofFYh:i:sA');//Thursday2

5thofDecember197502:15:16PM

//常用的時間格式

echo$dt->toAtomString();//in1Jahr

echo$dt->toCookieString();//Thursday,25-Dec-197514:15:16

EST

echo$dt->toIso8601String();//1975-12-25T14:15:16-0500

echo$dt->toRfc822String();//Thu,25Dec7514:15:16-0500

echo$dt->toRfc850String();//Thursday,25-Dec-7514:15:16E

ST

echo$dt->toRfc1036String();//Thu,25Dec7514:15:16-0500

echo$dt->toRfc1123String();//Thu,25Dec197514:15:16-0500

echo$dt->toRfc2822String();//Thu,25Dec197514:15:16-0500

echo$dt->toRfc3339String();//1975-12-25T14:15:16-05:00

echo$dt->toRssString();//Thu,25Dec197514:15:16-0500

echo$dt->toW3cString();//1975-12-25T14:15:16-05:00

Carbon

183

Page 184: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

比較時間差異

<?php

useCarbon\Carbon;

echoCarbon::now()->tzName;//America/To

ronto

$first=Carbon::create(2012,9,5,23,26,11);

$second=Carbon::create(2012,9,5,20,26,11,'America/Vancou

ver');

echo$first->toDateTimeString();//2012-09-05

23:26:11

echo$first->tzName;//America/To

ronto

echo$second->toDateTimeString();//2012-09-05

20:26:11

echo$second->tzName;//America/Va

ncouver

//大於、等於、小於

var_dump($first->eq($second));//bool(true)

var_dump($first->ne($second));//bool(false)

var_dump($first->gt($second));//bool(false)

var_dump($first->gte($second));//bool(true)

var_dump($first->lt($second));//bool(false)

var_dump($first->lte($second));//bool(true)

$first->setDateTime(2012,1,1,0,0,0);

$second->setDateTime(2012,1,1,0,0,0);//Remembert

zis'America/Vancouver'

var_dump($first->eq($second));//bool(false)

var_dump($first->ne($second));//bool(true)

Carbon

184

Page 185: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

var_dump($first->gt($second));//bool(false)

var_dump($first->gte($second));//bool(false)

var_dump($first->lt($second));//bool(true)

var_dump($first->lte($second));//bool(true)

//時間區間比較

$first=Carbon::create(2012,9,5,1);

$second=Carbon::create(2012,9,5,5);

var_dump(Carbon::create(2012,9,5,3)->between($first,$second)

);//bool(true)

var_dump(Carbon::create(2012,9,5,5)->between($first,$second)

);//bool(true)

var_dump(Carbon::create(2012,9,5,5)->between($first,$second,

false));//bool(false)

//時間大小比較

$dt1=Carbon::create(2012,1,1,0,0,0);

$dt2=Carbon::create(2014,1,30,0,0,0);

echo$dt1->min($dt2);//2012-01-01

00:00:00

$dt1=Carbon::create(2012,1,1,0,0,0);

$dt2=Carbon::create(2014,1,30,0,0,0);

echo$dt1->max($dt2);//2014-01-30

00:00:00

//nowisthedefaultparam

$dt1=Carbon::create(2000,1,1,0,0,0);

echo$dt1->max();

//時間差異運算

echoCarbon::now('America/Vancouver')->diffInSeconds(Carbon::now(

'Europe/London'));//0

Carbon

185

Page 186: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$dtOttawa=Carbon::createFromDate(2000,1,1,'America/Toronto'

);

$dtVancouver=Carbon::createFromDate(2000,1,1,'America/Vanco

uver');

echo$dtOttawa->diffInHours($dtVancouver);

//3

echo$dtOttawa->diffInHours($dtVancouver,false);

//3

echo$dtVancouver->diffInHours($dtOttawa,false);

//-3

$dt=Carbon::create(2012,1,31,0);

echo$dt->diffInDays($dt->copy()->addMonth());

//31

echo$dt->diffInDays($dt->copy()->subMonth(),false);

//-31

$dt=Carbon::create(2012,4,30,0);

echo$dt->diffInDays($dt->copy()->addMonth());

//30

echo$dt->diffInDays($dt->copy()->addWeek());

//7

$dt=Carbon::create(2012,1,1,0);

echo$dt->diffInMinutes($dt->copy()->addSeconds(59));

//0

echo$dt->diffInMinutes($dt->copy()->addSeconds(60));

//1

echo$dt->diffInMinutes($dt->copy()->addSeconds(119));

//1

echo$dt->diffInMinutes($dt->copy()->addSeconds(120));

//2

echo$dt->addSeconds(120)->secondsSinceMidnight();

//120

時間狀態

Carbon

186

Page 187: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useCarbon\Carbon;

$dt=Carbon::now();

$dt->isWeekday();

$dt->isWeekend();

$dt->isYesterday();

$dt->isToday();

$dt->isTomorrow();

$dt->isFuture();

$dt->isPast();

$dt->isLeapYear();

$dt->isSameDay(Carbon::now());

$born=Carbon::createFromDate(1987,4,23);

$noCake=Carbon::createFromDate(2014,9,26);

$yesCake=Carbon::createFromDate(2014,4,23);

var_dump($born->isBirthday($noCake));//bool(false

)

var_dump($born->isBirthday($yesCake));//bool(true)

時間運算

<?php

useCarbon\Carbon;

$dt=Carbon::create(2012,1,31,0);

echo$dt->toDateTimeString();//2012-01-3100:00:00

echo$dt->addYears(5);//2017-01-3100:00:00

echo$dt->addYear();//2018-01-3100:00:00

echo$dt->subYear();//2017-01-3100:00:00

echo$dt->subYears(5);//2012-01-3100:00:00

echo$dt->addMonths(60);//2017-01-3100:00:00

Carbon

187

Page 188: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

echo$dt->addMonth();//2017-03-0300:00:00

equivalentof$dt->month($dt->month+1);soitwraps

echo$dt->subMonth();//2017-02-0300:00:00

echo$dt->subMonths(60);//2012-02-0300:00:00

echo$dt->addDays(29);//2012-03-0300:00:00

echo$dt->addDay();//2012-03-0400:00:00

echo$dt->subDay();//2012-03-0300:00:00

echo$dt->subDays(29);//2012-02-0300:00:00

echo$dt->addWeekdays(4);//2012-02-0900:00:00

echo$dt->addWeekday();//2012-02-1000:00:00

echo$dt->subWeekday();//2012-02-0900:00:00

echo$dt->subWeekdays(4);//2012-02-0300:00:00

echo$dt->addWeeks(3);//2012-02-2400:00:00

echo$dt->addWeek();//2012-03-0200:00:00

echo$dt->subWeek();//2012-02-2400:00:00

echo$dt->subWeeks(3);//2012-02-0300:00:00

echo$dt->addHours(24);//2012-02-0400:00:00

echo$dt->addHour();//2012-02-0401:00:00

echo$dt->subHour();//2012-02-0400:00:00

echo$dt->subHours(24);//2012-02-0300:00:00

echo$dt->addMinutes(61);//2012-02-0301:01:00

echo$dt->addMinute();//2012-02-0301:02:00

echo$dt->subMinute();//2012-02-0301:01:00

echo$dt->subMinutes(61);//2012-02-0300:00:00

echo$dt->addSeconds(61);//2012-02-0300:01:01

echo$dt->addSecond();//2012-02-0300:01:02

echo$dt->subSecond();//2012-02-0300:01:01

echo$dt->subSeconds(61);//2012-02-0300:00:00

人類閱讀時間格式

Carbon

188

Page 189: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useCarbon\Carbon;

//通常會用在留言的時間顯示

//該時間會比較與現在的時間的差異

echoCarbon::now()->subDays(5)->diffForHumans();/

/5daysago

echoCarbon::now()->diffForHumans(Carbon::now()->subYear());/

/1yearafter

$dt=Carbon::createFromDate(2011,8,1);

echo$dt->diffForHumans($dt->copy()->addMonth());/

/1monthbefore

echo$dt->diffForHumans($dt->copy()->subMonth());/

/1monthafter

echoCarbon::now()->addSeconds(5)->diffForHumans();/

/5secondsfromnow

echoCarbon::now()->subDays(24)->diffForHumans();/

/3weeksago

echoCarbon::now()->subDays(24)->diffForHumans(null,true);/

/3weeks

時間常數

Carbon

189

Page 190: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

useCarbon\Carbon;

var_dump(Carbon::SUNDAY);//int(0)

var_dump(Carbon::MONDAY);//int(1)

var_dump(Carbon::TUESDAY);//int(2)

var_dump(Carbon::WEDNESDAY);//int(3)

var_dump(Carbon::THURSDAY);//int(4)

var_dump(Carbon::FRIDAY);//int(5)

var_dump(Carbon::SATURDAY);//int(6)

var_dump(Carbon::YEARS_PER_CENTURY);//int(100)

var_dump(Carbon::YEARS_PER_DECADE);//int(10)

var_dump(Carbon::MONTHS_PER_YEAR);//int(12)

var_dump(Carbon::WEEKS_PER_YEAR);//int(52)

var_dump(Carbon::DAYS_PER_WEEK);//int(7)

var_dump(Carbon::HOURS_PER_DAY);//int(24)

var_dump(Carbon::MINUTES_PER_HOUR);//int(60)

var_dump(Carbon::SECONDS_PER_MINUTE);//int(60)

參考資料

Carbon-AsimplePHPAPIextensionforDateTime.Carbon-docs

Carbon

190

Page 191: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

設計模式套件

這裏會介紹一些Laravel5不錯的設計模式套件

Entity資料顯示

laracasts/presenter

設計模式

191

Page 192: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

文字處理

文字發音

Laravel-pinyin

文字

192

Page 193: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

視圖

解析

yangqi/Htmldom-SimpleHTMLDomParser

最小化

Laravel-HTMLMinHTMLMinifierinLaravel5.*

視圖

193

Page 194: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

認證套件

這裏會介紹一些在Laravel5會用到的認證套件

參考資料

10ThingsYouShouldKnowaboutTokensCSRFTokennecessarywhenusingStateless(=Sessionless)Authentication?WheretoStoreYourJWTs-CookiesvsHTML5WebStorageCookiesarebadforyou:Improvingwebapplicationsecurity

認證

194

Page 195: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

OAuth2認證套件

使用套件

套件名稱:lucadegasperi/oauth2-server-laravel

套件版本:5.0.3

名詞解釋

名詞 描述

Accesstoken 存取標記,用於存取受保護資源的標記

Authorizationcode

授權碼,使用者授權Client的中介標記,Client可以透過此授權碼去取得Accesstoken

Authorizationserver

授權伺服器,使用者授權Client後,用於發送Accesstoken的伺服器

Client 被授權客戶,存取屬於使用者的受保護資源的應用程式(Application),像是Server、手機或其他裝置

Grant 授權方法,存取Accesstoken的方法

Resourceserver

資源伺服器,屬於使用者的受保護資源(像是文章、照片、個人隱私資料...等等)

Scope 資源存取範圍,Accesstoken允許存取的權限

ref:lucadegasperi/oauth2-server-laravel-Terminology

安裝

使用composer安裝套件

在 composer.json加入 "lucadegasperi/oauth2-server-laravel":"5.0.*"並執行 composerupdate安裝套件

OAuth2

195

Page 196: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

/*composer.json*/

"require":{

"lucadegasperi/oauth2-server-laravel":"5.0.*"

}

$composerupdate

設定套件

開啟 config/app.php檔案,並將系列套件資訊加入 providers與 aliases

'providers'=>[

LucaDegasperi\OAuth2Server\Storage\FluentStorageServiceProvi

der::class,

LucaDegasperi\OAuth2Server\OAuth2ServerServiceProvider::clas

s,

],

'aliases'=>[

'Authorizer'=>LucaDegasperi\OAuth2Server\Facades\Authorize

r::class,

]

設定middleware開啟 app/Http/Kernel.php,將系列設定加入$middleware與$routeMiddleware中

並將原本在$middleware的\App\Http\Middleware\VerifyCsrfToken::class移至$routeMiddleware,並命名為csrf

注意,原本Laravel會針對每個非Get的Request做CSRF的過濾,因為

OAuth已經取得授權Accesstoken,不需要CSRF驗證,所以如果你需要做

CSRF驗證的話,您可以在Route加入 csrf的middleware去做驗證

OAuth2

196

Page 197: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

<?php

classKernelextendsHttpKernel

{

protected$middleware=[

\LucaDegasperi\OAuth2Server\Middleware\OAuthExceptionHan

dlerMiddleware::class

];

protected$routeMiddleware=[

//CSRF

'csrf'=>\App\Http\Middleware\VerifyCsrfToken::class,

//OAuth2

'oauth'=>\LucaDegasperi\OAuth2Server\Middleware\OAuthM

iddleware::class,

'oauth-user'=>\LucaDegasperi\OAuth2Server\Middleware\O

AuthUserOwnerMiddleware::class,

'oauth-client'=>\LucaDegasperi\OAuth2Server\Middleware

\OAuthClientOwnerMiddleware::class,

'check-authorization-params'=>\LucaDegasperi\OAuth2Ser

ver\Middleware\CheckAuthCodeRequestMiddleware::class

];

}

產生套件設定及Migration執行 phpartisanvendor:publish複製套件的 migration與config/oauth.php設定檔到你應用程式的目錄,並執行migration建立OAuth2需要的資料表

$phpartisanvendor:publish

$phpartisanmigrate

設定檔名詞解釋

OAuth2

197

Page 198: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

參數名稱 說明資料類

型預設值

grant_types 授權類型設定 Array 無

token_type token類型 String League\OAuth2\Server\TokenType\Bearer

state_param

狀態參數,如果為true的話,在請求Accesstoken時候則必須帶入 &state=隨機字串,在透過授權後Authorizationserver會回覆相同的state字串

Boolean false

scope_param

存取權限參數,若為true,則在每一次的Request都需要帶入該資源的存取參數

Boolean false

scope_delimiter

存取權限區隔字串,在不同的存取權限使用什麼字元去區隔(scope1,scope2)

String ,

default_scope 預設存取權限 String null

access_token_ttl Accesstoken存活時間(單位:秒)

Integer 3600

limit_clients_to_grants是否限制Client允許使用的GrantType,可以在oauth_client_grants

資料表設定

Boolean false

limit_clients_to_scopes限制Client允許的Scope,可以在oauth_client_scopes

資料表設定

Boolean false

limit_scopes_to_grants限制Scope允許在哪個GrantType存取,可以在oauth_grant_scopes

資料表設定

Boolean false

http_headers_only 是否只使用Header做Accesstoken的檢查

Boolean false

OAuth2Accesstoken取得的方式

OAuth2

198

Page 199: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

OAuth2總共有下列4種Accesstoken取得的方式

Accesstoken取得

方式說明

ClientCredentials

純Client資料身份驗證,僅需要client_id與client_secret正確即可取得Accesstoken

Password 資源擁有者須登入帳號密碼,確認可以讓Client取得Accesstoken

AuthCodeGrant

資源擁有者授權Client可以存取指定Scope的資源並給予授權碼,Client透過此授權碼取得該Scope的Accesstoken

RefreshTokenGrant

授權Client在取得Accesstoken時也一併取得Refreshtoken,在Accesstoken過期時,Client可以用此Refreshtoken取得新的相同權限的Accesstoken

設定存取Accesstoken路由

不管是何種OAuth2Accesstoken取得的方式,都須透過 相同的路由去取得

Accesstoken,OAuth2會根據每個取得方式參數的不同做不一樣的驗證,所以我

們只有設定下列路由即可

Route::post('oauth/access_token',function(){

returnResponse::json(Authorizer::issueAccessToken());

});

設定client_id與client_secret每一個Client應用程式都會有自己的 client_id與 client_secret,你可以

自己設定你要核發給Client授權client_id與client_secret的頁面,並將資料分別

存放在 oauth_clients資料表的id與secret欄位中

OAuth2

199

Page 200: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Schema::create('oauth_clients',function(BluePrint$table){

$table->string('id',40)->primary();//client_id

$table->string('secret',40);//client_secret

$table->string('name');//Client名稱

$table->timestamps();

$table->unique(['id','secret']);

});

Client資料新增完成之後,之後Client可以透過這個client_id與client_secret去要

求取得Accesstoken,我們這裡以新增id為 KeKyun及secret為KeJyunSecret作為之後的範例

INSERTINTO"oauth_clients"("id","secret","name","created_at"

,"updated_at")

VALUES('KeJyun','KeJyunSecret','KeJyunClient',now(),now())

;

client_id與client_secret欄位長度皆為40,在產生資料時請自行產生長度40的亂數字串,這裡僅用於示範使用非亂數的client_id與client_secret

參考資料

lucadegasperi/oauth2-server-laravelOAuth2.0筆記(1)世界觀

OAuth2.0筆記(2)Client的註冊與認證

OAuth2.0筆記(3)Endpoints的規格

OAuth2.0筆記(4.1)AuthorizationCodeGrantFlow細節

OAuth2.0筆記(4.2)ImplicitGrantFlow細節

OAuth2.0筆記(4.3)ResourceOwnerPasswordCredentialsGrantFlow細節

OAuth2.0筆記(4.4)ClientCredentialsGrantFlow細節

OAuth2.0筆記(5)核發與換發AccessTokenOAuth2.0筆記(6)BearerToken的使用方法

OAuth2.0筆記(7)安全性問題

各大網站OAuth2.0實作差異

IntroductiontoauthenticationwithOAuth2

OAuth2

200

Page 201: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Laravel4OAuth2TestingOAuth2inLaravel5

OAuth2

201

Page 202: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

OAuth2ClientCredentials

設定config在 config/oauth2.php檔案中加入下列設定,並設定你的 token存活時間

(access_token_ttl),單位時間為秒

return[

'grant_types'=>[

'client_credentials'=>[

'class'=>'\League\OAuth2\Server\Grant\ClientCred

entialsGrant',

'access_token_ttl'=>3600

]

]

];

取得Accesstoken在我們取得Accesstoken的資料欄位中填入下列欄位

欄位名稱 資料

grant_types client_credentials

client_id KeJyun

client_secret KeJyunSecret

client_id與 client_secret為在OAuth套件說明頁建立的

OAuth2

202

Page 203: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

送出到我們設定的 /oauth/access_token路由後,我們就可以直接取得

access_token,並回傳此token失效的時間 expires_in為我們設定的

access_token_ttl

相關資料表

OAuth2會將token記錄在 oauth_access_tokens資料表,並將關聯的使用者

記錄在 oauth_sessions資料表,在 oauth_sessions中的 owner_id則為

oauth_clients資料表中Client的 id

參考資料

ClientCredentials

OAuth2

203

Page 204: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

OAuth2PasswordGrant

設定config在 config/oauth2.php檔案中加入下列設定,並設定你的 token存活時間

(access_token_ttl),單位時間為秒,在 callback設定您要用來驗證使用者

帳號密碼的類別函式,OAuth2會透過這個callback去驗證使用者的帳號密碼

return[

'grant_types'=>[

'password'=>[

'class'=>'\League\OAuth2\Server\Grant\PasswordGran

t',

'callback'=>'\App\PasswordVerifier@verify',

'access_token_ttl'=>3600

],

]

];

建立驗證身份callbackOAuth會將Client傳來的 username及 password欄位的資料透過

callback傳入並驗證,當中驗證的規則跟邏輯你可以自行定義,若驗證失敗回

傳 false即可,驗證成功的話可以將使用者的編號回傳,OAuth會將Accesstoken對應的使用者編號(資源擁有者編號)記錄下來

OAuth2

204

Page 205: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

useIlluminate\Support\Facades\Auth;

classPasswordGrantVerifier

{

publicfunctionverify($username,$password)

{

$credentials=[

'email'=>$username,

'password'=>$password,

];

//驗證成功

if(Auth::once($credentials)){

returnAuth::user()->id;

}

//驗證失敗

returnfalse;

}

}

取得Accesstoken在我們取得Accesstoken的資料欄位中填入下列欄位

欄位名稱 資料

grant_types password

username [email protected]

password 123456

client_id KeJyun

client_secret KeJyunSecret

client_id與 client_secret為在OAuth套件說明頁建立的

username與 password是你專案的使用者驗證資料,端看你驗證的

callback如何定義這兩個欄位的資料,驗證成功後回傳使用者的編號給

OAuth2記錄即可

OAuth2

205

Page 206: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

送出到我們設定的 /oauth/access_token路由後,我們就可以直接取得

access_token,並回傳此token失效的時間 expires_in為我們設定的

access_token_ttl

相關資料表

OAuth2會將token記錄在 oauth_access_tokens資料表,並將關聯的使用者

記錄在 oauth_sessions資料表,在 oauth_sessions中的 owner_id則為

我們剛剛回傳的使用者編號

參考資料

PasswordGrant

OAuth2

206

Page 207: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

OAuth2RefreshToken

設定config在 config/oauth2.php檔案中加入下列設定,並設定你的 token存活時間

(access_token_ttl)及 refreshtoken存活時間(refresh_token_ttl)單位

時間為秒

注意,若使用RefreshToken時,必須至少有 PasswordGrant或 AuthCodeGrant的這兩種OAuth2驗證方法其中一種,然後在取得Accesstoken時,會一併回傳refreshtoken

return[

'grant_types'=>[

'refresh_token'=>[

'class'=>'\League\OAuth2\Server\Grant\RefreshToken

Grant',

'access_token_ttl'=>3600,

'refresh_token_ttl'=>36000

]

]

];

使用PasswordGrant取得Accesstoken及RefreshToken在我們取得Accesstoken的資料欄位中填入下列欄位

OAuth2

207

Page 208: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

欄位名稱 資料

grant_types password

username [email protected]

password 123456

client_id KeJyun

client_secret KeJyunSecret

client_id與 client_secret為在OAuth套件說明頁建立的

username與 password是你專案的使用者驗證資料,端看你驗證的

callback如何定義這兩個欄位的資料,驗證成功後回傳使用者的編號給

OAuth2記錄即可

送出到我們設定的 /oauth/access_token路由後,我們就可以直接取得

access_token,並回傳此token失效的時間 expires_in為我們設定的

access_token_ttl,還有 refresh_token可以讓我們直接更新取得新的可用

token

使用RefreshToken取得的新的Accesstoken權限與先前的Accesstoken會完全相同

OAuth2

208

Page 209: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

透過RefreshToken取得新的AccessToken在我們取得Accesstoken的資料欄位中填入下列欄位

欄位名稱 資料

grant_types refresh_token

refresh_token Z9pBcvzzBquBzR01MrfYYWMECgVKlkCxTlkkU9zf

client_id KeJyun

client_secret KeJyunSecret

這樣我們就可以直接透過RefreshToken取得新的可使用者AccessToken,而不

用再透過使用者帳號密碼去取得可使用的AccessToken

相關資料表

OAuth2會將token記錄在 oauth_access_tokens資料表,並將關聯的使用者

記錄在 oauth_sessions資料表,在 oauth_sessions中的 owner_id則為

我們剛剛回傳的使用者編號

並在 oauth_refresh_tokens資料表中記錄RefreshToken是屬於哪一個

AccessToken,並透過這個關聯去產生新的AccessToken與新的RefreshToken

OAuth2

209

Page 211: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

OAuth2PasswordGrantWithScope延續PasswordGrant的OAuth2設定,我們可以在參數中加入我們要取得的 資源

存取範圍(Scope),讓這個AccessToken僅能有特定資源的存取權限

新增資源存取範圍(Scope)資料

OAuth2定義的Scope皆存在 oauth_scopes資料表中,我們在資料表中新增

user_profile及 user_likes這兩個Scope

INSERTINTO"oauth_scopes"("id","description","created_at","

updated_at")

VALUES('user_profile','profile',now(),now());

INSERTINTO"oauth_scopes"("id","description","created_at","

updated_at")

VALUES('user_likes','likes',now(),now());

取得Accesstoken在我們取得Accesstoken的資料欄位中填入下列欄位

欄位名稱 資料

grant_types password

username [email protected]

password 123456

client_id KeJyun

client_secret KeJyunSecret

scope user_profile,user_likes

我們的Scope也可以指填入一個,若要填入多個Scope的話,可以看

config/oauth2.php設定檔中的 scope_delimiter要怎麼區別不同的

Scope資源,預設是用 逗號「,」去區別Scope

OAuth2

211

Page 212: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

送出到我們設定的 /oauth/access_token路由後,我們就可以直接取得

access_token,並回傳此token失效的時間 expires_in為我們設定的

access_token_ttl

相關資料表

OAuth2會將token記錄在 oauth_access_tokens資料表,並將關聯的使用者

記錄在 oauth_sessions資料表,而 oauth_access_token_scopes資料表則

存放AccessToken相關的Scope資訊

參考資料

SecuringyourAPIendpoints

OAuth2

212

Page 213: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

驗證AccessToken

路由設定OAuthmiddleware在我們想要保護的資源中,我們可以加入 oauth的middleware中介層,這樣

//保護的資源設定oauthmiddleware

Route::get('/user-private-resource',['middleware'=>'oauth',fun

ction()

{

//取得資源擁有者編號,若經過PasswordGrant驗證的Token則為使用

者的編號

$user_id=Authorizer::getResourceOwnerId();

$data=[

'user_id'=>$user_id

];

//回傳受保護的資源

returnResponse::json($data);

}]);

透過AccessToken取的受保護的資源

在我們取得受保護資源的請求 Header中填入,這樣OAuth2就會取得我們傳入

的AccessToken,並驗證我們有沒有存取權限,若有存取權限,則會直接回傳該

受保護的資源

欄位名稱 資料

Authorization BearerrXXoWMg5UXzQpxAynCnYYOQiZQ0xDcAjT0ywGvke

OAuth2

213

Page 214: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

路由設定包含Scope的OAuthmiddleware若我們限制此路由需要有特定Scope的存取權限的AccessToken才可以存取,我

們可以在middleware後面加上允許的Scope名稱,若同時需要擁有多個Scope權限,則用 加號(+)把Scope連接起來即可

e.g.'oauth:user_profile+user_likes'

//保護的資源設定oauthmiddleware

Route::get('/user-private-resource',['middleware'=>'oauth:user_

profile+user_likes',function()

{

}]);

這樣這個路由就會被指定的Scope所保護著了~

參考資料

SecuringyourAPIendpoints

OAuth2

214

Page 215: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

JWT(JSONWebToken)Authentication

使用套件

套件名稱:tymondesigns/jwt-auth

套件版本:0.5.*

安裝

使用composer安裝套件

在 composer.json加入 ""tymon/jwt-auth":"0.5.*"並執行 composerupdate安裝套件

/*composer.json*/

"require":{

"tymon/jwt-auth":"0.5.*"

}

$composerupdate

設定套件

開啟 config/app.php檔案,並將系列套件資訊加入 providers與 aliases

'providers'=>[

Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,

],

'aliases'=>[

'JWTAuth'=>Tymon\JWTAuth\Facades\JWTAuth::class,

'JWTFactory'=>Tymon\JWTAuth\Facades\JWTFactory::class,

]

JWT

215

Page 216: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

產生套件設定

執行 phpartisanvendor:publish--provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"複製套件的

config/jwt.php設定檔到你應用程式的設定檔目錄

$phpartisanvendor:publish--provider="Tymon\JWTAuth\Providers

\JWTAuthServiceProvider"

產生JWTSecretKey

每個應用應該有屬於自己的JWTSecretKey用於加密並驗證你的資料

$phpartisanjwt:generate

產生的JWTSecretKey會設定在 config/jwt.php中的 secret中

//config/jwt.php

[

'secret'=>env('JWT_SECRET','your_personal_jwt_secret_key'

)

]

設定檔說明

JWT

216

Page 217: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

參數名稱 說明資料類

型預設值

secret 密鑰 String 無

ttl JWTtoken有效時間(單位:分鐘)

Integer 60

refresh_ttl token允許重新更新時間(單位:分鐘)

Integer 20160(2週)

algo 加密演算法 String HS256

user 使用者模型類別位置 String App\User

identifier 使用者資料主鍵欄位 String id

required_claims

必須包含在tokenpayload的資料,若驗證時無這些資料則會拋出TokenInvalidException

例外

Array ['iss','iat','exp','nbf','sub','jti']

blacklist_enabled 開啟黑名單清單 Boolean true

providers.user 找尋使用者類別物件 String Tymon\JWTAuth\Providers\User\EloquentUserAdapter

providers.jwt 用於加解密JWTToken的類別物件

String Tymon\JWTAuth\Providers\JWT\NamshiAdapter

providers.auth 取得受驗證使用者的類別物件

ClosureFunction

Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter

providers.storage儲存黑名單token的快取物件,token將會儲存到它過期為止

ClosureFunction

Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter

參考資料

tymondesigns/jwt-auth-Installationtymondesigns/jwt-auth-Configuration使用jsonwebtokenJsonWebTokens:IntroductionWheretoStoreYourJWTs-CookiesvsHTML5WebStorage

JWT

217

Page 218: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

JWT

218

Page 219: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

主機環境建置

程式寫完後,我們要上線測試時,還是需要一個完整的正式環境可以執行Laravel5,這裡會介紹大家如何不使用Homestead,在正式主機把Laravel5執行環境建

置起來

環境

Ubuntu14.04LTS

Nginx

MySQL5.7

PHP7.0

Redis

Memcached

Let'sEncryptSSL

安裝流程說明

安裝Nginx安裝php7安裝composer安裝MySQL5.7安裝Memcached安裝Redis安裝Let'sEncrypt

正式主機環境

219

Page 220: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝Nginx

更新系統套件

sudoapt-getupdate

安裝Nginx使用Ubuntu內建的nginx套件安裝,安裝完後預設的nginx設定檔是

/etc/nginx/sites-available/default,網站目錄會在

/usr/share/nginx/html

sudoapt-getinstallnginx

設定虛擬主機Virtualhost設定

編輯新的virtualhost設定檔案

在這裡通常我會用主機網域名稱當作他的檔案名稱,如果我有一個網域是

kejyun.dev,則我就會用 kejyun.dev當作虛擬主機設定檔名稱

sudovim/etc/nginx/sites-available/kejyun.dev

設定Listen的port

設定主機要使用哪一個port傾聽HTTP請求

listen80;

設定服務主機名稱

安裝Nginx

220

Page 221: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

設定你申請的網域名稱,nginx會以HTTPRequest的網域不同導向不同的

Virtualhost,所以一定要設定,以下以 kejyun.dev為例

server_namekejyun.dev;

設定網站根目錄路徑

我們將Laravel5的程式放在使用者 kejyun的家目錄下,而我們必須要將網站

路徑指定到Laravel專案下的 public目錄下才可以正常執行Laravel專案

root"/home/kejyun/laravel52/public";

設定Log路徑

設定當Request發生錯誤的時候,本Virtualhost要將Log存放在哪個檔案

error_log/var/log/nginx/kejyun.dev-error.logerror;

完整虛擬主機設定

設定檔中有包括 設定php檔案處理方式,在這邊我們可以先設定,等之後安裝完

php7時就可以直接使用

server{

#設定Listen的port

listen80;

#設定服務主機名稱

server_namekejyun.dev;

#設定網站根目錄路徑

root"/home/kejyun/laravel52/public";

#設定讀取檔案優先順序

indexindex.htmlindex.htmindex.php;

安裝Nginx

221

Page 222: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

#設定網站編碼

charsetutf-8;

location/{

try_files$uri$uri//index.php?$query_string;

}

location=/favicon.ico{access_logoff;log_not_foundoff;

}

location=/robots.txt{access_logoff;log_not_foundoff;

}

access_logoff;

#設定Log路徑

error_log/var/log/nginx/kejyun.dev-error.logerror;

sendfileoff;

client_max_body_size100m;

#設定php檔案處理方式

location~\.php${

fastcgi_split_path_info^(.+\.php)(/.+)$;

fastcgi_passunix:/var/run/php/php7.0-fpm.sock;

fastcgi_indexindex.php;

includefastcgi_params;

fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_scr

ipt_name;

fastcgi_intercept_errorsoff;

fastcgi_buffer_size16k;

fastcgi_buffers416k;

fastcgi_connect_timeout300;

fastcgi_send_timeout300;

fastcgi_read_timeout300;

}

location~/\.ht{

denyall;

}

安裝Nginx

222

Page 223: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

}

連結虛擬主機Virtualhost設定

Nginx虛擬主機設定主要是讀取 /etc/nginx/sites-enabled/目錄下的所有檔

案,如果要讓此設定檔案啟用,則必須要將原設定檔目錄 /etc/nginx/sites-available/的設定檔案使用軟連結連結過去

sudoln-s/etc/nginx/sites-available/kejyun.dev/etc/nginx/site

s-enabled/kejyun.dev

重新啟動nginx重新啟動nginx以讀取新的設定

sudoservicenginxrestart

這樣我們就完成了NginxServer的設定了!!

參考資料

HowToSetUpnginxVirtualHosts(ServerBlocks)onUbuntu12.04LTSphp-HowdoIchangetheNGINXuser?-ServerFault

安裝Nginx

223

Page 224: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝php7

加入php7套件資源庫

目前(2016/03)php7沒有在Ubuntu的預設套件庫中,所以若要使用php7的話,則必須要自行加入此套件庫,這樣我們才能在Ubuntu安裝php7

sudoadd-apt-repositoryppa:ondrej/php

更新套件資源庫

加入新的套件資源庫後,必須進行系統套件清單更新,才能夠讀取到新的套件設定

sudoapt-getupdate

安裝php7套件

php7.0-fpm:Nginx解析php檔案的工具

php7.0-mysql:連線mysqlphp7.0-mcrypt:Laravel加解密工具

其他套件是我在Laravel專案中需要的套件,可以依照自己需求去進行安裝

sudoapt-getinstallphp7.0-fpmphp7.0-mysqlphp7.0-mcryptphp7.

0-gdphp7.0-cliphp7.0-curlphp7.0-imap

設定php7.0-fpm若有需要變更任何php7.0-fpm的任何設定,可以修改下列設定檔案

sudovim/etc/php/7.0/fpm/pool.d/www.conf

安裝php7

224

Page 225: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

像是您如果想要把異動傾聽php的執行擁有者變更為 kejyun,您可以做以下的

設定

user=kejyun

group=kejyun

listen.owner=kejyun

listen.group=kejyun

listen.mode=0660

設定Nginxphp檔案處理方式

設定虛擬主機Virtualhost設定檔

sudovim/etc/nginx/sites-available/kejyun.dev

設定php檔案處理方式

安裝php7

225

Page 226: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

server{

#...

#設定php檔案處理方式

location~\.php${

fastcgi_split_path_info^(.+\.php)(/.+)$;

fastcgi_passunix:/var/run/php/php7.0-fpm.sock;

fastcgi_indexindex.php;

includefastcgi_params;

fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_scr

ipt_name;

fastcgi_intercept_errorsoff;

fastcgi_buffer_size16k;

fastcgi_buffers416k;

fastcgi_connect_timeout300;

fastcgi_send_timeout300;

fastcgi_read_timeout300;

}

#...

}

重新啟動php如果有異動任何php7.0-fpm的任何設定的話,必須要將php7.0-fpm服務重新啟

動,才能夠讀取到新的設定

sudoservicephp7.0-fpmrestart

這樣我們就完成php7的設定了!

參考資料

InstallPHP7onUbuntu14.04|EnricoZimuelkasparsd/php-7-debian:InstallPHP7onDebian/Ubuntu

安裝php7

226

Page 227: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Installingphp7-fpmwithphpredisextensiononUbuntu14.04

安裝php7

227

Page 228: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝composer

下載composer

curl-sShttps://getcomposer.org/installer|php

將composer執行檔移動到系統環境變數路徑

移動過去系統環境變數路徑中,這樣所有系統的使用者才都可以執行

sudomvcomposer.phar/usr/bin/composer

安裝所有Laravel專案套件

在我們將程式使用git推送到主機時,vendor下所有的套件都不會被推送到主機,

所以程式碼上去主機後,需要自己作安裝套件的動作

cd/home/kejyun/laravel52

composerinstall

這樣我們就完成了composer的安裝跟安裝Laravel專案套件了

參考資料

ComposerDownload

安裝composer

228

Page 229: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝MySQL5.7

設定MySQL5.7套件資源庫

目前(2016/03)MySQL5.7沒有在Ubuntu的預設套件庫中,所以若要使用

MySQL5.7的話,則必須要設定加入此套件庫,這樣我們才能在Ubuntu安裝

MySQL5.7

wgethttp://dev.mysql.com/get/mysql-apt-config_0.6.0-1_all.deb

sudodpkg-imysql-apt-config_0.6.0-1_all.deb

sudodpkg-reconfiguremysql-apt-config

設定使用MySQL當作預設安裝版本

安裝MySQL5.7

229

Page 230: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

設定完成點Apply完成設定

更新套件資源庫

加入新的套件資源庫後,必須進行系統套件清單更新,才能夠讀取到新的套件設定

安裝MySQL5.7

230

Page 231: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

sudoapt-getupdate

安裝MySQL

sudoapt-getinstallmysql-server-5.7

這樣就完成MySQL5.7的安裝了!

參考資料

MySQL::AQuickGuidetoUsingtheMySQLAPTRepositoryMySQL::DownloadMySQLAPTRepository

安裝MySQL5.7

231

Page 232: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝Memcached

安裝

直接安裝Ubuntu的Memcached套件

sudoapt-getinstallmemcached

sudoapt-getinstalllibmemcached-devlibmemcached11

設定php7Memcached套件

php7讀取Memcached的套件還是在開發版,沒辦法直接使用apt-get去完成安

裝,所以我們要自行下載開發版套件去進行編譯安裝

安裝php7套件編譯軟體

php7.0-dev是為了執行php7的phpize而安裝的

sudoapt-getinstallpkg-config

sudoapt-getinstallphp7.0-dev

下載phpMemcached套件

gitclonehttps://github.com/php-memcached-dev/php-memcached

切換開發版套件路徑

cdphp-memcached

gitcheckout-bphp7origin/php7

安裝Memcached

232

Page 233: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

編譯php7Memcached套件

phpize

./configure

make

maketest

sudomakeinstall

設定載入php7memcached套件

sudovim/etc/php/7.0/cli/conf.d/20-memcached.ini

sudovim/etc/php/7.0/fpm/conf.d/20-memcached.ini

在 20-memcached.ini檔案內設定

extension=memcached.so

設定檔分別要在 cli與 fpm兩個地方

cli指的是commandline的php執行擋

fpm指的是nginx解析php的解譯器

記得兩邊都要設定

重新啟動php7.0-fpm重新啟動之後,在網頁部分可以用 phpinfo();確認看看有沒有看到

Memcached套件

sudoservicephp7.0-fpmrestart

查詢安裝結果

查詢phpinfoMemcached安裝結果

安裝Memcached

233

Page 234: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

查詢phpcommandlineMemcached安裝結果

安裝Memcached

234

Page 235: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

$php-i|grepmemcached

/etc/php/7.0/cli/conf.d/20-memcached.ini,

memcached

memcachedsupport=>enabled

libmemcachedversion=>1.0.18

memcached.compression_factor=>1.3=>1.3

memcached.compression_threshold=>2000=>2000

memcached.compression_type=>fastlz=>fastlz

memcached.default_binary_protocol=>0=>0

memcached.default_connect_timeout=>0=>0

memcached.default_consistent_hash=>0=>0

memcached.serializer=>php=>php

memcached.sess_binary_protocol=>1=>1

memcached.sess_connect_timeout=>0=>0

memcached.sess_consistent_hash=>1=>1

memcached.sess_lock_expire=>0=>0

memcached.sess_lock_max_wait=>notset=>notset

memcached.sess_lock_retries=>5=>5

memcached.sess_lock_wait=>notset=>notset

memcached.sess_lock_wait_max=>2000=>2000

memcached.sess_lock_wait_min=>1000=>1000

memcached.sess_locking=>1=>1

memcached.sess_number_of_replicas=>0=>0

memcached.sess_persistent=>0=>0

memcached.sess_prefix=>memc.sess.=>memc.sess.

memcached.sess_randomize_replica_read=>0=>0

memcached.sess_remove_failed_servers=>0=>0

memcached.sess_sasl_password=>novalue=>novalue

memcached.sess_sasl_username=>novalue=>novalue

memcached.sess_server_failure_limit=>0=>0

memcached.store_retry_count=>2=>2

Registeredsavehandlers=>filesusermemcached

這樣我們就完成Memcached及在php7.0Memcached套件的安裝了

參考資料

安裝Memcached

235

Page 236: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

php-memcached-dev/php-memcached:memcachedextensionbasedonlibmemcachedlibrarykasparsd/php-7-debian:InstallPHP7onDebian/UbuntuServerPilot|HowtoInstallthePHPMemcacheExtensionInstallingPHP-7withMemcached-ServersforHackers

安裝Memcached

236

Page 237: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝Redis

設定Redis套件資源庫

sudoadd-apt-repositoryppa:chris-lea/redis-server

sudoapt-getupdate

安裝

sudoapt-getinstallredis-server

設定RedisRedis設定檔放在 /etc/redis/redis.conf

sudovim/etc/redis/redis.conf

設定設定檔

requirepass你的Redis連線密碼

#bind127.0.0.1不要限定只有本機才能連線

maxmemory-policynoeviction

appendonlyyes

appendfilenameredis-staging-ao.aof

重新啟動Redis

sudoserviceredis-serverrestart

這樣我們就完成Redis的安裝了!!

安裝Redis

237

Page 238: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

參考資料

HowToConfigureaRedisClusteronUbuntu14.04|DigitalOcean

安裝Redis

238

Page 239: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

安裝Let'sEncrypt為了推廣SSL憑證,Let'sEncrypt提供了免費的SSL憑證,可以讓你們的主機也

有SSL加密的保障

但是Let'sEncrypt提供的憑證有效期限每次只有 90天的效期,若過期之後需要

重新更新憑證方可繼續使用

下載

wgethttps://dl.eff.org/certbot-auto

chmoda+xcertbot-auto

安裝SSL憑證

在安裝SSL憑證時需要將您的Nginx主機服務關閉,才能進行憑證驗證

HowwouldyouliketoauthenticatewiththeACMECA?

----------------------------------------------------------------

---------------

1:Placefilesinwebrootdirectory(webroot)

2:Spinupatemporarywebserver(standalone)

----------------------------------------------------------------

---------------

Selecttheappropriatenumber[1-2]then[enter](press'c'toc

ancel):

用nginx選擇 standalone,若是apache則選擇用 webroot

輸入驗證SSL的網址

安裝Let'sEncrypt

239

Page 240: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Pleaseenterinyourdomainname(s)(commaand/orspaceseparate

d)(Enter'c'

tocancel):kejyun.dev

憑證檔案

安裝完的憑證會依照你申請的domain當作資料夾名稱放到

/etc/letsencrypt/live/目錄下

如果我同時申請了 kejyun.dev與 www.kejyun.dev,那麼憑證檔案就會分別

放在 /etc/letsencrypt/live/kejyun.dev/及/etc/letsencrypt/live/www.kejyun.dev/目錄下

憑證檔案分別會有4個

檔案名稱 說明

cert.pem 申請網域的憑證

chain.pem Let'sEncrypt的憑證

fullchain.pem cert.pem及chain.pem合併檔案

privkey.pem 申請網域的憑證密鑰

設定nginx使用SSL憑證

安裝Let'sEncrypt

240

Page 241: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

server{

#設定監聽的port為443

listen443ssl;

#設定憑證檔案

ssl_certificate/etc/letsencrypt/live/kejyun.dev/fullchain.p

em;

ssl_certificate_key/etc/letsencrypt/live/kejyun.dev/privkey

.pem;

ssl_protocolsTLSv1TLSv1.1TLSv1.2;

ssl_prefer_server_cipherson;

ssl_ciphers'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH

';

}

設定nginx80port自動轉址導向SSL443port

server{

listen80;

server_namekejyun.dev;

return301https://$host$request_uri;

}

重新啟動Nginx

sudoservicenginxrestart

設定完成後就可以看到自己的網站有做SSL加密了!

自動更新Let'sEncrypt憑證

自動更新憑證

安裝Let'sEncrypt

241

Page 242: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

./path/to/certbotrenew--pre-hook"servicenginxstop"--post-h

ook"servicenginxstart"

在更新憑證的時候,還是需要把webserver停掉,所以可以在 --pre-hook更新前關掉nginx,在 --post-hook更新後啟動nginx

加入Cronjob排程執行憑證更新

編輯crontab

sudocrontab-e

設定每個禮拜一的凌晨2:30進行一次憑證的檢查及更新

302**1./path/to/certbotrenew--pre-hook"servicenginxsto

p"--post-hook"servicenginxstart">>/var/log/letsencrypt-ren

ewal.log

這樣我們就有了一個半永久的SSL憑證了!!

參考資料

Certbot-NginxonUbuntu14.04Certbotdocumentation-Renewingcertificatesletsencrypt/letsencryptHowToSecureNginxwithLet'sEncryptonUbuntu14.04|DigitalOcean

安裝Let'sEncrypt

242

Page 243: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

其他常見問題

這裏會介紹一些在開發Laravel5遇到的常見問題

CalltoundefinedmethodgetCachedCompilePath()

其他常見問題

243

Page 244: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

CalltoundefinedmethodgetCachedCompilePath()我在使用Laravel5.0.x時,使用 composerupdate去更新目前的套件時,跳出

了這樣的訊息:

(PS:也有人在執行 phpartisanclear-compiled出現這樣的狀況)

PHPFatalerror:CalltoundefinedmethodIlluminate\Foundation\Application::getCachedCompilePath()

這個是因為Laravel5在執行時會把整個Framework編譯到

storage/framework/compiled.php,若這個檔案已產生,Laravel5在更新套

件時執行一些相關Laravel的功能時,會預設執行 compiled.php檔案中的類別

函式,而更新的檔案中有 getCachedCompilePath()這個方法,所以呼叫時

Laravel會在舊的 compiled.php找不到這個方法

解決方式

直接把 storage/framework/compiled.php刪除即可,Laravel5會自動重新產

生這個 compiled.php檔案!

參考資料

RuntimeExceptiononfreshinstall

CalltoundefinedmethodgetCachedCompilePath()

244

Page 245: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

變更專案目錄名稱導致View無法讀取

在想要變更原先Laravel5的專案目錄時,Laravel5會告訴你你沒辦法讀取到view的目錄,看了錯誤的訊息發現這個view的目錄是在原先舊專案的目錄名稱下

錯誤訊息長得像這樣:

InvalidArgumentExceptioninFileViewFinder.phpline137:

View[welcome]notfound.

這個原因是Laravel5會將設定檔作快取存下來到

bootstrap/cache/config.php目錄下面,而這個快取的檔案是原本舊專案的設

定,所以我們必須要清除這個快取,才可以讓Laravel5可以讀取到新的設定,這

時候我們可以在artisan下這些指令,清除原先專案的快取設定:

$phpartisanconfig:clear

$phpartisanview:clear

執行清除這些快取資料後,我們就可以正常的的獨到新專案目錄下的view資料

摟!

變更專案目錄名稱導致View無法讀取

245

Page 246: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

Laravel5.1目錄結構異動

從Laravel5.0升級到Laravel5.1時,app的目錄結構有做一些小異動,異動如下

app/Command=>app/Jobsapp/Handlers=>app/Listeners

根據官方說法,這樣的命名比較能夠識別出該目錄程式的作用是什麼

命令(Command)=>工作(Jobs)處理器(Handlers)=>事件傾聽器(Listeners)

在從5.0升級至5.1時,記得將這幾個目錄做重新命名喔~

參考資料

DirectoryChanges-LaracastReleaseNotes-laravel.tw

Laravel5.1目錄結構異動

246

Page 247: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

學習資源

KeJyun學習日誌:Laravel4

學習資源

247

Page 248: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

官方學習資源

FrameworkLaravel-ThePHPFrameworkForWebArtisansLumen-PHPMicro-FrameworkByLaravel

最新消息

LaravelNewsLaravelWeekly

文件(Document)Welcome!-LaravelPHPFrameworkLaravelwiki

APILaravel5APIDocumentation

套件清單

Packalyst::PackagesforLaravelPackagist-taglaravelLaravelCollectiveArsenal::Cartalyst

作者

TaylorOtwell|Twitter

官方

248

Page 249: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

官方

249

Page 253: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

工作

LaraJobsLaravelConsultantsandFreelancers+LaravelGurusWithLaravel-ThejobboardforLaravelprojectsanddevelopers

工作

253

Page 254: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

文件

LaravelALaravel5BoilerplateProjectLaravelBookWebdevelopment,design,andothernerdytopics!|DayleReesLaravel-簡潔、優雅的PHP開發框架(PHPWebFramework)。-Laravel中文網

Laravel中國社區

SimpleLaravel♥ScotchAwesomeLaravelCursodeLaravel5enespañoldesdecero|styde.netLaravelCollective

PHPAwesomePHPPHP-ToolsSitePointPHP–LearnPHP,MySQL,SOAP&more

設計模式

PSR繁體中文

安裝

HowtoSetupLaravel4-Tuts+CodeTutorial

指令函式

LaravelCheatSheetLaravel-Tricks.com

文件

254

Page 255: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

文件

255

Page 256: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

文章

部落格

MattStauffer.co

文件

AwesomeLaravel

除錯

DebuggingQueriesinLaravel

IoC神奇的服务容器

事件

StepbyStepGuidetoInstallingSocket.ioandBroadcastingEventswithLaravel5.1

文章

256

Page 257: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

套件

清單

Packalyst::PackagesforLaravelPackagist-taglaravelLaravelCollectiveArsenal::CartalystBuiltwithLaravel

時間

Carbon-AsimplePHPAPIextensionforDateTime.

編輯器

LaravelMarkdown

檔案

LaravelFlysystem

除錯

ThemissingtailcommandforLaravel5LaravelExceptionsLaravelDebugbar

條碼

SimpleQrCode

套件

257

Page 259: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

佈署程式

LaravelForgeForgeRecipes

Envoyer-ZeroDowntimePHPDeploymentLaravelhostinginthecloud

服務工具

259

Page 261: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

教學網站

英文

LaravelRecipesLaravel-Tricks.comWebdevelopment,design,andothernerdytopics!|DayleReesLaravelBookPHP:TheRightWay

中文

Laravel初體驗-實作Blog系統|LaravelDojoPHP:TheRightWay繁體中文

教學網站

261

Page 262: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

SublimeProWorkflowinLaravelandSublimeText-Tuts+CodeTutorial

編輯開發

262

Page 264: Laravel 5 學習筆記 · 2017-10-02 · Laravel 5 .env 檔案 在 Laravel 5 使用.env 檔案的方式跟 Laravel 4 有很大的不同,在 Laravel 5 中 就只有.env 與.env.example

案例

VDemocracy.tw-群眾募資‧群眾集資網站CrowdfundingPlatforminTaiwanBuiltwithlaravel.com

成功案例

264