Jimmy's Code

Want to be a better Coder
^

Laravel 建置與執行及相關筆記

2019-08-31

Laravel 建置與執行

1.為甚麼要使用Laravel

  • 為甚麼要使用框架
    • Laravel
    • Lumen
    • Slim
  • 歷史
    • Ruby on rails
    • CodeIgniter
    • Laravel
  • Laravel 的設計哲學
    • 使用與光有關的字眼
      • illuminate 照亮
      • spark 火花
    • 提升開發速度和開發者的幸福
  • Laravel 社群

2.設置Laravel 開發環境與介紹

  • 系統需求
  • Composer
  • 本地開發環境
    • Laravel Valet (mac)
    • Laravel Homestead
      • vagrant up
      • vagrant suspend
      • vagrant halt
      • vagrant destroy
      • vagrant provision
  • laravel new & composer create-project
  • Laravel 的目錄結構

3.路由與控制器

Route::get('/',function(){
    return 'Hello World';
    //return view('welcome'); #resources/views/welcome.blade.php
})

#可用正規表達式限制路由
Route::get('/{name}',function(){
    return 'Hello World';
})->where('name','[0-9]+')
  • 路由動詞
    • Get 觀看
    • Post 新增
    • Put/Patch 更新
    • Delete 刪除
    • any
      php= Route::any('/',function(){})
    • match
      php= Route::match(['get','post'],'/',function(){})
  • 中介層 middleware
    • 在進入controller 之前 過濾request 的條件和身分等
    • 有controller construct 和 route 定義兩種方式宣告
  • 使用視圖組件讓所有視圖共用變數
    view()->share('variable','variable);
  • Controller
方法名稱動詞URL
indexgettasks
showgettasks/{task}
creategettasks/create
storeposttasks
editgettasks/{task}/edit
updatepost (put or patch)tasks/{task}
destroypost (delete)tasks/{task}
  • 路由模型綁定

定義一個特定的參數名稱 如{task} 來指示路由解析器,他應該用那個的id 來尋找而不是傳統將id 傳入

  • 顯式與隱式
  • 路由快取
    壓榨載入時間的每毫秒
php artisan route:cache
php artisan route:clear
  • 方法欺騙: method_field() 或者 input-name:_method
  • CSRF
  • 轉址 redirect
  • 中止請求
    • abort(403)
    • abort_if(condition,403)
    • abort_unless(condition,403)
  • 回應 response
    • response()->make() 建立一個http 回應
    • response()->json()
    • response()->download()

4.Blade 模板

 @if 和 @endif
 {{ }}
 @unless @endunless
 @for @foreach @while
 @forelse ==>@foreach 在迭代的物件是空的時可寫應變機制
 @section/@show @yield
 @include 
 @extends
  • 自動blade 指令
  • 全域共用變數
# in App\Providers\AppServiceProvider.php
public function boot()
{
    ...
    view()->share('posts',Post::recent());
}

view()->composer('partials.sidebar',function($view){
    $view->with('posts',Post::recent());
})
#自訂指令
//AppServiceProvider
public function boot()
{
    Blade::directive('ifGuest',function(){
        return "<?php if (auth()->guest()): ?>"
    });
}

5.前端套件

  • laravel-mix

6.收集與處理用戶資料

  • Request
    • all()
    • except() or only()
    • has() or exist()
    • input() 提供第二個參數是預設值
    • json()
    • 路由資料
      • segment()
    • 上傳檔案
      • $request->hasfile() and $request->file()
      • guessExtension
      • getMimeType
      • move()
      • getClientOriginalName()
      • getClientOriginalExtension()
      • isValid()
      • …..其他(p.102)
  • 驗證
    • \$this->validate($request,[rules]);
    • 表單請求 php artisan make:request Arequest
      • authorize()
      • rule / message
    • withErrors 顯示錯誤訊息
    • 規則可以看文件
  • Eloquent 模型的大量賦值
    • $fillable in model
  • {{ … }} v.s {!! … !!}

7.Artisan 與 Tinker

php artisan make:command {action} 

php artisan make:model [name] -m -r ////可以同時生成model 和migration 和controller

8.資料庫與Eloquent

  • Laravel 的 ActiveRecord ORM
  • config/database.php
  • migration 資料庫遷移
    • 系統會依據日期執行他的up/down方法
    • 定義 migration
      • up() 作他的migration
      • down() 恢復他
    • 建立 migration
      • php artisan make:migration create_users_table
      • php artisan make:migration add_votes_to_users_table --table=users php artisan make:migration create_users_table --create=users
    • 撰寫 migration 請參考文件
    • seeder指令
      • php artisan migrate --seed
      • php artisan migrate:refresh --seed
      • php artisan db:seed
      • php artisan db:seed --class=VotesTableSeeder #分別執行
      • php artisan make:seeder ContactsTableSeeder
  • 查詢產生器
    • 任何一種資料庫的功能核心都是查詢產生器
    • 原生DB 靜態介面寫法 php= DB::statement('drop table users') DB::select('select * from student where id=?',[1]) $users=DB::table('users')->get() #....其他如join where insert 等 略
      • 限制方法
        • select()
        • where()
        • orwhere()
        • whereBetween()
        • whereIn()
        • whereNull() whereNotNull()
        • whereRaw()
        • whereExists()
        • distinct
      • 修改方法
        • orderBy groupbY having() havingRaw()
        • skip() take()
        • latest() oldest()
        • inRandomOrder() 隨機排序結果
      • 結束回傳方法
        • get()
        • first() firstOrFail()
        • value() 拉出某個欄位
        • count()
        • min() max()
        • sum() avg()
      • 聯集與聯結
        • join()
        • union()
      • 增加 更新 刪除
        • insert()
        • update()
        • delete()
      • json 的操作
        如果你的資料有json 格式可以這樣寫
        //查詢
        DB:table(‘users’)->where(‘options->isAdmin’,true)->get()
        //更新
        DB:table(‘users’)->update([‘options->isAdmin’,true])
  • Eloquent 模型請參考文件

Eloquent 雖有獨有all 方法,但本書建議不要使用~

  • Eloquent 模型序列化
    • 將某種複雜的東西轉換成字串 toArray() toJson()
    • https://laravel.com/docs/5.5/eloquent-serialization

9.用戶身分驗證與授權

  • php artisan make:auth
  • https://laravel.com/docs/5.5/authentication
  • 守衛
    • config/auth.php
    • auth()->guard(‘user’)->user()
  • 授權 ACL
    • in blade: can cannot allows denies
    • can
    • gete
    • policy

10.請求與回應

  • 請求生命週期
    • 每一個請求都會轉成 Illuminate Request 物件 經過middleware 過濾請求後進入controller 處理好後就產生 Illuminate Response
    • request
    • resonse
    • middleware
      • 每一個請求都會經過每一個middleware 最後進入應用程式,之後產生的回應會經過middleware回到用戶

11.容器

  • 相依注入
    • 每一個類別的相依關係都是從外面住入的 而不是在類別中實例化的
  • 控制反轉
  • app() 全域輔助函式
  • 將類別綁定容器
    • 告知容器如果有人要求一個Logger 實例,則執行這段程式

12.測試

  • Laravel 內建 PHPUnit、Behat、Mockery、Faker 等
  • 單元測試
    • 測試對象是小型、相對獨立的單位,通常是一個類別或方法
  • 整合測試
    • 測試各個單位合作及傳遞訊息的方式
  • 應用測試
    • 驗收或功能測試,測試整個應用程式的行為
  • 在根目錄執行 .\vendor\bin\phpunit
  • 文件
  • php artisan make:test GreetTest
    • 在feature 資料夾裡面增加一個GreetTest.php 繼承TestCase
    • phpunit 會跑feature 和unit 裡的每一個測試
    • $this->visit(url)
    • $this->call(method,url,params,cookies,file,server,content)
    • $this->get/post/put/patch/delete
    • $this->json
    • $this->followRedirects
  • 各種的asset 測試方法
  • 自我練習
  • Browser Tests (Laravel Dusk)
  • 測試特徵
    • withoutMiddleware
    • databasemigrations
    • databasetransactions

13.編寫API

  • 類REST JSON API 基礎
    • 一種用來建構API 的架構格式
    • URL 可以獨特的表示一種資源
    • 使用HTTP動詞來和資源互動
  • CRUD
  • Laravel Passport 作 API 身分驗證
    • https://laravel.com/docs/5.5/passport

composer require laravel/passport

在config/app.php providers 加入 Laravel\PassportServiceProvider::class

php artisan passport:install

將HasApiTokens 的trait 加入 App\user

  • http://www.itread01.com/content/1496308818.html’
  • http://codingweb.tw/2016/12/23/laravel-5-3-api-%E8%AA%8D%E8%AD%89-authentication-passport/

14.儲存與取出

  • 本地與雲端檔案管理器
  • config/filesystems.php
  • storage_path() 輔助函式

php artisan storage:link

  • 使用Storage 靜態介面
  • Storage::disk(‘s3’)->get(‘file.jpg’)
    • get()
    • put()
    • putFile(‘dir’,$file)
    • exists()
    • copy(old,new)
    • move(old,new)
    • prepend() 在前面加
    • append() 在後面加
    • delete()
    • deleteDirectory()
    • size()
    • lastModified
    • files(dir)
    • allFiles(dir) +子目錄內的
    • directories()
    • allDirectories()
  • Session
    • Laravel 的session 管理器支援:檔案、cookie、資料庫、Memcached、Redis
#取出
session()->get('key')
session('key')
#放入
session()->put('key','value')
session(['key','value'])
#session 是陣列時
session->push(key,value)
#全部
session()->all()
#移除
session()->forget(key) #移除一個
session()->flush() #移除每一個
  • Flash session 儲存
    • 只想要在下一個網頁載入時抹除它
session()->flash(key,value)

session()->reflash() / session()->keep(key)
#讓前一個網頁的flash session 繼續使用
  • 快取
  • 快取中的資料是為每一個應用程式儲存的;而session 中的資料是為每一個用戶儲存的
  • config/cache.php
  • https://laravel.com/docs/5.5/cache
    • cache()->get(key,fallbackvalue)
    • cache()->pull(key,fallbackvalue)
    • cache()->put(key,value,minutesOrExpiration)
    • cache()->add(key,value)
    • cache()->forever(key,value)
    • cache()->has()
    • cache()->remember(key,minutes,closure) / cache()->rememberForever(key,closure)
    • cache()->increment(key,amount) / cache()->decrement(key,amount)
    • cache()->forget() / cache()->flush()
  • Cookie
  • https://laravel.com/docs/5.5/requests#cookies
  • Laravel Scout 作全文搜尋
    • 可為Eloquent 模型加入全文搜尋
    • Algolia預設驅動程式
    • 要改成elasticsearch 請另外找辦法

composer require laravel/scout
加到config/app.php
php artisan vendor:publish
composer require algolia/algoliasearch-client-php

在模型內 加入Laravel\Scout\Searchable
toSearchableArray()
searchableAs()

Revie::search('Llew')->get();

config/scout.php 把queue 設為true

15.郵件與通知

  • 郵件
  • https://laravel.com/docs/5.5/mail
  • config/mail.php
    • classic
    • mailable
  • 傳統郵件 classic
Mail::send(view,data,closure)
# closure 裡面有寄件者 收件者 等等
  • Mailable

php artisan make:mail Assignment
會創造一個 Assignment class (extend mailable)
build 方法裡面 return $this->view(‘view.name’)

本地開發

  • log驅動程式
  • Mailtrap.io
  • Universal to
  • 通知 Notification
  • php artisan make:notification WorkoutAvailable

16.佇列、工作、事件、廣播與排程器

  • 佇列可以將昂貴或緩慢的程序移出任何同步呼叫 ex.傳送郵件
  • config/queue.php

php artisan make:job CrunchReports
dispatch(job)->onQueue(‘high’)
php artisan queue:work

  • 事件
  • event()

php artisan make:event UserSubscribed

  • 監聽事件
    • php artisan make:listener jobname –event=UserSubscribed
  • 將事件廣播到WebSocket 與 Laravel Echo
  • 排程器
    • cron job in linux
    • app\console\kernel.php
    • $schedule

php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1 (in linux:將唯一的cron 項目啟動)

17.輔助函式與集合

  • https://laravel.com/docs/5.5/helpers
  • https://laravel.com/docs/5.5/collections

Laravel 的中大型專案架構

1.Model : 僅當成 Eloquent class。
2.Repository : 輔助 model,處理資料庫邏輯,然後注入到 service。
3.Service : 輔助 controller,處理商業邏輯,然後注入到 controller。
4.Controller : 接收 HTTP request,調用其他 service。
5.Presenter : 處理顯示邏輯,然後注入到 view。
6.View : 使用 blade 將資料 binding 到 HTML。
7.Transformer :轉換顯示欄位(API)
8.Formatter: 格式的統一顯示格式(API)
9.Foundation: 獨立掛載功能

總結

  • 職責單一: 就是說每次修改都會有個地方變動而已,所以每個類別都只會有一種改變的理由
  • 跟夥伴們取得一個共識:讓他們知道這樣的設計和方法可以帶來時麼樣的好處,建立一個良好的溝通

Laravel 外掛整理

Debug

開發相關

驗證

權限

管理後台

  • 管理後台平台外掛 類似Django 自帶後台?
    • http://labs.infyom.com/laravelgenerator/
    • LARAVEL-ADMIN
      • http://www.ctolib.com/article/comments/21786
      • http://laravel-admin.org/

Ruby on rail Scaffold

  • Laravel 類似Ruby on rail 的scaffole 指令
    • https://github.com/appzcoder/crud-generator/

Office

  • laravel excel
  • laravel word

Notification 通知

  • laravel flash

Log

  • laravel5 log viewer

開發

  • laravelcollective HTML

PDF

  • laravel dom-pdf

資料庫備份

  • laravel-backup

Datatable

其它

Laravel 的Carbon 小技巧

1.本地化

# app/Providers/AppServiceProvider.php
public function boot()
{
    \Carbon\Carbon::setLocale('zh');
}
#$article->created_at->diffForHumans(); # 1 年前

2.七個小技巧
https://9iphp.com/web/php/less-known-useful-carbon-functions.html

  • isX :True/False
<?php
$dt->isWeekday();
$dt->isWeekend();
$dt->isYesterday();
$dt->isToday();
$dt->isTomorrow();
$dt->isFuture();
$dt->isPast();
$dt->isLeapYear();
$dt->isSameDay(Carbon::now());
  • isBirthday
<?php
$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));
  • StartOfX 和 EndOfX 列表
