發表文章

[筆記] 如何在 Laravel 測試中使用 Faker

圖片
是這樣的,我想在 Test 中產生一些假資料丟給 Service method 跑,於是很直覺地想到了 Faker 這個很棒很方便的東西。 一般我們使用 Faker 是 搭配 Model Factory 使用 。但是我這次只是想產生個簡單的假資料,跟我的資料庫或 Model 都沒有關係,有沒有辦法? 只是放一個封面圖 隆重介紹:WithFaker trait Laravel 從 5.5.24 版開始 已經內建了這個 trait,而且在你使用 artisan 指令建立測試檔案時就會自動幫你導入命名空間了: use Illuminate \ Foundation \ Testing \ WithFaker ; 結果到現在已經 5.7 版了,竟然還沒有在教學文件出現過。可以自行參考 Laravel API 文件 。 如何使用 WithFaker 現在只需使用 trait 在你的測試類別上,例如: # tests/Unit/ExampleTest.php // 上略 class ExampleTest extends TestCase { use WithFaker ; // 下略 接著就可以透過 $this->faker 來操作 Faker 了,例如: echo $this - > faker - > name ; // 'Lucy Cechtelar'; echo $this - > faker - > address ; // "426 Jordy Lodge // Cartwrightshire, SC 88120-6700" echo $this - > faker - > text ; // Dolores sit sint laboriosam dolorem culpa et autem. Beatae nam sunt fugit // et sit et mollitia sed. // Fuga deserunt tempora facere magni omnis. Omnis quia temporibus laudantium ...

[筆記] Faker 如何產生 10 位數以上的 random number?

在寫 Laravel 測試需要的 Factory 時,有個欄位需要 16 位數以下的數字。一般來說直接透過 fzaninotto/Faker 的 randomNumber 就可以很方便的生成了: $number = $faker - > randomNumber ( 16 ) ; 結果執行的時候竟然噴錯了! InvalidArgumentException: randomNumber() can only generate numbers up to mt_getrandmax() mt_getrandmax() 是什麼 錯誤訊息中提到的 mt_getrandmax() 是 PHP 的內建函式,會回傳 PHP 透過 mt_rand() 可以產生的最大數。 這個 mt_rand() 就是一般的隨機產生函式,只要有指定 min 和 max,其實他是可以產生更大數的,不是很理解為什麼 Faker 沒有做這個處理。 可以怎麼做? 這裡我想了幾個方法,可以給各位參考。 方法一:直接使用 mt_rand 或 random_int 既然他背後是使用 mt_rand() ,那就直接使用它吧。 $number = mt_rand ( 1 , 9999999999999999 ) ; 不過我實際使用發現,雖然我是只有上限給了 16 位數,他產生的結果好像是固定十六位數。 後來嘗試了 PHP 7 新的 random_int ,結果差不多。 $number = random_int ( 1 , 9999999999999999 ) ; PHP 官網文件在 mt_getrandmax 的頁面上有提及,如果提供 MAX 給 mt_rand 會減少隨機性,不知道是不是這個原因。 方法二:使用 numberBetween Faker 有提供 numberBetween ,所以可以直接使用: $number = $faker - > numberBetween ( 1 , 9999999999999999 ) ; 因為 numberBetween 也是基於 mt_rand ,我實測結果好像只比 mt_rand 好一點。 以上兩個方法如果有人知道如何修正,再麻煩留言跟我說一下。 方法三:使用...

[筆記] Facebook Open Graph 的 og:locale 該如何設定?

圖片
Facebook 的開放社交關係圖(Open Graph)針對 og:locale 的規範不曉得是不是有更新,以至於檢查網頁抓取資訊的時候噴了一個我沒看過的錯: 「 website 」類型的 URL「 https://www.example.com 」無效,因為「 og:locale:locale 」特性的指定值「 XX 」無法作為「 enum 」類型進行剖析。 Object at URL ‘ https://www.example.com ’ of type ‘website’ is invalid because the given value ‘XX’ for property ‘og:locale:locale’ could not be parsed as type ‘enum’. 查了一下發現是語言格式錯了,Facebook 的格式不是完全依照 ISO 標準,依據 本地化文件 的說明: Facebook 上的語言使用 ll_CC 格式,ll 是兩個字母的語言代碼,CC 是兩個字母的國家/地區代碼。例如,en_US 代表美式英文。 我們支援許多 ISO 語言和國碼/區碼 從 SDK 文件 裡面可以看到目前 Facebook 支援的 og:locate 列舉如下: Allowed values: en_us, ca_es, cs_cz, cx_ph, cy_gb, da_dk, de_de, eu_es, en_pi, en_ud, ck_us, es_la, es_es, es_mx, gn_py, fi_fi, fr_fr, gl_es, ht_ht, hu_hu, it_it, ja_jp, ko_kr, nb_no, nn_no, nl_nl, fy_nl, pl_pl, pt_br, pt_pt, ro_ro, ru_ru, sk_sk, sl_si, sv_se, th_th, tr_tr, ku_tr, zh_cn, zh_hk, zh_tw, fb_lt, af_za, sq_al, hy_am, az_az, be_by, bn_in, bs_ba, bg_bg, hr_hr, nl_be, en_gb, eo_eo, et_ee, fo_fo, fr_ca, ka_ge, el_gr, gu_in, hi...

[筆記] 延長 PHP-FPM 和 NGINX 執行時間上限

