發表文章

目前顯示的是 八月, 2015的文章

Laravel PHP 5.6 mail stream_socket_enable_crypto

今天在用 Laravel 使用寄信時一直遇到這個問題: stream_socket_enable_crypto(): Peer certificate CN

查了一下才知道自己的 php 版本是 php 5.6,好像是改變了一些機制,看起來很複雜,不過快速的方式就是,如果你跟我一樣不是用 SSL,那可以把 'encryption' 的設定改為 '' 空值就好。

預設為 //'encryption' => 'tls',,改為 'encryption' => '', 或是 'encryption' => env('MAIL_ENCRYPTION', ''),

有空再來了解,蠻煩的,因為最近專案全面使用 php 5.6 以上,沒遇過這些問題,本來 SMTP 是一件這麼簡單的事情,搞的我心煩。

參考文章 https://laracasts.com/discuss/channels/general-discussion/smtp-mail

SCP 下載遠端 server 上的檔案

複製 AWS  ubuntu 上的檔案到自己的本機,可以使用 SCP 指令。
要看完整的 scp (secure copy) 指令就 man 一下吧 (man scp)。

如果你是要用 pem 去登入的話: 公式: scp -r -i [pem file path]user@host:[server folder path][local destination path]
範例: scp -r -i your_server.pem  ubuntu@ip_or_domain:/var/www/XXXX/  /tmp/目的地資料夾

-r 是遞迴的意思,因為複製的檔案可能是好幾層的資料夾。 -i 是 identity_file 的意思,所以後面的參數就是接 pem 檔的路徑。

因為每次都忘記,所以特別紀錄一下。

關於 Laravel 5.1 的 Middleware

接觸 Laravel 5.1 的時候看到 middleware 這個資料夾的時候真的有驚訝到,是說,正常人第一眼看到 middleware 的時候會有以下症狀:

* middleware 是什麼?
* 我該怎麼用 middleware?
* 不會寫會怎麼樣嗎? (<- 一定不會怎樣,看你對自己的要求到哪而已 XD)
* 乾眼症

本魯心中也是這兩個問號,不過還好,在剛進敝公司的時候,跟隨同事用 Koa (一個 node.js 的 web framework) 開發 Web Application 的時候,就已經接觸過 Middleware 這個玩意兒了,他說起來確實有點難解釋,抽象,但漸漸抓到它的用處之後,會覺得他真的很好用,使用它最著名的範例,像是 csrf, 權限管理, auth...,下面我會貼上一個 link,大家可以稍微去參考一下那個作者怎麼使用 middleware 做權限管理 (年紀越大越懶得把整份 code 都貼出來講...)。

我先拉回來繼續講 middleware 本身。middleware 有的書會翻中介層,有的會翻中介軟體。它本身的行為可以說是 filter (過濾器),他本身的功能,用意是來隔離網站基礎設施與業務邏輯,至於他的工作範圍,可以說是收到 http request 之後一直到業務邏輯這一段都算,你可以想像你在切一顆洋蔥,那一刀要切下去的時候,就是開始發送 http request,切到中心點時,就是 app 本身的核心功能 (MVC),中間這一段過程,都是 middleware 可以處理事情的地方。

所以那個過程,可以攔截很多資訊,像是在程式還沒跑到 view 時,就先判斷誰有資格看到那個 view,所以這樣的權限功能,就可以寫在 middleware,而不是已經進到 controller 甚至是 view 了,才開始做這些判斷,你一個 app 可能 50 個 controller,難道你要一隻一隻程式各別去加那個判斷嗎? 所以,試著把這些功能抽出來,寫到越前面(底)的地方,提早執行, 不符合條件繼續往下一步就早點 response 回去給 user。

假如今天我寫了一個 middleware,在每個 route 去設定 middleware 以及要 filter 的規格,這樣就算是有用到 middleware 的功能了,不…

Laravel 5.1 測試時模擬 user 登入