<?php
$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->startOfDay();     // 2012-01-31 00:00:00
echo $dt->endOfDay();       // 2012-01-31 23:59:59
echo $dt->startOfMonth();   // 2012-01-01 00:00:00
echo $dt->endOfMonth();     // 2012-01-31 23:59:59
echo $dt->startOfYear();    // 2012-01-01 00:00:00
echo $dt->endOfYear();      // 2012-12-31 23:59:59
echo $dt->startOfDecade();  // 2010-01-01 00:00:00
echo $dt->endOfDecade();    // 2019-12-31 23:59:59
echo $dt->startOfCentury(); // 2000-01-01 00:00:00
echo $dt->endOfCentury();   // 2099-12-31 23:59:59
echo $dt->startOfWeek();    // 2012-01-30 00:00:00
echo $dt->endOfWeek();      // 2012-02-05 23:59:59
  • Today, Tomorrow, Yesterday
<?php
$today = Carbon::today();  // assuming 2016-06-24
echo $today;                   // 2016-06-24 00:00:00
$tomorrow = Carbon::tomorrow();
echo $tomorrow;                      // 2016-06-25 00:00:00
$yesterday = Carbon::yesterday();
echo $yesterday;                   // 2016-06-23 00:00:00
  • DiffForHumans + 本地化
