學習筆記:《Laravel5.3》

過去做事情急,什么東西拿起來就用,不喜歡進行系統性的學習,造成在使用過程中的錯誤和低效,現在感覺自己耐心多了,用之前先系統的看一下文檔,再接著用。

Laravel 是“小丑魚”項目技術團隊共同確定下來的 PHP 程序框架,其近幾年的發展異常迅猛,已經蓋過了 YII 和 Symfony 的風頭。Laravel 的發起人 Taylor Otwell 在 Blog 中說自己的偶像是 Symfony 的創始人 Fabien Potencier:《PHP Developers Who Have Inspired Me》

Laravel 需要使用 composer 安裝,然后安裝 composer 本身又需要命令行支持https翻墻(后來知道其實下載也可以),https翻墻需要裝 icu4c,icu4c 需要安裝 brew,好在 ruby 已經系統安裝了,不然這個循環還會繼續下去。Laravel 最新版本對 PHP 版本的要求也比較高,要求 PHP >= 5.6.4,為此專門把本地 PHP 版本升了級。

安裝:

  1. 先安裝好 Composer
  2. 全局安裝 laravel/installer,一個 laravel 的安裝工具
    composer global require "laravel/installer"
  3. 初始一個 laravel 的項目,然后就可以開始運行了
    $HOME/.composer/vendor/bin new project_name
  4. 建立 .env 文件
    cp .env.example .env
  5. 設置 APP_KEY
    ./artisan key:generate
  6. 設置權限(正式環境不要這么操作)
    chmod -R 777 .

以下是閱讀官方文檔做的記錄,基于5.2版本:

目錄結構

這里解釋的非常清楚:https://laravel-china.org/docs/5.4/structure

在 Laravel 的開發過程中會用到許多不同類型的包管理工具,新生成很多的文件,這里簡單說明一下:

composer.json 是 composer 的配置文件
/vendor 目錄存放被 composer 安裝的文件

package.json 是 nodejs 的配置文件
/node_modules 目錄存放被 npm 安裝的文件

bower.json 是 bower 的配置文件
.bowerrc 文件中設置了被 bower 安裝的文件,一般設置為 /resources/assets/bower

gulpfile.js 是 gulp 的配置文件

框架核心結構

Service Container:
管理依賴注入(dependency injection)的容器工具,《嘮嘮依賴注入》 《嘮嘮Service Container》 兩篇文章里面解釋的比較清晰。

Service Providers:
包含了 Service Container、事件監聽(event listeners)、中間件(middleware)、路由(routes)的整套實現機制的類。
// Laravel Framework Service Providers... Illuminate\Auth\AuthServiceProvider::class, Illuminate\Broadcasting\BroadcastServiceProvider::class, Illuminate\Bus\BusServiceProvider::class, Illuminate\Cache\CacheServiceProvider::class, Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, Illuminate\Cookie\CookieServiceProvider::class, Illuminate\Database\DatabaseServiceProvider::class, Illuminate\Encryption\EncryptionServiceProvider::class, Illuminate\Filesystem\FilesystemServiceProvider::class, Illuminate\Foundation\Providers\FoundationServiceProvider::class, Illuminate\Hashing\HashServiceProvider::class, Illuminate\Mail\MailServiceProvider::class, Illuminate\Pagination\PaginationServiceProvider::class, Illuminate\Pipeline\PipelineServiceProvider::class, Illuminate\Queue\QueueServiceProvider::class, Illuminate\Redis\RedisServiceProvider::class, Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, Illuminate\Session\SessionServiceProvider::class, Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, Illuminate\View\ViewServiceProvider::class, // Application Service Providers... App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class,

HTTP層:

Routing
Laravel 非常尊重 CRUD,所以可以在表單里面添加:
<input type="hidden" name="_method" value="PUT">

路由中傳遞的 id 值可以根據名字直接返回帶有了數據字段的 model(感覺這個有點太過于智能了):
Route::get('api/users/{user}', function (App\User $user) { return $user->email; });

Laravel 5.2 開始取消了 Route::controller() 這個方法,不能再方便得使用:

Route::controller('user', 'UserController');

官方文檔中的解釋是:

The following features are deprecated in 5.2 and will be removed in the 5.3 release in June 2016:
Implicit controller routes using Route::controller
have been deprecated. Please use explicit route registration in your routes file. This will likely be extracted into a package.

可能是為了讓路由的定義更加的清晰化

Middleware
類似于 Symfony 的 FIlter,屬于一個請求從 HTTP 層 進入到 APP 層,以及從 APP 層出去到 HTTP 層過程中可以添加處理的部分。

CSRF Protection
在表單中添加:
{{ csrf_field() }}
或者
<input type="hidden" name="_token" value="{{ csrf_token() }}">
然后 VerifyCsrfToken 這個中間件便會自動處理 CSRF,對于 AJAX 請求的保護,則可以在 meta 中插入:
<meta name="csrf-token" content="{{ csrf_token() }}">
再配合一段 JS 的程序來自動實現:
$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } });

Controllers
如果路由中沒有指定某個具體的 Controller 方法,則指向一下叫做 __envoke() 的方法:
public function __invoke($id) { return view('user.profile', ['user' => User::findOrFail($id)]); }

中間件經常在 Controller 的構造方法中被指定:
public function __construct() { $this->middleware('auth'); $this->middleware('log')->only('index'); $this->middleware('subscribed')->except('store'); }

Controller 中有一套封裝好的 CRUD,叫做 Resource Routes,感覺比較重,不大敢用。

Controller 方法的第一個參數支持 Service Container,還是蠻有意思的,構造函數 __construct() 的第一個參數也支持,使用 Service Container 的方式是利用的 PHP 最新版本的新語法,在實踐中看看會出現怎么樣的運用機會,這種運用反射機制和 type-hint 結合而出現的使用方式,真的是喪心病狂......

Requests & Responses
Laravel 的 Requests & Responses 遵循著 PSR-7 standard 的標準,對上傳和下載也做了相應的封裝,東西比較多,這個具體使用的時候查文檔

Validation
有一個叫做 bail 的參數可以幫助只返回首個驗證不通過的信息:
$this->validate($request, [ 'title' => 'bail|required|unique:posts|max:255', 'body' => 'required', ]);

View 和 Template