最近這幾天都在寫測試,花蠻多時間的,不熟之外,資源也不夠齊(不好找,有時 L4, L5 參雜,自己都搞混了)。

如果你是用 Laravel 4,那麼請參考 4 的說明 (有一段:『 You may set the currently authenticated user using the be method』從這邊開始 )。

在 Laravel 5.1 測試 user 登入狀態,要用 Model Factories 的方式,在這裡也要感謝小鐵大大,幫了我很多忙 :P。


大概的重點如下
* 在 phpunit 測試 code 裡面,使用 factory 去 fake 一個 $user,如官方文件說明,看你想要用 make() 還是 create()。另外我也意外地發現 $faker 蠻方便的,很開心的在 database/factories/ModelFactory.php 盡量學習用 $faker XD

我的 sample code,不是很完美,大概描述一下作法類似這樣子而已:
因為之後有很多模組或是功能都會需要這個假裝有 user 登入的測試情況,所以把它寫在外面 (TestCase去),繼承 TestCase 的測試 php 就都可以使用。
// TestCase.php

protected function demoUserLoginIn()
{
    $user = factory(App\User::class)->make();
// Use model in tests...
// 登入 user
    $this->be($user);
}
繼承 TestCase 的測試程式:
//  某隻 extends 自 TestCase 的測試.php

public function testLogout()
{  
    // 使用 TestCase 的 demoUserLoginIn
    $this->demoUserLoginIn();

    // 檢查登入狀態
    $this->assertTrue(Auth::check());
    // do other things...
}
* 另外一種測法是,只是測試資料帶入 form 然後登入的情況,一樣也可以模擬出登入的情況,只是每次都要繞到登入頁,這種測法就比較適合單純測登入表單的情況…

Laravel 設定 foreign 要注意的事情

設定 FOREIGN_KEY_CHECKS
(1) 如果你在有設定 foreign 的相關 table 做 seeder 的時候,假設出現以下的 error: SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot truncate a table referenced in a foreign key constraint ....

會有這樣的問題是因為 seed 的時候,就會立刻去檢查某個 schema 的外鍵,可是外鍵當時可能還沒建立。

那表示你需要在 seeder 在 inser 資料前後,做 FOREIGN_KEY_CHECKS 的切換 (畫底線那兩行),inser資料前先設為 0,insert 資料後設為 1 :

// 假設這是某隻 seeder 
// 這隻 seeder 的某個欄位是別張表的外鍵 
// XXXXTableSeeder.php

<?php
use Illuminate\Database\Seeder;
class UserTableSeeder extends Seeder
{
publicfunction run()
    {
        // disable foreign key constraints
DB::statement('SET FOREIGN_KEY_CHECKS = 0');
        DB::table('user')->truncate();
        $users = [
               // data....
        ];
         DB::table('user')->insert($users);
        // disable foreign key constraints
DB::statement('SET FOREIGN_KEY_CHECKS = 1');
    }
}

小心,unsigned()!
(2) 『當外鍵有參照到自動增量時,記得設定外鍵為 unsigned 型態。』- from http://laravel.tw/docs/4.2/schema
這句話的意思是,如果某張表的 key 是參考到另一張表的鍵而且是 a…

Laravel ORM 兩個 schema(cloumns) 一起 unique

在製作某個表時,發現有個 schema 是需要一起 unique 起來的。

比方說有張記錄使用者權限的表格,user winwu  同時有 article-write, 以及 article-read 兩個權限,就會有兩筆記錄:

id  user_account     user_auth
1   winwu                 article-write
1   winwu                 article-read

但是又不希望  winwu   article-write 有一天又被重複紀錄,就是 winwu 這個人,對應到 article-write 是 unique 的。

在 schema builder  (migration 檔案) 可以這樣表示:

$table->unique(['user_account', 'user_auth']);
記得,重跑 migrate:rollback,然後再重新 migrate,你可以在 seeder 試著故意重複兩次一樣的紀錄,應該就會有 error 告訴你這些 schema 是 unique 的了。

