2017年2月5日 星期日

laravel 1071 Specified key was too long; max key length is 767 bytes 解決方法

        laravel new 一個新專案之後,在.env用好資料庫設定,接著執行php artisan migrate的時候,拋出了兩個例外:

  [Illuminate\Database\QueryException]                                                                                                                                                 
  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))  
                                                                                                                 
  [PDOException]                                                                                                   
  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes  

        可以看到共通點就是Specified key was too long; max key length is 767 bytes。

        因為laravel5.4用的是utf8mb4編碼,這種編碼跟默認的uft8編碼差別就在於utf8編碼最多支援到3個字節,而utf8mb4可以支援到四個字節,所以utf8mb4可以支援四個字節的emojis儲存進資料庫,mb4指的就是「most bytes 4」,而utf8mb4同時也支援許多的漢語難字。

        但在5.7.7之前的Mysql版本,以及10.2.2之前的MariaDB版本必須要手動調整預設的字串長度讓MySQL可以為他們新增索引。

        實際做法是在AppServiceProvider.php裡面加兩行程式碼:

<?php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

// 1
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        // 2
        Schema::defaultStringLength(191);
    }

    /**     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //    
    }
}

        引入Schema之後再去呼叫defaultStringLength去更改預設字串長度就行了。


參考資料:


2017年2月1日 星期三

PHP else if 和 elseif 的研究

        開門見山的說,用 {} 的寫法運行起來是完全一樣的,舉例:

$a = 2;

if ($a == 1) {

} elseif ($a == 2) {

}

vs

$a = 2;

if ($a == 1) {

} else if ($a == 2) {

}

        會顯示出一樣的結果,而php在解析語法的時候,會將第二種寫法,也就是else if剖析成:

if ($a == 1) {

} else {
    if ($a == 2) {

    }   
}

        不過如果用colon的寫法則會有所不同,以php官方文件的程式碼為例:

/* Incorrect Method: */
if($a > $b):    
    echo $a." is greater than ".$b;
else if($a == $b): // Will not compile.    
    echo "The above line causes a parse error.";
endif;

/* Correct Method: */
if($a > $b):    
    echo $a." is greater than ".$b;
elseif($a == $b): // Note the combination of the words.    
    echo $a." equals ".$b;
else:    
    echo $a." is neither greater than or equal to ".$b;
endif;

         可以看到上方寫成else if分開,運行會parse error,下方連在一起的則不會。      

         psr-2的規範也說了必須連在一起:

     
        綜此上述,elseif目前是php裡判斷是的最佳選擇。

        參考資料:      
        http://www.php-fig.org/psr/psr-2/#if-elseif-else      
        http://www.php.net/manual/en/control-structures.elseif.php
        http://stackoverflow.com/questions/3662412/are-elseif-and-else-if-completely-synonymous