2017年12月5日 星期二

laravel binding database config 機制

        今天需要在一個地方連續切換資料庫,所以連帶的也要設定database config,但發生db table not found的狀況,dd了config發現沒有設定錯誤。

        查了stackoverflow才知道,laravel似乎有個binding的機制,如果基於一開始的config建立連線,那這個連線就會持續存在,之後不管是eloquent還是db connection都會基於這個連線運行sql,即使之後調整了config也一樣:

$page = Page::find(1);

// 設定另外一個config
config([
    'database.connections.mysql.host' => $hostname,
    'database.connections.mysql.username' => $username,
    'database.connections.mysql.password' => $password,
    'database.connections.mysql.database' => $database,
    'database.connections.mysql.charset' => $char_set
]);

// 原本的db沒有orders table,發生錯誤
$order = Order::find(1);

        這裡的解決方式:

$page = Page::find(1);

// disconnect 連線
DB::disconnect('mysql');

// 設定另外一個config
config([
    'database.connections.mysql.host' => $hostname,
    'database.connections.mysql.username' => $username,
    'database.connections.mysql.password' => $password,
    'database.connections.mysql.database' => $database,
    'database.connections.mysql.charset' => $char_set
]);

// 原本的db沒有orders table,發生錯誤
$order = Order::find(1);

        這樣一來就會連接到之後設定的config了。


參考資料:

https://stackoverflow.com/questions/35466362/laravel-5-changing-database-name-in-runtime

2017年11月23日 星期四

array_filter的注意事項

        今天前端回報一個api的型別問題,發現有一個應該要return array的卻return成object了,
只有array型別是associative array的時候才會return成object,也就是一個key對一個value,但是之前寫的程式沒有任何key的設定,最後發現是array_filter的坑。

        以下是程式碼:

$ary = [1, 2, 3, 4, 5];

$ary = array_filter($ary, function($v) {
    return $v != 3;
});

echo json_encode($ary);

        當$content進入到array_filter之後,array_filter把不符合label的刪除,但同時也會幫你保留keys值的相對位置,進而把你的array變成associative array。

        也就是說結果變成:{"0":1,"1":2,"3":4,"4":5} 。

        所以這裡我們必須對array_filter產出的結果在處理一次:

$ary = [1, 2, 3, 4, 5];

$ary = array_filter($ary, function($v) {
    return $v != 3;
});

$ary = array_values($ary);

echo json_encode($ary);

        用array_values重新轉換成sequential array就行了。

        結果回到我們預想中的:[1,2,4,5]。


        參考資料:


2017年11月22日 星期三

CI/CD Journey from on-premise to AWS Cloud 筆記


  1. 講者推alb
  2. opsworks一堆坑,直接用ec2設定auto scaling
  3. 之前用opsworks,加掛monit做看門狗
  4.  cloudformation沒有提供隱藏或編碼db密碼的function,講者團隊自己寫一個lambda
  5. cliff推薦用serverless framework,對CI/CD會事半功倍

cliff => https://blog.clifflu.net/2016/09/lambda-container-reuse/

ps. 團隊用的是github+circleci+cloudformation做CI/CD

2017年11月14日 星期二

docker port無法釋出的問題

        已經停止所有的container了,但要起一台新的container卻一直無法成功,不然就說是有衝到port,查詢了之後可能是osx版本docker的network還可能佔有的樣子。

        https://github.com/docker/compose/issues/3277

        
         照著指示清除network就沒事了,主要可以先執行最後一行查看目前的port試試。

2017年9月10日 星期日

用docker快速建立開發環境 (php7.1 + mysql + apache)

        以下範例的程式碼都在github上。
     
        https://github.com/keepgoing147/docker-php7-apache-mysql

        安裝好docker之後,新建一個資料: test,cd 到test,新增docker-compose.yml,並新增以下code:

web:
  build: .
  links:
    - db
  ports:
    - 80:80
  volumes:
    - ./www/html:/var/www/html
    - ./src/your-project/:/var/www/html/your-project