View
View 可以進行判斷:
if (View::exists('emails.customer')) { // }

如果你希望每個 Controller 中都可以共享一些值,也可以有方法可以實現,但是會有人記得用嗎?
public function boot() { View::share('key', 'value'); }

View Composers
如果你希望不同的 Controller 中的 View 可以共享一些數據,那么就可以引入 View Composers 的機制,不過個人感覺實踐中沒有特別的必要使用這個機制,太私人的業務邏輯歸屬會讓代碼不易維護

Blade Templates
Laravel 提供的一套輕量級的模板引擎,未來的架構會越來越趨向于前后端的分離,加之 PHP 語言本身具有較強的模板特性,內置一套輕量級的模板引擎是非常聰明的解決方案。

涉及前端部分

Laravel 結合使用了 Bootstrap 和 Vue 作為前端解決方案,然后提供了一個叫做 Laravel Elixir 的工具來進行前端 JS 和 CSS 的編譯,同時這個編譯過程支持 Less、Sass、Stylus、Plain CSS 這些 CSS 的同時編譯,也支持 Webpack、Rollup、JavaScript 的結合編譯。Laravel Elixir 本身是對 Gulp 的封裝,而 Gulp 是基于 node.js 他們家的 npm,所以這個解決方案的安裝過程也是喪心病狂,一路上 node.js、npm、Gulp、Laravel Elixir 安裝完,等到真正使用的時候不知道還會遇到多少問題,成本啊!

因為 Laravel Elixir 基于 Gulp,所以在編譯的時候可以直接用 Gulp 的命令行工具:
gulp // 編譯命令 gulp watch // 只要 CSS 或者 JS 文件修改過了,就會自動編譯

余下的就是看 Bootstrap 和 Vue 的文檔了

涉及安全部分

Laravel 提供了一個 Auth 靜態類存放權限安全相關的代碼,提供了 Gate 靜態類處理認證相關的內容

Authentication
Laravel 對 Authentication 做了全局統籌,不僅僅注冊好了路由,而且運行 php artisan make:auth 可以看到一個腳手架搭建好的小系統,方便學習:
// Authentication Routes... $this->get('login', 'Auth\AuthController@showLoginForm'); $this->post('login', 'Auth\AuthController@login'); $this->get('logout', 'Auth\AuthController@logout'); // Registration Routes... $this->get('register', 'Auth\AuthController@showRegistrationForm'); $this->post('register', 'Auth\AuthController@register'); // Password Reset Routes... $this->get('password/reset/{token?}', 'Auth\PasswordController@showResetForm'); $this->post('password/email', 'Auth\PasswordController@sendResetLinkEmail'); $this->post('password/reset', 'Auth\PasswordController@reset');

在數據安全方面,Laravel 提供了一套稱為 Policy 的解決機制,Policy 機制可以在 Methods、Models、Filters、Authorizing Actions、Middleware、Controller Helpers、Blade Templates中進行使用

文檔中提到了涉及 Vue 的一套 API Authentication 解決方案,因為對 Vue 還不夠了解,這塊先放過,等學會了 Vue 以后再回過頭來看這塊的內容

Laravel 提供了一個 encrypt helper 協助加密保護,使用 OpenSSL 和 AES-256-CBC cipher,反正都封裝好了,只要用就是了

Laravel 提供了一個 Hash 靜態類產生和匹配用戶密碼,也是封裝好了,用就可以

一些零碎知識

Event Broadcasting
Laravel 提供了很詳細的通訊解決方案,支持 Pusher、Redis、Socket.IO、Log 等等的驅動方案,提供了一個叫做 Laravel Echo 的 Javascript 工具包在前端部分進行支持,這塊文檔詳細的提供了一個示例,等用到的時候可以參考

Cache
提供了一個 Cache 靜態類操作緩存,支持 Memcached、Redis、文件、數據庫緩存

Events & Listeners
這個應該是來源于 Symfony 的一套程序監聽機制,但是感覺在大型系統中這樣的方式會把業務邏輯搞的比較混亂,所以一直沒有大規模使用過,但是前面 Event Broadcasting 的文檔中強調了其重要性,可能在通訊解決方案中這樣的監聽機制是需要的,具體在使用的時候去理解

文件系統使用的 Flysystem,Storage 這個靜態類封裝了文件管理的全部功能,遠程(亞馬遜A3、Rackspace等)、本地等等,各種文件相關的操作需求應有盡有

郵件機制使用的是 SwiftMailer,SwiftMailer 本身是對 SMTP, Mailgun, SparkPost, Amazon SES, PHP's mail function, sendmail 等的封裝,出自 SensioLabs,所以品質有保障

Notifications
消息機制是指給用戶發提醒郵件、SMS信息、Slack、網頁上的提醒信息等等,使用的 Notification 靜態類進行了所有相關功能的封裝

Queues
隊列機制 Laravel 也提供了詳細的支持,包括 Beanstalkd, Amazon SQS, Redis, 本地數據庫等等

這些零碎的知識,都是對一些較小應用場景的功能封裝,對于這樣的封裝,最怕的就是不完善然后用戶會跳過封裝直接用相關的接口,維護起來也比較困難,所以無論過去封裝成 PHP 組件,或者是成為某些框架的插件,都很難取得成功,更別提像 Laravel 這樣包含在框架的核心代碼里面,Laravel 能這么做,我想有一個原因是 composer 的出現讓代碼更高效的復用成為一種可能,即時是 Laravel 的核心庫,也可以方便的和別的項目共享

數據庫相關

Query Builder:Laravel 提供的一套數據庫操作方法,基于 DB 這個 Facade 靜態類,這里有詳細的關于這個方法的接口說明:
https://laravel.com/api/5.3/Illuminate/Database/Query/Builder.html

Migrations:等到項目的業務邏輯到達一定的規模,會有 Migrations 方面的需求,在 Laravel 中體現為 Schema 這個 Facade 靜態類

Eloquent ORM:Laravel 提供的一套 ActiveRecord 實現,有一些很有趣的機制:

Collections:提供了一整套強大的方法幫助檢索返回數據的處理,很多的有用方法都支持 Lamda 表達式作為參數,非常有效的提升了代碼的可讀性。

Accessors & Mutators:在 get 和 set 數據的時候分別加上了一層回調處理,對業務邏輯的分離非常有幫助。

Date Mutators:實現一個 Carbon 的實例:
https://github.com/briannesbitt/Carbon
將類屬性 $dates 中設定的相關字段自動轉換成一個 Carbon 對象,可以調用所有 Carbon 中的相關方法。

Attribute Casting:使用類屬性 $casts 可以方便得對 get 到的字段數據進行屬性設定,可以進行一層類型轉換,可以設置的值有:integer, real, float, double, string, boolean, object, array, collection, date, datetime, timestamp

Serialization:幫助查詢數據在格式處理時候的兩個方法 toArray() 和 toJson(),兩個協調相應字段顯示與否的類屬性 $hidden 和 $visible,以及額外增加顯示信息的 $appends 類屬性

pivot:在處理 ManyToMany 關系的時候,對于中間表專門提供的一個屬性和方法協助方便處理

Mass Assignment:提供了防止字段被錯誤插入數據的兩個屬性 $fillable 和 $guarded

在插入數據的時候 firstOrCreate(), firstOrNew() 在提供一些列的查詢條件后沒有任何匹配結果,則直接進行插入

findOrFail(), firstOrFail() 如果查詢沒有任何的結果,就拋出一個 ModelNotFoundException

除了 One To One、One To Many、Many To Many 以外,laravel還提供了 Has Many Through(遠層一對多關聯:跨一個表進行一對多關聯)、Polymorphic Relations(多態關聯:某個字段多態關聯不同的外表)、Many To Many Polymorphic Relations(多態的多對多關聯)

Eager Loading:關聯查詢的時候提高效率的機制,使用 with() 方法實現,傳 Lamda 表達式的方法也是很贊:
$users = App\User::with(['posts' => function ($query) { $query->where('title', 'like', '%first%'); }])->get();

Soft Deleting:Laravel 提供了整套的 Soft Deleting 解決方案,當然你不希望一個數據真正的從數據庫刪除的時候

Query Scopes:查詢作用域,將某些查詢的條件綁定到某個 Model 上,比如 Soft Deleting 的時候,或者丟棄歷史數據的時候,Query Scopes 就非常能幫得上

chunk:當 crontab 操作的時候遇到30秒時間限制的時候,就可以用 Laravel 提供的這個 chunk() 方法來解決:
http://laraveldaily.com/process-big-db-table-with-chunk-method/

aggregate methods:count, max, min, avg, and sum,對查詢結構數據進行操作的簡單方法

Seeding:一套偽造測試數據的方法,做單元測試之類的時候,會非常的有用

附件

Facades:一套靜態類的基類接口,提供了 Laravel 整套的靜態類標準解決方案,便于靜態類全局使用
'App' => Illuminate\Support\Facades\App::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, 'Auth' => Illuminate\Support\Facades\Auth::class, 'Blade' => Illuminate\Support\Facades\Blade::class, 'Cache' => Illuminate\Support\Facades\Cache::class, 'Config' => Illuminate\Support\Facades\Config::class, 'Cookie' => Illuminate\Support\Facades\Cookie::class, 'Crypt' => Illuminate\Support\Facades\Crypt::class, 'DB' => Illuminate\Support\Facades\DB::class, 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 'Event' => Illuminate\Support\Facades\Event::class, 'File' => Illuminate\Support\Facades\File::class, 'Gate' => Illuminate\Support\Facades\Gate::class, 'Hash' => Illuminate\Support\Facades\Hash::class, 'Lang' => Illuminate\Support\Facades\Lang::class, 'Log' => Illuminate\Support\Facades\Log::class, 'Mail' => Illuminate\Support\Facades\Mail::class, 'Password' => Illuminate\Support\Facades\Password::class, 'Queue' => Illuminate\Support\Facades\Queue::class, 'Redirect' => Illuminate\Support\Facades\Redirect::class, 'Redis' => Illuminate\Support\Facades\Redis::class, 'Request' => Illuminate\Support\Facades\Request::class, 'Response' => Illuminate\Support\Facades\Response::class, 'Route' => Illuminate\Support\Facades\Route::class, 'Schema' => Illuminate\Support\Facades\Schema::class, 'Session' => Illuminate\Support\Facades\Session::class, 'Storage' => Illuminate\Support\Facades\Storage::class, 'URL' => Illuminate\Support\Facades\URL::class, 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class

Contracts:前面的 Facades 是系統提供的一套靜態類,但是如果你希望可以自定義這些功能的話,可以用 Contracts 來實現,Contracts 的作用是為你提供好了解耦的機制,方便自定義的時候直接套用,也是因為 Contracts 的存在,可以方便的找到很多現成的代碼可以直接使用(防止第三方提供的代碼具有耦合性)

Contract 對應的 Facade
Illuminate\Contracts\Auth\Factory Auth
Illuminate\Contracts\Auth\PasswordBroker Password
Illuminate\Contracts\Bus\Dispatcher Bus
Illuminate\Contracts\Broadcasting\Broadcaster
Illuminate\Contracts\Cache\Repository Cache
Illuminate\Contracts\Cache\Factory Cache::driver()
Illuminate\Contracts\Config\Repository Config
Illuminate\Contracts\Container\Container App
Illuminate\Contracts\Cookie\Factory Cookie
Illuminate\Contracts\Cookie\QueueingFactory Cookie::queue()
Illuminate\Contracts\Encryption\Encrypter Crypt
Illuminate\Contracts\Events\Dispatcher Event
Illuminate\Contracts\Filesystem\Cloud
Illuminate\Contracts\Filesystem\Factory File
Illuminate\Contracts\Filesystem\Filesystem File
Illuminate\Contracts\Foundation\Application App
Illuminate\Contracts\Hashing\Hasher Hash
Illuminate\Contracts\Logging\Log Log
Illuminate\Contracts\Mail\MailQueue Mail::queue()
Illuminate\Contracts\Mail\Mailer Mail
Illuminate\Contracts\Queue\Factory Queue::driver()
Illuminate\Contracts\Queue\Queue Queue
Illuminate\Contracts\Redis\Database Redis
Illuminate\Contracts\Routing\Registrar Route
Illuminate\Contracts\Routing\ResponseFactory Response
Illuminate\Contracts\Routing\UrlGenerator URL
Illuminate\Contracts\Support\Arrayable
Illuminate\Contracts\Support\Jsonable
Illuminate\Contracts\Support\Renderable
Illuminate\Contracts\Validation\Factory Validator::make()
Illuminate\Contracts\Validation\Validator
Illuminate\Contracts\View\Factory View::make()
Illuminate\Contracts\View\View -

Collections:對數組操作進行封裝的一套方法,保留了 PHP 數組操作的巨大有點,同時又滿足了方法的調用需求,不羅列了,可以直接看文檔

Helper Functions:70-80個左右的 Laravel 封裝的函數,又一次對數組、字符串、Url等等的操作進行了擴展,看來 PHP 語言的函數總量,還是達不到 Laravel 的需求,在使用的過程中可以根據需求自己挖礦,不羅列了,可以直接看文檔

使用備忘(細節)

Cookie:

Cookie::queue('userId', 3, 1440);
echo Cookie::get('userId');
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容

  • 先說幾句廢話,調和氣氛。事情的起由來自客戶需求頻繁變更,偉大的師傅決定橫刀立馬的改革使用新的框架(created ...
    wsdadan閱讀 3,073評論 0 12
  • 校園失物招領平臺開發 ——基于laravel框架構建最小內容管理系統 摘要 ? 針對目前大學校園人口密度大、人群活...
    藍蓮花xzsky閱讀 6,213評論 8 54
  • 原文鏈接 必備品 文檔:Documentation API:API Reference 視頻:Laracasts ...
    layjoy閱讀 8,619評論 0 121
  • 最近在和同學參與一個創業項目,用到了laravel,仔細研究了一下,發現laravel封裝了很多開箱即用的方法,通...
    MakingChoice閱讀 3,320評論 0 0
  • 已經很晚了,婆婆收拾收拾去睡了;已經很晚了,小丫頭摟著我的脖子被哄睡了;已經很晚了,老公才從外邊回來,很疲憊的樣子...
    火紅的石榴暖暖閱讀 197評論 0 0