2015年1月9日 星期五

PHP常見問題

取某段字串裡的數字
preg_match_all('!\d+!', $str, $matches);
取某段字串裡的日期 (我們假設日期格式是 YYYY-MM-DD HH-ii-ss)
preg_match('/^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}/', $str, $matches);
去除前後的空白
$ php -r '$str = "  hello world  "; echo trim($str);'
hello world
參考資料:
http://stackoverflow.com/questions/6278296/extract-numbers-from-a-string

去除陣列所有字串前後的空白
http://stackoverflow.com/questions/6769464/how-can-i-trim-all-strings-in-an-array
使用array_map()
$source_array = array(" hey ", "bla ", " test");
$result = array_map('trim', $source_array); // $result = array("hey", "bla", "test");


開發時在網頁上顯示錯誤
編輯/etc/php5/apache2/php.ini 修改以下設定
error_reporting = E_ALL
display_errors = On
( nginx+fpm )
If you have /etc/php5/fpm/php.ini (used in Debian, Ubuntu style config) then changes to this file should take effect, and that configuration may be further overridden per pool by making changes to specific /etc/php5/fpm/pool.d/*.conf files.
如果你有 /etc/php5/fpm/php.ini (Debian, ubuntu) ,則編輯修改以下設定即可(採用)
; enable display of errors
display_errors = On
display_startup_errors = On
而該設定會被 /etc/php5/fpm/pool.d/*.conf 的設定覆蓋,例 ( /etc/php5/fpm/pool.d/www.conf ):
; enable display of errors
php_flag[display_errors] = on
php_flag[display_startup_errors] = on


註:
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT =>產品上線用
; Development Value: E_ALL => 開發用
參考資料:
http://stackoverflow.com/questions/5680831/php-does-not-display-error-messages
http://stackoverflow.com/questions/13929314/display-errors-for-php5-fpm-not-working-with-nginx  display_errors for php5-fpm not working with nginx

在PHP腳本中修改錯誤輸出的級別
error_reporting(0); // Turn off all error reporting
error_reporting(E_ALL ^ E_NOTICE); // Report all errors except E_NOTICE, This is the default value set in php.ini
http://stackoverflow.com/questions/2867057/how-do-i-turn-off-php-notices


file_put_contents的LOCK_EX 參數
在php.net中,file_put_contens的描述是
int file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] )
而地三個參數$flags常用的有:
FILE_APPEND=>直接在該檔已有的內容後面追加內容
LOCK_EX=>寫檔的時候先鎖定,防止多人同時寫入造成內容丟失
當需要頻繁操作file_put_contents函數寫txt檔時,經常出現前半截內容缺失的情況,非常苦惱。此時LOCK_EX非常有用,加上它之後,再也沒有出現過內容缺失的情況了。LOCK_EX的意思很直白,就是寫檔時,先鎖上這個檔,這樣只允許某個客戶端訪問的時候寫,其他客戶端訪問不能寫了。
http://www.wyxuan.com/184.html  PHP写文件函数file_put_contents确实给力


unlink()函數
unlink() 函数删除文件。若成功,则返回 true,失败则返回 false。
Ex.
$ touch test2
$ ls
smarty  test  test2
$ php -r 'unlink("test2");'
$ ls
smarty  test

php的refrence符号&用法
& 可以當二位元AND運算也可以當reference,以下為reference的例子
$arr = array(1, 2, 3);
function a(&$arr2){
 foreach ($arr2 as &$value) {
  $value = $value*$value;
 }
 echo '$arr2:';
 print_r($arr2);
 // print_r($arr); // Notice: Undefined variable: arr
}
a($arr);
echo '<br>$arr:';
print_r($arr);
// print_r($arr2); // Notice: Undefined variable: arr2
// a(&$arr); // Fatal error: Call-time pass-by-reference has been removed => And as of PHP 5.4.0( PHP Version 5.6.8 on my server ), call-time pass-by-reference was removed, so using it will raise a fatal error.

輸出:
$arr2:Array ( [0] => 1 [1] => 4 [2] => 9 )
$arr:Array ( [0] => 1 [1] => 4 [2] => 9 )

如果a(&$arr)這樣呼叫,在PHP5.3.0會產生警告,在PHP5.4.0+會產生fatal error.

以純變數為例子:
$a='小妹哥';
$b=$a;
$c=&$a;
$b='大妹哥';
$c='拉屎小妹哥';
echo $a;
輸出:
拉屎小妹哥

傳值呼叫(call By Value) - 將變數的值傳入函數,並不會更變原來的值
傳址呼叫(call By Reference)將變數實際儲存的位址傳入,在函數變更參數值,也會同時更變傳入的變數值

參考資料:
http://stackoverflow.com/questions/3737139/reference-what-does-this-symbol-mean-in-php Reference - What does this symbol mean in PHP?
http://www.php.net/manual/en/language.references.php References Explained
http://php.net/manual/en/language.references.pass.php Passing by Reference
http://syunguo.blogspot.com/2013/04/php_1.html  [PHP]傳址與傳值呼叫

array_chunk()
http://w3school.com.cn/php/func_array_chunk.asp
把array分割,chunk=>大塊 的意思
Ex.
preserve_key = true - 保留原始数组中的键名
$ php -r '$a=array("a"=>"Cat","b"=>"Dog","c"=>"Horse"); print_r(array_chunk($a,2,true));'
Array
(
    [0] => Array
        (
            [a] => Cat
            [b] => Dog
        )

    [1] => Array
        (
            [c] => Horse
        )

)

$ php -r '$a=array("a"=>"Cat","b"=>"Dog","c"=>"Horse","d"=>"Cow"); print_r(array_chunk($a,2));'
Array
(
    [0] => Array
        (
            [0] => Cat
            [1] => Dog
        )

    [1] => Array
        (
            [0] => Horse
            [1] => Cow
        )

)

array_slice()
http://www.w3school.com.cn/php/func_array_slice.asp
陣列中根據條件取出一段值,並返回
Ex.
從第二個開始往後取兩個
$ php -r '$a=array("e"=>"Cat","b"=>"Dog","c"=>"Horse","d"=>"Cow"); print_r(array_slice($a,1,2));'
Array
(
    [b] => Dog
    [c] => Horse
)
從倒數第二個(與key的升降冪無關)開始往後取兩個
$ php -r '$a=array(5=>"Cat",1=>"Dog",2=>"Horse",3=>"Cow"); print_r(array_slice($a,-2,2));'
Array
(
    [0] => Horse
    [1] => Cow
)
preserve = true,數字型key保留鍵值
$ php -r '$a=array(5=>"Cat",1=>"Dog",2=>"Horse",3=>"Cow"); print_r(array_slice($a,-2,2,true));'
Array
(
    [2] => Horse
    [3] => Cow
)

字串轉unicdoe,unicode轉字串
http://stackoverflow.com/questions/7106470/utf-8-to-unicode-code-points
function unicode2utf8($str){
    if(!$str) return $str;
    $decode = json_decode($str);
    if($decode) return $decode;
    $str = '["' . $str . '"]';
    $decode = json_decode($str);
    if(count($decode) == 1){
            return $decode[0];
    }
    return $str;
}
echo json_encode('測試'); // \u6e2c\u8a66

echo "
unicode2utf8('\u6e2c\u8a66'):".unicode2utf8('\u6e2c\u8a66'); // 測試
s

快速檢查必填欄位有無缺失(無法判斷是缺哪個欄位)
http://stackoverflow.com/questions/13169588/how-to-check-if-multiple-array-keys-exists
//The values in this arrays contains the names of the indexes (keys) that should exist in the data array
$required = array('key1', 'key2', 'key3' );

$data = array(
    'key1' => 10,
    'key2' => 20,
    'key3' => 30,
    'key4' => 40
);

if(count(array_intersect_key(array_flip($required), $data)) === count($required)) {
    //All required keys exist!              
}

過濾掉不合法的欄位
http://stackoverflow.com/questions/4260086/php-how-to-use-array-filter-to-filter-array-keys
$my_array = array("foo" => 1, "hello" => "world");
$allowed = array("foo", "bar");
$inserted_data = array_intersect_key($my_array, array_flip($allowed)); // array("foo" => 1);

計算生肖
https://en.wikipedia.org/wiki/Chinese_zodiac
必須把每年除夕的日子存起來,再另外處理。最後我只用國曆做簡單的判斷

PHP多維陣列搜尋(由值找key)
http://stackoverflow.com/questions/8102221/php-multidimensional-array-searching-find-key-by-specific-value
function search($columns, $field, $value){
    foreach ($columns as $key => $column) {
        if ($column[$field] === $value) {
            return $key;
        }
    }
    return false;
}

$products = array (
1  => array(
        'shortname'     => 'The One-Touch Tea Maker',
        'price'         => '249.99',
        ),

2  => array(
        'shortname'     => 'Variable Temperature Kettle',
        'price'         => '129.99',
        ),
);

$key = search($products, 'shortname', 'Variable Temperature Kettle');
echo "\$key:".$key;
輸出:
$key:2
(找$porducts 中 shortname為 Variable Temperature Kettle 的key值(通常為id))

備份上傳的檔案(框架以ThinkPHP為例)
http://www.w3school.com.cn/php/func_filesystem_copy.asp
$project_path =pathinfo(THINK_PATH, PATHINFO_DIRNAME);
$import_path = $project_path."/Uploads/import";
$file_name = "import-".microtime(true)."-".$_FILES['excel']['name'];
$file_full_path = $import_path."/".$file_name;
copy($_FILES['excel']['tmp_name'],$file_full_path);
注意:
input[type=file]的name記得要寫$_FILES['excel']['tmp_name'],不然抓不到檔案會複製不出結果

從陣列的值求其key
http://stackoverflow.com/questions/8729410/php-get-key-name-of-array-value
$arr = array ('first' => 'a', 'second' => 'b', );
$key = array_search ('a', $arr); // $key = 'first'
array_search()可以從值反查key

避免PHP Deprecated:  preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in xxx.php on line xx錯誤
http://stackoverflow.com/questions/2082207/calling-function-inside-preg-replace-thats-inside-a-function  calling function inside preg_replace thats inside a function
http://stackoverflow.com/questions/21334934/deprecated-preg-replace-the-e-modifier-is-deprecated-use-preg-replace-call  Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in
http://stackoverflow.com/questions/20951133/deprecated-preg-replace-how-to-convert-to-preg-replace-callback  Deprecated: preg_replace(): How to convert to preg_replace_callback?
直接看程式
error_reporting(E_ALL);

function embed_video($url) {
 echo "\n\$url:".$url;
    return $url;
}

$result = "[video]http://youtube.com/id/xxxxxxpron[/video]";
$result = preg_replace(
    "/\[video\](.+?)\[\/video\]/e",
    "embed_video('$1')",
    $result
);
echo "\n\$result:" . $result."\n";

$result2 = "[video]http://youtube.com/id/xxxxxxpron[/video]";
$result2 = preg_replace_callback(
    "/\[video\](.+?)\[\/video\]/",
    function($matches) {
     print_r($matches);
        return embed_video($matches[1]);
    },
    $result2
);
echo "\n\$result2:" . $result2;
結果:
PHP Deprecated:  preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in xx.php on line 14
$url:http://youtube.com/id/xxxxxxpron
$result:http://youtube.com/id/xxxxxxpron
Array
(
    [0] => [video]http://youtube.com/id/xxxxxxpron[/video]
    [1] => http://youtube.com/id/xxxxxxpron
)
$url:http://youtube.com/id/xxxxxxpron
$result2:http://youtube.com/id/xxxxxxpron

注意:
改成preg_replace_callback後,第一個參數 $pattern ( "/\[video\](.+?)\[\/video\]/e" ),必須把 替換操作符 的 /e ( 替換字符串作為表達式 ) 拿掉,否則會報錯
PHP Warning:  preg_replace_callback(): Modifier /e cannot be used with replacement callback in xx.php on line xx
Don't use the \e modifier in your preg_replace_callback() call or php will throw the following warning and return nothing
不要使用 modifier 在 preg_replace_callback() 呼叫,否則php會丟警告且返回空值

較簡單的範例
error_reporting(E_ALL);

$x = 'abcd-efg-hijk-lmnop';

$x = preg_replace(
    '/-(.)/e', //pattern
    "strtoupper('$1')",
    $x //subject
);

echo "\n\$x:" . $x . "\n"; //abcdEfgHijkLmnop

$x = 'abcd-efg-hijk-lmnop';

$x = preg_replace_callback(
    '/-(.)/', //pattern
    function ($matches) {
        //callback
        print_r($matches);
        return strtoupper($matches[1]);
    },
    $x //subject
);

echo "\n\$x:" . $x; //abcdEfgHijkLmnop
結果:
PHP Deprecated:  preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in xx.php on line 10

$x:abcdEfgHijkLmnop
Array
(
    [0] => -e
    [1] => e
)
Array
(
    [0] => -h
    [1] => h
)
Array
(
    [0] => -l
    [1] => l
)

$x:abcdEfgHijkLmnop

避免PHP Strict Standards:  Only variables should be passed by reference in strict_standards.php on line xx錯誤
http://stackoverflow.com/questions/9848295/strict-standards-only-variables-should-be-passed-by-reference-error  “Strict Standards: Only variables should be passed by reference” error
直接看程式
error_reporting(E_ALL);
$value = "a.b.c.d";
$extension = strtolower(array_pop(explode(".", $value)));
print_r($extension);
結果:
PHP Strict Standards:  Only variables should be passed by reference in /home/ds/strict_standards.php on line 6
d

解法:
把explode()放到外面處理,多一行
error_reporting(E_ALL);
$value = "a.b.c.d";
$explodes = explode(".", $value);
$extension = strtolower(array_pop($explodes));
print_r($extension);
結果:
d
( PHP Strict Standards 錯誤沒了 )

檢查class有無方法和在一行中if兩次
http://stackoverflow.com/questions/10287789/check-if-class-has-method-in-php
$where = (method_exists($Model, "get_where")) ? $Model->get_where() : ( (isset($this->_map['where']))? $this->_map['where'] : null );
1. 使用 method_exists($Class, "method_name") 檢查
2. 在一行中使用兩次if:$result = ( condition1 ) ? a : ( ( condition2 )? b : c );

得到陣列中最後一個key
http://stackoverflow.com/questions/2348205/how-to-get-last-key-in-an-array
$array = array(
    'first' => 123,
    'second' => 456,
    'last' => 789, 
);
end($array);         // move the internal pointer to the end of the array
$key = key($array);  // fetches the key of the element pointed to by the internal pointer
echo $key; // last, 但$array的順序是不變的

使用sprintf連結字串
http://www.w3school.com.cn/php/func_string_sprintf.asp
喇叭王:要組合字串都改用sprintf,考量之後維護的人的關係。今天要是這字串比較長 超過一個畫面 你在維護的時候怎麼知道裡面有幾個變數 你能保證不會看漏嗎
例:
$a = "Daniel";
$b = "Lin";
$c = "Laba King";
$text = sprintf("%s %s, %s",
    $a,
    $b,
    $c
);
echo $text."\n";
$text2 = $a." ".
    $b.", ".
    $c;

echo $text2;
結果:
Daniel Lin, Laba King
Daniel Lin, Laba King
結果是一樣的,看起來用sprintf()好像比較好

XML字串轉陣列
http://stackoverflow.com/questions/12148662/xml-to-array-php
使用json_decode(json_encode(simplexml_load_string($xml)),TRUE)
$s =<<<EOS
<root>
<Formula>
<formulaname>Basic</formulaname>
<movespeed>1</movespeed>
<box>4</box>
<chicken>3</chicken>
<ducks>1</ducks>
<cereal>2</cereal>
</Formula>
</root>
EOS;
$array = json_decode(json_encode(simplexml_load_string($s)),TRUE);
echo "<pre>\$array:";
print_r($array);
echo "</pre>";
結果:
$array:Array
(
    [Formula] => Array
        (
            [formulaname] => Basic
            [movespeed] => 1
            [box] => 4
            [chicken] => 3
            [ducks] => 1
            [cereal] => 2
        )
)

in_array() 的BUG
https://stackoverflow.com/questions/7669589/in-array-does-not-work-as-expected
in_array('string', [1,0])  // true,因為 0 == "string"true
in_array('string', [1,0], true)  // false. working as expected

兩個變數中的&
https://stackoverflow.com/questions/22376222/what-does-a-single-ampersand-operator-do-in-php
What does a single ampersand ('&') operator do in PHP?
這是bitwise operator AND
ex.
$a =     9;
$b =     10;
echo $a & $b;

place value   128  64  32  16   8  4   2   1
$a                     0   0    0    0    1   0   0   1   =9
$b                     0   0    0    0    1   0   1   0   =10

result   8

使用microtime(true)計算php程序代碼執行消耗時間
https://blog.csdn.net/eflyq/article/details/19130141
https://stackoverflow.com/questions/33107182/php-microtime-is-correct
$start = microtime(true);
// code
$time_elapsed_secs = microtime(true) - $start; // code執行了多少「秒」


laravel判斷model的特定欄位是否被更改

https://stackoverflow.com/a/28866535  Laravel Eloquent update just if changes have been made
https://stackoverflow.com/a/40544518  How to search if the key value in an array exists in another array, using PHP?

$dirty = $user->getDirty();
$columns = [
    'phone', 'address',
];
if (array_intersect(array_keys($dirty), $columns)){
    // 用戶電話或地址已被更改
}
s








沒有留言:

張貼留言