db:
  image: mysql:latest
  restart: always
  volumes:
    - ./mysql:/var/lib/mysql
  environment:
    MYSQL_ROOT_PASSWORD: rootpassword
  ports:
    - 8887:3306

        這邊要注意yml編排格式。

        接著,在同樣的資料夾新增一個Dockerfile,並新增以下code:

FROM php:7.1.9-apache

RUN apt-get update
RUN docker-php-ext-install pdo pdo_mysql

        最後,新增src/your-project/index.php,index.php的內容打:

<?php

echo 'success execute in docker!';


        這個時候,你的資料夾結構應該會長這樣:


        執行:docker-compose up -d
         (-d是為了讓docker-compose命令在背景執行,不追蹤成功run起來之後的後續動作)

        會出現開始build image的訊息


        這次我們用了兩個image:php:7.1.9-apache, mysql:latest,所以會需要pull下來兩個image檔。

        

    執行完成之後,存取 http://localhost/your-project/ ,就會看見成果了:


        也可以再your-project裡面新增這段code來測試mysql是不是也架好了:

<?php
try {
    $db = new PDO(
       'mysql:host=db;dbname=docker-table;port=3306;charset=utf8',
      'root',
      'rootpassword'   );
} catch (PDOException $e) {
    echo 'DB connection failed';
   exit;
}

$data = $db->query('select * from comments');
$data = $data->fetchAll();
var_dump($data);

        osx上的話可以透過sequel pro去連接localhost:8887的db,去建立一個docker-table的database,再新增一個table為comments,去測試能否成功query就行了。

        結果會像這樣:

        連接成功!

2017年7月19日 星期三

「淺談WAF在AWS的架構」小聚筆記

新知:
  1. OWASP top10 => https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project
  2. CVE & NVD
  3. PCI DSS
  4. DVWA => 資安測試
需研究:
  1. aws vpc
  2. aws alb
  3. aws cloudfront cooperate with waf
        總結來說aws的waf以業界的waf廠商來看還不是這麼完善,像log只能追到三小時前,不然只能自己寫script去定時抓,或是per web ACL只能支援10條....etc,不過夾帶著aws可以跟其他service一起管理的優勢,以及之後aws一定會更完善waf的架構,市佔率一定也會穩定提升的吧。

        講者建議白皮書必讀,六月剛發行的。

2017年7月16日 星期日

介紹php array_map

        有時候需要對array做一點另外的處理,譬如為每一個value做另外的處理:

$nameAry = ['Hong', 'Peiwen'];

$helloNameAry = array();
foreach ($nameAry as $name) {
    $helloNameAry[] = 'hello, ' . $name;
}

var_dump($helloNameAry);

        幫每一個name都加上一個hello,結果會是:


        但這樣一來可讀性很低,而且需要多新增一個$helloNameAry的參數去存result。

        這時候array_map就能派上用場了:

function addHello($name)
{
    return 'hello, ' . $name;
}

$nameAry = ['Hong', 'Peiwen'];

$nameAry = array_map('addHello', $nameAry);

var_dump($nameAry);

       這裏array_map會遍歷所有array的value去跑callback function,這裡的callback function指的是addHello,這樣寫的話,不僅重新parse array value的function可以複用,而且寫起來也比較優雅。

       如果不想另外另一個function的話,也可以直接寫在array_map的parameter裡面:

$nameAry = ['Hong', 'Peiwen'];

$nameAry = array_map(function ($v) {
    return 'hello, ' . $v;
}, $nameAry);

var_dump($nameAry);

        $v就是遍歷$nameAry裏的value,結果都會是:



參考資料:

http://php.net/manual/en/function.array-map.php


2017年5月10日 星期三

zshrc搞壞的補救方法(zsh: command not found: vim)


        現在人大部分都會裝iterm2+zsh,而裝了zsh的關係,設定檔也會從.bashrc or .bash_profile變成.zshrc。

        今天要討論的就是萬一把.zshrc的PATH改壞了,而且又source它發生憾事的時候,該如何處理?

        首先當下一定會看到類似這個狀況:



        command明明就存在,但是zsh卻一直報錯,嘗試著用vim去編輯.zshrc也沒辦法,似乎就卡在這裡無法做任何事了。

        要解決這件事,首先我們可以先把zsh切換為原本的bash,用bash的環境去執行:

exec bash -l

        -l 就是login的意思,換成--login or -login也可以:   exec bash --login

        接著就可以用vim去把.zshrc修回來囉!


        source完變更之後,zsh又是一條好漢!



        參考資料:

http://stackoverflow.com/questions/10341271/switching-from-zsh-to-bash-on-osx-and-back-again

2017年4月10日 星期一

public vs protected vs private比較

        這是在php裡,最常看到三種宣告function的方式。

        下面用code做個簡單解說:

class Test
{
    public function public_function()
    {
        echo 'I am public function!';
    }

    protected function protected_function()
    {
        echo 'I am protected function!';
    }

    private function private_function()
    {
        echo 'I am private function!';
    }
}

$test = new Test();

$test->public_function();


       這三個宣告方式,如果要在class外面使用的話,只有public可以,因為public意思就是公眾化的,開放的,大家都可以任意取用的。

       而protected則是要透過parent class的用法,也就是extends就能調用了:

class Test
{
    public function public_function()
    {
        echo 'I am public function!';
    }

    protected function protected_function()
    {
        echo 'I am protected function!';
    }

    private function private_function()
    {
        echo 'I am private function!';
    }
}

class Test2 extends Test
{
    public function call_parents_function_protected()
    {
        $this->protected_function();
    }
}


$test = new Test();

$test->public_function();

$test2 = new Test2();

$test2->call_parents_function_protected();


        像這樣的方式,就能成功調用了!

        至於private在所處的class裡面才能調用:

class Test
{
    public function public_function()
    {
        echo 'I am public function!';
    }

    protected function protected_function()
    {
        echo 'I am protected function!';
    }

    private function private_function()
    {
        echo 'I am private function!';
    }

    public function call_in_same_class()
    {
        $this->private_function();
    }

}

$test = new Test();

$test->call_in_same_class();

        這樣就行了!

        總結來說,public大家都能取用,protected則是父類別才能使用,private則是只能在宣告function的class裡面使用。



        參考資料:

http://stackoverflow.com/questions/4361553/what-is-the-difference-between-public-private-and-protected


2017年3月29日 星期三

__call()的妙用

        php有個magic method叫__call(),寫法是這樣的:

class Demo
{
    public function __call($function , $args)
    {
        echo 'function: *' . $function . '* don\'t exist!';
    }
}

(new Demo)->target();



        __call的兩個參數可以任意取名,只要確定是兩個就好。

        當呼叫的target不存在,class Demo就會轉為呼叫__call(),讓開發者可以去設定如果function呼叫不到的時候做的事情,以上面的code執行下來,結果會是:

function: *target* don't exist!

        當沒有建立__call()的時候,會出現報錯:

Fatal error: Call to undefined method Demo::target() in /Users/Hong/php/test/test.php on line 11

        這裡有個今天讀code剛學到的小技巧:

class Animal
{
    public function __call($function , $args)
    {
        if ($function == 'dog') {
            $this->bark();
        } elseif ($function == 'cat') {
            $this->meow();
        }
    }

    private function bark()
    {
        echo 'bark!';
    }

    private function meow()
    {
        echo 'meow!';
    }
}

(new Animal)->dog();



        假設今天不確定動物的叫聲,這裡只需要呼叫動物的種類當作function name,然後因為Animal class找不到該function name,所以會呼叫__call(),__call()拿到之後就可以根據該function name去做對應的動作。

        注意到了嗎?本來應該是找不到function name做的預防措施,這邊卻反過來利用了這個特性,故意讓class找不到該function name,然後做統一分發。

        所以如果運用到API的溝通部分就是,先看看$_SERVER['REQUEST_METHOD']進來的是什麼,GET,POST,PUT?接著再從__call()統一分發到對應的function去呼叫後端API,達到整合的作用。

        寫code真的是一門永遠無法精通的學問,就算把單一語言的特性跟用法用得滾瓜爛熟,但永遠都會有更出其不意,或是更聰明的方式去完成任務,這次的__call()反其道而行的用法著實讓我大開了眼界。