error的訊息會像這樣:
  [PDOException] SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'winwu-article-read' for key ...

參考:
http://stackoverflow.com/questions/16990723/laravel-4-making-a-combination-of-values-columns-unique

對了,如果有比較適合的方式可以達到一樣的功能,就麻煩留言一下讓更多人知道 :) 謝謝!

O'REILLY『可測試的 JavaScript』 讀書心得

圖片
(我好幾次呆坐在螢幕前,不知道該分享些什麼...)
第一次在書店看到這本書時還蠻興奮的,又是 JavaScript,又講測試,感覺就應該讀一下,立刻帶回家 XD (敗家)。
幾個心得:
*測試是有方法可以遵循,有經驗可以參考,但是寫測試是要練出來的,只有自己練出來才是最真實的...。
 *  TDD (Test-Driven Development) 測試驅動開發,是敏捷開發的推薦做法,就是先寫測試,再寫相對應的程式。 
 * BDD (Behavior-Driven Development) 行為驅動開發,建立在 TDD 之上,測試描述一個程式或是模組的行為。 
*要測試你的程式碼,首先程式碼要先可以被測試才是重點,畢竟程式可以很複雜,也可以很簡單,可以測試的程式碼要盡量是低耦合, 獨立的。(多做程式的拆解練習,把複雜的程式慢慢拆解為一隻隻比較單純, 單一任務的程式)。
*第三章講的事件導向架構,我沒有看得很懂就是,但是重點跟上一點接近。
*第四章講單元測試,單元測試算是我第一次接觸測試的方式,他需要工程師去思考每個單元測試需要哪些測試案例(腦補一些可能出現的弱點,就好像某隻程式明明需要帶入一個 值為 email 的參數,但是只有測到這個參數帶進去,卻沒有測試 email 的格式是否正確之類的...),因此,單元測試算是不能百分之百找到 bug 的測試,但是單元測試的重點是在於測試每隻程式的功能是否有符合需求(功能確認導向)。    另外單元測試的 code 我覺得蠻好讀的,他的重點就是斷言(assert),直接去驗證某個值是否符合預期。
* 程式碼涵蓋率(Code Coverage),用來測量已經執行的測試程式碼之於未執行過的程式碼的涵蓋數,結果會用百分比來表示。 通常跟單元測試有關。書中 P.95 有個涵蓋率的參考:     - 低於 50% 的 code coverage,是個低標區 (red flag)     - 介於 60%~80% 的 code coverage,是甜蜜區 (sweet spot)     - 大於 80% 的 code coverage,單元測試的效能會符合收益遞減率(<- 基本上我看不懂這個意思是什麼) ( code coverage 過高可能有誤導之嫌)。    另外,code coverage 最好是自動化產生。
* …

Laravel5 file upload 上傳檔案範例

我把 controller 的範例分兩個來看,一個是多檔上傳,一個是單檔上傳,也不是說寫得很好,但至少還可以 work。

多檔上傳的範例:
另外因為是 json 回傳,所以 ajax 的部分我就不說明了。

單檔上傳的範例:

另外我也描述一下 view 的 form:

範例裡面有兩個 Form::file,請選擇是用哪一種,一個是 photo,另一個是 photo[]。

你還可以多注意的事情
* 檔名的建立方式我通常偏好 uuid,這部分就是依個人喜好。
* 圖片的 crop, resize 在這個範例並沒有做,你也可以自己串。
* 如果你不是用 Form:: 的方式在 view 建立你的 <form> 等等標籤,那麼務必要記得 form 的這個 enctype="multipart/form-data" (在這個範例是透過 'files'=>'true' 屬性產生)屬性一定要有,否則你永遠沒有東西可以上傳
* 這邊沒有做 javascript ajax 的範例,所以如果你是沿用這個 sample,當然送出之後會接看到 json 格式的頁面,所以也是要自己把這段串起來,這邊我是為了方便,才先用 form submit。

參考
How To Create File Upload With Laravel By clivern On April 10, 2014
webpatser/laravel-uuid