Laravel 或是一般 PHP 專案上常會遇到執行時間超時的問題, 例如遇到了 PHP 超過執行時間上限的錯誤: 'production.ERROR: Maximum execution time of 30 seconds exceeded' 或是遇到 NGINX 的超時錯誤: '504 Gateway Time-out' 是因為 PHP 和 NGINX 預設最長執行時間都是 30 秒,我們可以修改設定來延長它們。這裡我們延長到 Apache、IIS 慣例的 5 分鐘。 這個主題其實很多人寫了,但是資訊有點零散,乾脆自己再寫一篇方便以後找。 (感覺就是很常會改啊) PHP: 延長 max_execution_time PHP 的 runtime 設定中的 max_execution_time 參數可以指定腳本被 parser 中止之前允許的最大執行時間,預設值是 30 秒。我們可以透過修改 php.ini 指定為 300 秒。 修改 php.ini 以 PHP 7.2 為例,php.ini 的位置預設是在 /etc/php/7.2/cli/php.ini 。php.ini 的位置可以經由 php -i 指令查詢的到。順帶一提,PHPBrew 使用者可以透過 phpbrew config 指令直接開啟當前版本對應的 php.ini。 ; /etc/php/7.2/cli/php.ini ;;;;;;;;;;;;;;;;;;; ; Resource Limits ; ;;;;;;;;;;;;;;;;;;; ; Maximum execution time of each script, in seconds ; http://php.net/max-execution-time ; Note: This directive is hardcoded to 0 for the CLI SAPI max_execution_time = 300 重新啟動 PHP-FPM 修改完成後,需要重新啟動 PHP-FPM。 PHPBrew 使用者 phpbrew fpm restart Ubuntu/Debian 系 sudo service php7.2-fpm res...

PHPBrew:編譯 PHP 的各種踩雷紀錄

PHPBrew 是由 C9S 大神產出來的神作,一直以來都用它維護伺服器上的 PHP 版本,但時常會有一些小問題要解決。這次剛好要裝到新機器上,就順便記錄一下遇到的一些狀況。 系統環境 新開的 VPS 主機,作業系統為 CentOS 7.5,已經用 yum update 更新到最新環境,有啟用 epel-release repository。 Requirement 先安裝官方 Wiki 指定的基本套件,使用的是以下段落: https://github.com/phpbrew/phpbrew/wiki/Requirement#fedoracentos-requirements 這頁面的另一個段落( CentOS Requirement )親身實驗確定已失效, repoforge.org 已經掛很久啦 !! yum install make automake gcc gcc-c++ kernel-devel yum install php php-devel php-pear bzip2-devel yum-utils bison re2c libmcrypt-devel libpqxx-devel libxslt-devel pcre-devel libcurl-devel libgsasl-devel openldap-devel yum-builddep php yum install httpd-devel 以及我自己需要裝的相依,注意 readline 是有包含在 +default 的,如果你也是指定 +default ,記得安裝。 yum install readline-devel ImageMagick-devel libmemcached-devel Installing PHPBrew into System wide Environment 參考資料: https://github.com/phpbrew/phpbrew/wiki/Installing-PHPBrew-into-System-wide-Environment 如果想要讓編譯的 PHP 可以給所有使用者使用,就使用 root 來編譯吧。 sudo -i # 切換成 root 身份 phpbrew init 增加環境變數到 PHP...

[筆記] Laravel One to Many 遇到 a foreign key constraint fails

圖片
碰到錯誤訊息了 (以下 Model 與 Table 名稱為示意,有可能因為手工改寫而有出入,看起來怪怪的地方請跟我說) 在儲存 Category、Product 兩 table 的 One to Many 資料時,我收到的錯誤訊息如下: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`store`.`products`, CONSTRAINT `products_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`)) (SQL: insert into `products` (`name`, `category_id`) values (商品 P, 0)) 發生錯誤的程式碼簡化後類似這樣: $category = new Category ; $category - > id = "category01" ; $category - > name = "分類 C" ; $category - > save ( ) ; $product = new Product ; $product - > name = "商品 P" ; $category - > products ( ) - > save ( $product ) ; 檢查了一遍 Category 的 Model 已經設好 hasMany : public function products ( ) { return $this - > hasMany ( 'App\Product' ) ; } Product 的 Model 中 belongsTo 也設定正確: public function category ( ) { return $this - > belongsTo ( ...

[筆記] 無法重置 MariaDB 的 root 密碼該怎麼做?

圖片
忘記 MariaDB 的密碼想要重設,下了多個常見的指令 MariaDB [ ( none ) ] > SET PASSWORD FOR 'root' @'localhost ' = PASSWORD(' new_password '); MariaDB [(none)]> ALTER USER ' root '@' localhost ' IDENTIFIED BY ' new_password '; MariaDB [(none)]> UPDATE mysql.user SET authentication_string = PASSWORD(' new_password ') WHERE User = ' root ' AND Host = ' localhost '; MariaDB [(none)]> update mysql.user set password=password(' MyNewPass ') where user=' root' ; 都失敗,出現的錯誤訊息大多如下 ERROR 1131 (42000): You are using MariaDB as an anonymous user and anonymous users are not allowed to change password 照著很多網路步驟做,都還是不能修改成功。 都是當下看起來成功,然後下 quit 重新登入又失敗。 這時只好換個關鍵字搜尋:"cant reset MariaDB password" 就被拯救了! 發生什麼事? 多篇文章都提到同一個現象 如果你的 mysql.user table 裡面的 plugin 欄位被 “unix_socket” 佔據, 就會修改失敗(這是什麼巫術…) 依據國外網友分析, 通常 MariaDB 更新後, plugin 欄位就會被補上這個值(這又是什麼巫術…) 大致看一下, Unix Socket 是一個認證外掛, 主要是讓使用者可以直接透過系統認證進入資...