參考資料:

http://php.net/manual/en/language.oop5.overloading.php#object.call





2017年3月28日 星期二

error_reporting 與 display_errors 區別

        當安裝好php,並開始coding的時候,有時候會看到頁面報錯:


        或是看到有warning,但頁面依然正常執行:


        身為開發人員,看著報錯上的提示去debug是很重要的,但有時候已經到了demo階段,頁面上有的報錯還來不及解決,在漂亮的UI上如果出現幾行Notice,會嚴重影響美觀以及客戶對系統的第一印象,這時候便需要對報錯的機制做一些調適。

        在mac安裝好php之後,會有一個php.ini的參數配置檔,php在server上運行就是靠這個配置檔,我是用brew安裝的,php.ini路徑在/usr/local/etc/php/x.x/php.ini,根據版本的不同再去更改x.x就好。

        預設的配置為:



        可以看到,php.ini在不同的環境下有不同的建議配置。

        display_errors在開發的時候,建議用On,但是正在線上運行的專案則是Off,開發的時候秀出錯誤,盡可能方便掌握系統的狀況,而在線上環境的時候,保持頁面的整潔,不出現抱錯or程式碼。

        error_reporting有很多種配置方式,在php.ini裡都有很好的說明,而~則是代表不包含,例如E_ALL & ~E_DEPRECATED & ~E_STRICT就是秀出所有error,但除了E_DEPRECATED以及E_STRICT,這點在php.ini裡也有解釋。

        但error_reporting以及display_errors到底差在哪?

        display_errors意思是要不要秀到頁面上,也就是一開始的兩張圖片,Notice和Parse error。

        error_reporting則是決定要秀什麼到頁面上,全秀?還是把一些訊息先排除?


        display_errors:要不要秀?

        error_reporting:要秀什麼?




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

2016年11月29日 星期二

var、let 的scope介紹

        以往Javascript的變數宣告都用「 var 」,「 var 」屬於比較鬆散的變數宣告方式,即使在不同的地方宣告一樣的變數名稱,在瀏覽器上執行一樣不會出錯,而這個特性同時也很容易造成一些Bug,ES6出現的「 let 」就很好的補足了var的不足。

        回顧var的特性,var屬於function scope,意思就是在function裡面宣告的變數只有在function裡面才有用,不會影響到外面,同樣的,也不能從外頭取得function裡的變數。

var i = 0;

function varTest() {
    var i = 100;
}

varTest();

console.log(i);

結果:0


function varTest() {
    var i = 100;
}

varTest();

console.log(i);

∆ 想直接取得宣告變數,結果就會是:


     
        而function scope也代表只有在function裡面才算有自己的地盤,一旦沒有function包住var,那幾乎等於跟全域變數一樣了,會直接影響到外面宣告的變數。

var i = 0;

if (true) {
    var i = 50;
}

console.log(i);

        結果:50

        同樣包在大括號之間,但是像這樣的if statement沒有包覆住裡頭的var,連帶地影響到外面宣告的變數。



        而let在一開始宣告就比var嚴謹了。

let i = 0;
let i = 50;

        在這一步,瀏覽器會直接報錯:


        而相較於function scope的var,let是block scope的,意思是在任何的{大括弧}裡面,let都會被緊緊包住,不會leak到外面去。

let i = 0;

if (true) {
    let i = 50;
}

console.log(i);

        結果:0

   
        在看歐萊禮的繁體中文書的時候,javascript的宣告變數scope會翻譯成「範疇」,不過如果用更白話文的方式來表達的話就是:

        「只要宣告在xxx裡,就不會影響到別人」。

        function scope:只要宣告在function裡,就不會影響到別人。

        block scope:只要宣告在任何一個{區塊}裡,就不會影響到別人。

     







2016年10月30日 星期日

