Category: Programming

Best practice to generate random token in PHP

Posted by – January 10, 2017

在 Stackoverflow 看到一篇超級實用的文:在 PHP 中產生隨機字串的最佳實踐。

產生隨機字串這個看似不起眼的議題實作起來還挺麻煩的,曾經為了如何產生字串跟同事討論了許久。

$length = 16;
$token = bin2hex(openssl_random_pseudo_bytes($length));
# => e9bf18672b051619a3479ecbe1cb7d08

唯一的參數 $length 可以替換成任意整數,產生的字串長度就是 $length *2。

同場加映,Google Chrome 的亂數演算法也有改過

How to Flatten a Multidimensional Array in PHP?

Posted by – January 9, 2017

最近碰到的小需求:如何將多維陣列攤平成一維陣列?....

本來以為 PHP 那巨大的 Lib 會有一個神奇的 function 完成這任務,結果翻了一遍 php.net 的文件,沒有找到這神奇的功能。不過還是有另一個神妙的 function 可以拿來用,那就是 array_walk_recursive,這個 function 會有遞迴的方式走完整個 array,然後看使用者後續想幹嘛...

以攤平一維陣列為例,以下是只保留 value 的作法...

function flatten(array $array) {
  $return = array();
  array_walk_recursive($array, function($a) use (&$return) {
    $return[] = $a; 
  });
  return $return;
}

如此一來就可以將多維陣列轉為一維。若是要保留 key 與 value,要注意 key 名稱是否有重複 (isset)。

將 Sequel Pro 的表導出成 Laravel migration 文件

Posted by – December 23, 2016

Laravel 學院看到一篇有趣的文,筆記下。


将 Sequel Pro 中已存在的数据表导出为 Laravel 迁移文件

對於用 Mac 的開發者來說頗為實用。Sequel Pro 這款 MySQL GUI 也是我用過最好用、最順手的 DB 管理工具,沒有之一,輕巧高效,可惜支援的 DB 種類不多。

強制 fputcsv 所有欄位都加上雙引號

Posted by – August 2, 2016

公司跟一家新廠商展開合作,其中交換電文是用 CSV 格式。但對方要求所有的欄位都要用 " 雙引號包起來。看起來就像下圖這樣。

Screen Shot 2016-08-02 at 2.58.00 PM

但是很不巧的,PHP 內建產生 CSV 的指令 fputcsv 沒有提供強制的選項。做出來的檔案如下圖。

Screen Shot 2016-08-02 at 3.03.33 PM山不轉只好路轉...

在丟進 fputcsv 前就先用雙引號包一包。

<?php

function forceQuote($value) {
    return "\"$value\"";
}

$file = @fopen($file_path, "w");

foreach ($data['content'] as $line) {
    fputcsv(
        $file,                          // 輸出檔名
        array_map('forceQuote', $line), // 先包雙引號
        ',',                            // 資料用逗號分隔
        chr(0)                          // 跳脫預設的 enclosure 字元
    );
}

fclose($file);

比較特別是 fputcsv 原本的 enclosure 字元預設就是雙引號,無法替換成空白,只好用 chr(0) 來跳脫,不然每一筆資料會變成 """aaa""",三個引號…

這樣就可以交差了。

Connection could not be established with host

Posted by – July 19, 2016

最近重灌了工作用的筆電,把開發環境的 PHP 升級到 5.6.10,然後就各種狀況.....

其中一個問題是從本機連不上公司 mail server,所以寄信功能就掛掉了。Laravel log 的訊息如下

local.ERROR: 500 - Connection could not be established with host xxx.com.tw [ #0] @ /
exception 'Swift_TransportException' with message 'Connection could not be established with host xxx.com.tw [ #0]' in laravel/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php:270

原來是因為從 PHP 5.6 開始,變更了 SSL 認證的預設值,verify_peer 與 verify_peer_name 這兩項安全檢查都被改為預設,然後很多 SSL verification 就過不了。雖然提高安全性是好事,但開發環境卻造成一些困擾。

以上述的 swiftmailer 套件為例,它的 SSL 連線是用 stream_socket_client 實現的,其參數設置是透過 stream_context_create 傳入,所以設定方式如下:

$contextOptions = [
    'ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => false
    ]
];
$context = stream_context_create($contextOptions);
stream_socket_client(
    $host.':'.$port, 
    $errno, 
    $errstr, 
    $timeout, 
    STREAM_CLIENT_CONNECT, 
    $context
);

如此一來就可以關閉檢查,終於可以連上 mail server 了。收工。

How to get length of integers in PHP?

Posted by – May 25, 2016

在寫 code 的時候想到這個無關緊要的問題... 如何得知一個數字有幾位數?

比較直覺的想法是這樣....

function digits($num) {
    return (int) strlen((string) abs($num));
}

在 stackoverflow 看到一個也不賴的寫法....

function digits($num) {
    return (int) log(abs($num), 10) + 1;
}

筆記一下,都快忘了 log 怎麼算 XD

How to disable phone number linking in Mobile Safari?

Posted by – November 4, 2015

同事問了這個問題,如何將 iOS webview 裡出現的電話連結移除,因為畫面中出現了不是電話的數字,卻被系統自動加上了電話連結。

有一個非常簡單的方法,在 HTML 檔案的 <head> 區段加一行宣告即可。

<meta name = "format-detection" content = "telephone=no">

這行宣告會停用所有的電話連結。若是反過想要在停用的情況下,加上例外,則可以自行宣告電話連結,語法如下:

<a href="tel:0932123456">0932123456</a>

主要就是用 tel: 關鍵字來達成。

Laravel 5.0: 紀錄 SQL 指令

Posted by – August 22, 2015

在同事轉貼的一些文章裡翻到這篇记录运行时SQL语句,稍微修改一下,在我的 Laravel 5.0 測試站上實作。

文章中的第一步我就傻眼了,因為我的 php artisan list 裡面沒有 make:listener.... More

Javascript: 檢查生日是否成年

Posted by – August 17, 2015

接到一個開發需求,讓使用者填寫生日,然後用 Javascript 判斷是否滿二十歲。但是需要檢查到月和日... 總覺得有點懶。

Coding 發懶的時候,問 Stack Overflow 就對了....

function getAge(DOB) {
    var today = new Date();
    var birthDate = new Date(DOB);
    var age = today.getFullYear() - birthDate.getFullYear();
    var m = today.getMonth() - birthDate.getMonth();
    if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
        age--;
    }    
    return age;
}

總之先修改一下,寫了一個草稿試試。結果如下: More

Smooth Touch Scrolling in iOS with -webkit-overflow-scrolling

Posted by – April 17, 2015

在開發一個兼容 iPad 的網站專案時,發現 <div style="overflow: scroll;"> 在 iOS 下捲動很不順暢,手感很糟糕。好奇地搜尋了一下,找到一個 webkit 特有的語法:-webkit-overflow-scrolling: touch。加上這個屬性後,在 iOS Safari 上連回彈的效果都出來,手感與原生程式無異。

可惜 Android 上的 Chrome 似乎沒有作用,有點希望這屬性能成為正式語法。

範例先丟在 Codepen,不過看來要註冊才能 embed,先醬。
http://codepen.io/anon/pen/oXvjvJ