<?php
echo Carbon::now()->subDays(5)->diffForHumans()//5daysago
Carbon::setLocale('zh');
echo Carbon::now()->addYear()->diffForHumans(); //一年前
  • 改变 now() 为任意你想要的时间
<?php
$knownDate = Carbon::create(2001, 5, 21, 12);//建测试日期
Carbon::setTestNow($knownDate);    // set the mock 
echo Carbon::now();      // 2001-05-21 12:00:00
  • 星期常量
<?php
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)

Laravel 的 Eloquent 小技巧

1.同時產生migration 和model

php artisan make:model Post -m
2.scope

class Post extends Model
{
    public function scopePublished($query)
    {
        return $query->where('is_published', true);
    }
}
#Post::published()->get();
#相當於 Post::where('is_published', true)->get();

3.Accessors(访问器)
4.动态方法名称

// Post::where('published', 1)->get();
Post::wherePublished(1)->get();

// Post::where('category', null)->get();
Post::whereNull('category')->get();

// Post::where('category', '!=', null)->get();
Post::whereNotNull('category')->get();

5.扩展访问器

class User extends Model
{
    protected $appends = ['name'];
}

laravel 建立多國語言

https://www.myandroid.tw/bbs-topic-1615-0.sea

  • 先在 lang 下建立 zh_tw 資料夾,然後在 en 與 zh_tw 中加入語言定義檔
  • app()->setLocale(Session::get(‘locale’));