PHPConf 2016 Day1 主議程心得 people is your assets 篇 + QA心得

        give praise

        不只Josh Lockhart在topic上提到,在QA的時候Sebastian Bergmann也完全同意這個觀點,有時候工程師在忙碌中,聽到一句「 good job!」、「 nice work」的時候,其實就也夠了,在Josh寫slim的時候,其實也有很多負評,但當一些使用者不管是用email或twitter之類的跟Josh表達感謝的時候,Josh覺得完全可以取代千千萬萬的負評,從而有動力的繼續維護。

        Josh Lockhart維護的slim framework、Sebastian Bergmann維護的PHPUnit,是完全沒有得到任何薪水的,支持他們繼續維護的最大動力,就是來自人們的感謝。

        Do not punish mistake 

        犯錯時不要責備。

        Josh提到,即使是他,在NMC的時候也犯了一堆錯誤,工程師們都會犯錯,但重要的是了解犯錯的原因,在下一次的時候避免掉,而不是一昧的責備,犯錯了,針對問題修復,學起來,別再犯,繼續往前邁進。

        Don't use obviously 

        沒有「 很明顯地」這種事情,每個人都會有思考盲點,所以這才是團隊合作的價值,大家能彼此用不同的角度去解決問題,共同激發出彼此想不到的角度去切入,也許你看到另外一位工程師卡在一個地方很久,然後你一過去就看到並解決了,但這時候但這時候千萬不能說「這地方出錯的很明顯啊,你怎麼解不出來?」、「很明顯的,你似乎走神囉」。

        或許你真的比這位工程師厲害,但或許也是因為運氣好,或是思考角度不一樣,但無論如何,在這個時候用obviously會達到負面的效果。

        welcome feedback

        永遠歡迎回饋。

        無論你接到語氣多差的負評,只要裡面提供的feedback是有價值的,就要接受,認為自己的專案已經很好了是不可行的,永遠都還有更好的空間,必須要接納各種可以讓專案變得更好的意見。

        這也跟上一段一樣,如果真的有個語氣不好的工程師指出你的錯誤,也要虛心接受,畢竟我們從這位工程師身上學到了新東西,幫助我們的技術更上一層樓,所以應該要心懷感激,當然,自己除了學到新東西之外,也記得教別人的時候,態度要好一點。



        兩位大神在QA的時候著墨在上面幾項很多,而對於open source的看法卻有點不太一樣。

        Josh Lockhart說open source不是一個人可以做得起來的,slim也是信任了幾位好朋友,把一些核心開發權交給他們一起維護,所以Josh說信任非常重要,如果一直巴著不放的話,slim不會像現在一樣這麼受到歡迎,運行的這麼好。

        而Sebastian Bergmann剛好相反,如果給他重新選擇的話,可能不會這麼快交給其他人共同維護,到了後期,Sebastian在PHPUnit上維護的工作幾乎都是翻修code,讓可讀性變得更好,而這個工作非常無聊,佔用了非常多的時間而且無法全心全意開發新功能,PHPUnit內部的程式碼品質參差不齊。

        Sebastian最後說了一句:「 Could have been better. 」

2016年10月29日 星期六

PHPConf 2016 Day1 主議程心得

        自從在facebook上加入了很多php社團,常常會看到很多活動公布在上面,不過幾乎都是平日晚上,遠在北投而相對晚的狀態,就比較難加入了,不過一方面也是因為懶,畢竟稍微遲到一下下,能聽到各式各樣業界人士非想還是蠻值得的。

        於是某一天看到PHPConf 2016的消息公布之後,時間一到就去買票了,說也巧合,本來10/29是我當初「一日北高」的預定時間,但到了六月的時候,腰突然發病,造成我整整三個月沒運動,想當然也達不到一日北高的訓練量,只好含淚售出了。

        寫這篇文章的當下,當初一起報名的另外兩個夥伴應該也快到了吧。


        phpConf 2016兩天的票是分開賣的,第一天主要是由講者分享php的想法、演變或實際應用,早上由國外的兩個大神,分別是Josh Lockhart(現代php的作者和Slim Framework、PHP The Right Way)、Sebastian Bergmann(PHPUnit的作者)做分享。

        Josh Lockhart這次的主題為:Become a better PHP developer.

        很多人常常會問Josh該怎麼樣變成一個senior developer,而在回答無數個一樣的問題之後,Josh整理出一套完整的觀念之後,在這次分享給大家。

        一開始,Josh就表明不會在這個topic裡面提到關於任何技術,或是任何的php code,因為要成一個better developer,所靠的不會僅僅只有技術,更重要的是必須要注意下列幾項事情:

  1. PHP is only a tool.
        PHP僅僅是達成目標的一種工具,並不一定把所有重點都放在php,或是php 單一framework,假設你會laravel,然後就每一個專案都用laravel去解決,那麼就是不適當的,正確方法應該是用適合的工具去解決相對應的專案,畢竟PHP is only a tool,人類解決問題的時候,當然不可能永遠使用一個工作去做。

      2. Work smart, not hard.

        這部分我有點忘了,大意就像句子裡所說的,用腦子工作,不要硬幹,如果已經有套件能夠解決你的問題(其實大部分都可以),那麼就不要自己重新寫一個,也就是「重造輪子」,自己寫一個的解決方法先不說品質,用優秀的套件的話,等於擁有一個上百人甚至幾萬幾千人的團隊同時在幫你維護專案,這戰力,猛!

      3. people is your assets

        Josh今天的重點幾乎都是圍繞在這點:「 周圍的人都是你的資產」。

       聽完整個topic之後,要成為一個更好的開發者,Josh認為最重要的還是在於人跟人之間的相處,這點在QA的時後也有一直提到,所以我之後會把這點單獨整理成一篇文章。

      4. keep it simple

        程式碼不光是寫給機器看的,也是寫給人看的,不管是哪天走在路上被公車撞到(轉述Josh口吻)讓下個人要接,或是未來的你回來維護,發現一堆髒code,一定馬上崩潰,所以最好保持程式碼簡單易讀,工作起來才會愉快又有效率。

      5. share knowledge 

        就像PHPConf上的講者一樣,當你學到一個階段之後,盡量把技術也分享出來,大家一起學習,問個問題,互相交流,甚至在網路上寫blog,都可以彼此幫助成長。

        或許學到的東西有些地方缺了,別人的提問可以幫你補上,也或許技術基本掌握了,卻可以從更厲害的人身上看到不同的角度。



        至於Sebastian Bergmann,說實在我幾乎跟不上,不知道是不是我沒用過PHPUnit的關係,他前面的投影片講解都聽不太懂,還有些參雜了有點像組合語言的東西,讓我意識到,似乎腦子也是要有點基礎才能再往上一層,就跟蓋晴空塔一樣(硬要提到)。

        後半段就大概介紹PHPUnit和php的支援期限,直得注意的是php5.6在今年年底,也就是2016-12-31之後,就不會再修復Bug了,所以Sebastian也強烈建議換到PHP7,效能、使用記憶體也都較PHP5好。

        而對於PHPUnit,Josh和Sebastian共同的看法是:「 我現在每個專案一定會用PHPUnit,無法想像沒有它會變成怎麼樣。」


        至於下午的場次非常多,有workshop、單一時間兩場講座還有兩位大神的QA,結果QA的到場人次很少,所以每個人想問的問題一定都會被問到,我也用破英文發問,結果好像大神們都聽不太懂,但還是很盡責地把自己的理解加上一些經驗鉅細彌遺的解答,一點都沒有架子。


∆ 開始前一分鐘的場地

        我選擇的講座分別是「 Refactoring to Collections - 從陣列重構談物件導向程式設計 」和「 用 Laravel + Vue.js 打造即時資訊看板 」。

        前著收穫蠻大的,不過當array裡面的value過多的時候,講者也提到這個topic的用法不適用,因為今天主要在程式碼可讀性,而value過多的時候效能也會不佳,這時候就要做個取捨。

        後者有點可惜,DEMO出來的成果蠻有趣的,但由於我沒有Vue.js的知識,Laravel也停留在基礎階段,所以沒辦法完全抓住己者的精髓。

        最後提一下兩位大神的個性,Josh Lockhart感覺比較像用功的大學生,殷殷教誨,講話的時候神情認真且語調真誠;而Sebastian Bergmann比較像是江湖走跳出來的,表情語氣都很靈活調皮,但是回答到重點的時候,表情會突然很嚴肅,但講完之後眼珠子一轉,又回到之前鬼靈精的感覺。

        蠻有趣的,兩個人都是PHP界的翹楚,個性卻是天差地遠。