Laravel 實作資料庫讀寫分離

https://laravel-china.org/topics/1879/laravel-5-configuration-read-and-write-separation-and-source-analysis

  • Laravel5读写分离配置比较简单,只需修改config/database.php,下面以MySQL数据库为例,内容如下
'mysql' => [
    'read' => [
        'host' => '192.168.1.1'
    ],
    'write' => [
        'host' => '196.168.1.2'
    ],
    'driver'    => 'mysql',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
]

Laravel 與TDD

關於TDD-1
關於TDD-2

先寫規格在寫程式,而規格本身就是可執行的案例

1.Red – 先寫測試程式,此時因為還沒有實作功能,所以這個測試是會++失敗++
2.Green – 快速實作出功能,讓上述的測試++通過++
3.Refactor – 重構程式碼,去除多餘重複的代碼,提高程式碼品質,同時維持測試通過

注意事項

  • 一定是先寫一個不通過的單元測試,才開始實作功能
  • 每次只新加一個單元測試,只需要剛剛好不通過即可,不要一次加多個測試情境
  • 每次實作功能時,只需要剛剛好通過測試即可,不多也不少
    http://oomusou.io/laravel/laravel-service-provider/
    http://jellybook.me/articles/2017/04/laravel-view-count
    http://www.jianshu.com/p/445ef6820753
    https://my.oschina.net/imayanlong/blog/828855
    https://noob.tw/elasticsearch

詳解MVC 架構

https://hackmd.io/JwBgHAzAJgRsUFoYHZgGMEBYCGMBMCYArBMAhGhAKaZoBmAbBJlEUA==#

Laravel 佈署到 Azure

相關資源

r567tw

住在台北的一位台東developer,最喜歡"忠心"這個形容詞。這一生希望完成三件事:寫一本書、站在TED演講並且想要成為福音及各種學科的橋梁,希望自己能從基督教的思考框架出發與各學科傾聽、回應、對話