∆ 左邊Sebastian Bergmann,右邊Josh Lockhart

        總歸來說,今天的主議程整體來說很不錯,工作人員人都非常好,會議廳環境很不錯,除了一開始幫Josh調電腦的時候似乎有點卡卡的,但整天下來,專業度還是挺高的。



error_log寫入及php tag表頭支援的php版本

        之前寫php的時候完全沒注意warning,寫出了很多不嚴謹的code,不過當時也沒特別在意,想說只是顯示一下而已,在參數裡面改成看不見就好了。

        沒想到最近看到切割空間竟然快沒了,可是切了40g啊!一個中小系統的規模而已,在注意看了一下,centos6環境下的/var/log/httpd/error_log竟然足足佔了38G,稍微看了幾行發現,這不都是之前在php上的warning嗎?!

        全部都記錄下來了,而因為數量太多,才過了幾十天就無法控制了,於是趕緊把warning打開,先把一些error_log裡面記錄看起來很多的warning休一下,再來放置個一兩天,果然error_log的大小增長緩慢許多。

        這邊要注意一下,當我們把error_log從裡面刪除之後,要記得重啟httpd,像在centos就是:

service httpd restart

        伺服器才會繼續寫error_log出來。




        今天也同時注意到一個php版本轉換的tag差異,以往我們在html tag裡面要echo php的值的時候,我們都會像這樣寫:

<div><?php echo $myValue; ?></div>

       不過php在5.4.0之後,你再也完全不用擔心是否調整了php.ini裡面的short_open_tag參數,可以毫無顧忌地使用下列程式碼:

<div><?= $myValue; ?></div>

        但相對而言,如果你沒有辦法完全掌握你未來專案正式上線之後的環境,那麼使用最原始的<?php echo 還是最安全的,如果版本是5.3.x甚至更舊,而且也沒有調整任何參數,那網頁上將直接顯示出來div裡面所有的東西,也就是完整的tag。



參考資料:

http://php.net/manual/en/migration54.new-features.php

2016年10月27日 星期四

alpha beta rc stable之軟體版本週期

        之前都使用最新的php版本7.1.0,不過一直在beta版。


        今天試著brew upgrade了一下,發現beta變成RC5了。


        咦,RC5是什麼意思?趕緊查一下wiki!

        beta版的意思是產品已經差不多開發完成了,可以開放給部分的使用者用用看,以公司來講的話,通常會給一些公司的熟顧客或是親戚好友之類的使用,看看哪邊還要改進的,像silicon valley主角的公司發的邀請函一樣,請大家給點意見。

        alpha版的意思則是內部測試專用,相對beta版會有較多問題,當內部測試alpha版到一個地步之後,討論過覺得OK就會發佈beta版了。

        至於RC版又更穩定了,全名為:Release Candidate,意思是此版本已經是發佈候選了,如果沒出什麼毛病,大概就是會推出這個版本。

        而如果依然有些小地方需要調整的話,RC後面的數字會隨著每一次的更新往後推,像剛剛上面的圖示一樣:


        可以看到7.1.0RC5,代表RC版本已經是發佈以來第四次更新了,不過看了官方發佈消息:


        最新訊息竟然只有RC4,不小心更新到外星人版本了嗎?

        最後發現php官方的文檔似乎會在版本發佈之後才正式更新消息,於是就在剛剛:


        請注意看最後一行話:

THIS IS A DEVELOPMENT PREVIEW - DO NOT USE IT IN PRODUCTION!
  
        這是開發預覽版,千萬別用在專案上!

        至於正式推出穩定版(stable)之後,以php來說,後面就不會再接任何的版本解釋,意思就是這就是最穩定版本了,可以安心的使用在正式專案上。


        目前7.1還沒有完全穩定,需要用php7當作上線環境的話,使用7.0會相對穩定許多。


2016年10月26日 星期三

「 人月神話 」掃讀雜記 2

        給予技術人員專注

        管理者必須尊重技術人員的專業,信任技術人員提出來的見解,再做適當的業務評估,並全力保護技術人員的注意力,給予他們完全專注的環境。

        目前我待的小公司,跟一般的小公司一樣,人力是需要多樣化使用的,電話一來,負責專門解決客戶業務上的問題的人都忙線,勢必要幫忙接電話,偶爾掛號、包裹甚至員工自己的網拍會按門鈴,還要去開門(不過來了一個新人幫忙之後,就很少去了),還有很多有的沒的雜事,對於一個程序員來講,這些都是嚴重剝奪注意力的事情。

        小公司的確能讓員工學到很多東西,但注意力容易分散就是其中一個可怕的代價,身在其中的情況下,我本身就先盡量不去剝奪別人的注意力,像不訂網拍到沒有大樓管理的公司,如果問的問題沒有辦法對我現在的難題有極大的推進,盡量不會去問公司其他的工程師。

         目前的位置沒有參與公司的核心業務裡,所以我似乎是公司裡面可以帶耳機幫助注意力集中的人,這點還是挺好的。


        

「 人月神話 」掃讀雜記

        1. 專案時程估計

        在估計專案時程的時候,必須要把測試的比重佔到時程一半以上,前期規劃次之,真正實作時間最少。

        實際開始專案的時候,傳統的作法會把功能實作估到deadline沒多久前,想說在實作的同時也一直在de bug,當實作結束的時候,想必bug也差不多沒了吧。

        沒想到交貨前,給公司內部總測試的時候,一些之前沒發現的bug開始浮出來,於是又瘋狂趕工,趕得出來還好,趕不出來得延期交貨,客戶失去信任感,公司也失去信譽,工程師在業界的名聲可能也會打折扣。

        所以在規劃時程的時候,絕對要分配最多時間給測試。

        2. 錯誤的增加人手時機

        我剛進公司的時候,大概有兩個禮拜的適應期,兩個禮拜之後被交派一個小小的除錯任務,由於這個任務不太緊急,所以依然可以繼續跟資深的工程師討論之前的架構,又經過了兩三天,bug解決。

        不過有些專案在已經很趕的狀況下,增加人手可能不會帶來預期中的效益,人力吃緊沒錯,想透過增加人手來加快開發速度的狀況會演變成老手需要撥出珍貴的時間來幫助新手進入狀況,當新手進入狀況之後,產能或許不會比老手把全部時間投入在專案裡面還要來得高。

        這時候精簡一些功能,或是調整一下工作時程會是一個相對適合的做法。

        3. 一個高手 vs 十個凡人

        在台灣,傳統公司徵工程師的思維還是停留在夠用就好,東西能work就好,不會去考慮比較未來的問題,但幾乎沒想過一個問題,一個高手的戰力,可以電爆十個凡人甚至等比級數上漲。

        十個凡人並沒有非常優秀的工程思維,幾乎都還停留在程式能動就OK的階段,不會去考慮擴充性及可維護性。

        一個高手有很好的架構思維,clean code、好接手、好維護、好擴充,非常優質的程式碼,就算之後離職了,下一個接任的是新手,也能維持一段時間不crash,更重要的是生產力屌打凡人的同時,完全不會影響到程式碼的品質。

        以前有聽到一個故事:一個老闆說我為什麼要給你66k?你的薪水我可以請三個22k。

        而網路有一句話完美的回擊:生病的時候你要選一個30萬醫藥費的頂尖醫師,還是10個3萬的新手醫師?

        老實說我現在也有困擾,我是個凡人,還是個最初階的凡人,公司請我開發新專案的時候,畢竟經驗實在不足,雖然公司有另一個經驗豐富的工程師可以問,難免還是有種力不從心的感覺。

        相信老闆心中也瞭解,一個剛入行沒多久的開發出來的產品能優秀到哪,所以我很感謝他,還願意給我這個機會繼續在公司歷練,有很多專案能加入自己成長的軌跡。