Skip to content

Zeroplex 生活隨筆

軟體開發、伺服器和生活瑣事

小 縮小字型大小。 中 重設字型大小。 大 放大字型大小。

標籤: PHP

PHP 近幾年生態圈一些可惜的地方

Posted on 2018 年 1 月 5 日2021 年 3 月 12 日 By 日落 在〈PHP 近幾年生態圈一些可惜的地方〉中尚無留言

進幾年 Laravel framework 竄紅,大家也趨之若騖,相對其他的 framework 就被冷落了,實在有點可惜。

Laravel 有其特色,但個人用了幾個版號,覺得 Laravel 比較適合中大型專案、以及快速開發,在往後維護和升級難度都不低 (5.1 migrate 到 5.4 根本是地獄)。

php-framework-benchmark at 2017/02

而如雨後春筍般冒出來的 Laravel library 很多又只能供 Laravel 使用,很難在其他 framework 上使用。Laravel 開發出來的元件耦合度也不低,很難拉出來供其他人使用 (Symfony 的各個元件都是 library,可以透過 composer require 供需要者使用)。結果讓想要使用其他 framework 的人找不到資源可以使用,少了很多選擇。

個人比較想看到的是,各種 framework 都能有社群協助一起發展,PSR 把一些好的設計制定成開發規範,大家遵守便能讓一個 library 在多個平台使用,而不是讓 Laravel 獨大,讓 PHP 的生態系變得單調、沒有選擇。

最近因公司需要而翻了近十個 framework、以及 CRM,並從中截長補短撰寫適合公司使用的 framework,希望以後有時間可以整理成公版讓其他有類似需求的人也來用看看。(本來想再愚人節發布的,似乎來不及了 TAT)

Tags:PHP, 生活雜記

PHPStan 靜態分析工具

Posted on 2018 年 1 月 4 日2021 年 3 月 12 日 By 日落 在〈PHPStan 靜態分析工具〉中尚無留言

前陣子從 gslin 那邊看到 PHPStan 這個工具,剛好手上有需要測試的程式,就拿來掃一掃。常見的問題大多都可以抓到,甚至連 doc comment 有錯誤也會抓出來。

下面弄個個 demo code 讓大家稍微看一下實際狀況。

Hello.php:

<?php
namespace Zero;

class Hello
{
    /**
     * @param array $name
     */
    public function greeting(): void
    {
        $test = '123';
        echo "Hello $namen";
    }
}

bootstrap.php:

<?php
require __DIR__ . '/../vendor/autoload.php';

$hello = new ZeroHello();
$hello->greeting(123);

然後執行 PHPStan 做 level 5 的分析:

 ------ ------------------------------------------------------ 
  Line   src/Hello.php                                         
 ------ ------------------------------------------------------ 
  10     PHPDoc tag @param references unknown parameter $name  
  14     Undefined variable: $name                             
 ------ ------------------------------------------------------ 

 ------ --------------------------------------------------------------------- 
  Line   src/bootstrap.php                                                    
 ------ --------------------------------------------------------------------- 
  7      Method ZeroHello::greeting() invoked with 1 parameter, 0 required.  
 ------ ---------------------------------------------------------------------

從 PHPStan 給的錯誤訊息,就可以在執行 PHP 之前預防錯誤發生。

不過有一些比較可惜的地方:

  • PHPStan 一定要吃 autoload 規則,看起來是為了要解 PHP Refelction 問題,所以比較就的程式就 GG 了
  • Hello.php 裡面有個沒使用到的變數 $test 沒有被抓到,不然應該可以再把程式清的更乾淨
Tags:PHP

PHP 將 HTTP POST field 的 . (dot) 改為 _ (underscore)

Posted on 2017 年 12 月 21 日2021 年 3 月 12 日 By 日落 在〈PHP 將 HTTP POST field 的 . (dot) 改為 _ (underscore)〉中尚無留言

今天遇到很奇怪的行為,在 PostMan 將 HTTP POST data 丟給 PHP 以後,參數名稱裡面有 . (dot) 的字元,全部都被改為 _ (underscore) 了。像是 field 名稱為「article.title」的欄位名稱,在 PHP 底下取值必須使用 $_POST[‘article_title’]。

原本以為 RFC 裡面有的定義 reserve word,但是找了半天找不到。最後原因是 PHP 為了支援 register_global,但是 PHP 變數名稱又不允許使用 . (dot) 當作名稱的一部分,最後就自動轉為 _ (underscore)。

這個行為不管有沒有啟動 register_global 都會出現,即使上了 PHP 7.2 都已經不支援了,這個行為仍然存在。

ref:

  • https://stackoverflow.com/a/3742678/8681141
  • PHP: Variables From External Sources – Manual


後來做了個簡單的測試,在 HTTP POST 依序送出二個 field data:

a.b=100&a_b=200

這時候再印出 $_POST:

var_dump($_POST);

array(1) {
  'a_b' =>
  string(3) "200"
}

所以後面的會打贏前面的 … (所以「世界上的戰爭沒任何人贏了,只有戰爭贏了」)

Tags:PHP

PHP 變數初始化 (?)

Posted on 2017 年 11 月 15 日2021 年 3 月 12 日 By 日落 在〈PHP 變數初始化 (?)〉中尚無留言

看到有 Java 工程師在學 PHP 遇到變數初始化的問題,覺得有趣,做個筆記順便複習 PHP 的特性。

Java 是強型別 (strong type) 的程式語言,所有的變數在使用之前都必須給資料型態以及初始值;PHP 則是弱型別,就算不給值、不給資料型態也沒差,interpreter 會在 runtime 的時候自動做型別轉換在繼續執行程式。我想 PHP 這一特性就會讓很多 Java 工程師決得很莫名其妙吧,沒定義的變數到底要怎麼用?執行的時候真的不會出事嗎? (其實就是會 XD)

先來看正常的寫法:

$x = 'hello';
var_dump($x);  // "hello"

如果變數沒有給值會發生什麼事?

var_dump($x);  // NULL

PHP 把沒有初始化的變數帶入 NULL 來使用,連錯誤訊息都沒噴耶?其實有,只是要調整一下 error reporting 的 level:

error_reporting(E_ALL);

var_dump($x);

// Notice: Undefined variable: x
// NULL


如果拿一個完全沒有被初始化的變數做運算,interpreter 到底會怎麼轉型:

var_dump('123' . $x);  // "123"

$x[] = '123';
var_dump($x);  // array([0] => "123")

好像很強耶,居然會自動轉陣列!那換個方式來玩玩看:

$list = [1, 2, 3];

array_merge($list, $x);

// PHP Warning:  array_merge(): Argument #2 is not an array

其實還是會遇到 interpreter 沒辦法幫你作主的時候。

以 PHP 這類的弱型別寫法,比較保險的作法就是去檢查要被使用的變數到底是否有初始化:

if (isset($x)) {
    var_dump($x);
} else {
    echo 'undefine';
}

// "undefine"

所以使用 PHP 寫程式時變數到底是否需要初始化?其實可以不用,但是若要保險起見 (防禦性程式設計),要用到的變數建議都要初始化、或是做檢查。StackOverflow 上也有提到:
PHP does not require it, but it is a good practice to always initialize your variables.

Tags:PHP

PHP curl 的一些特性

Posted on 2017 年 10 月 9 日2021 年 3 月 12 日 By 日落 在〈PHP curl 的一些特性〉中尚無留言

curl 在 PHP 中是以 extension 形式存在,所以只能透過 resource reference 去操作 curl 行為,沒辦法透過 debug 工具摸清楚 curl 在背景到底做了哪些事情。

手癢用 memory_get_usage() 看了一下 curl 在 init、exec 以及 close 這幾個狀態的記憶體使用量,來猜測 curl 到底怎麼運作。

echo memory_get_usage() . "n"   // 236136;

$ch = curl_init();
var_dump($ch);                   // resource(4) of type (curl)
echo memory_get_usage() . "n";  // 237472

在 init_curl() 以後,會先在記憶體中 allocate 並放一些資料,所以吃掉大概 1 KB 左右的記憶體,再將 curl 的 reference 傳出來給 $ch。

接下來這邊讓 curl 去 http://assets.blog.zeroplex.tw/2017-07/php-bench-v2.html 抓一個大小 128 KB 的網頁,並看一下記憶體使用量:

echo memory_get_usage() . "n"  // 235744;

$ch = curl_init();
echo memory_get_usage() . "n";  // 237072

curl_setopt($ch, CURLOPT_URL, "http://assets.blog.zeroplex.tw/2017-07/php-bench-v2.html");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_exec($ch);
echo memory_get_usage() . "n";  // 371784

curl_close($ch);
echo memory_get_usage() . "n"  // 235928;

var_dump($ch);                  // resource(4) of type (Unknown)

由整個記憶體使用量,可以看出在 curl_exec() 之後,會把傳回來的資料除存在記憶體中,除了網頁 128KB 的內容以外,可能還包括一些與 HTTP 連線有關的資料,所以記憶體使用量增加了 130 KB (371784 – 237072 = 134712) 左右。這些資料存在於記憶體中,直到呼叫了 curl_close() 才會釋放掉。

比較有趣的是 PHP 官方文件只有提到 curl_close() 會關閉 session,但是沒有提到用來儲存 resource 的 $ch reference 會如何。上面可以看到 curl_close() 以後,其實 resource refence 還存在,只是 resource 已經被 released,所以 type 顯示為 unknown。

由此可知,沒有 unset($ch) 還拿原來的 resource reference 亂用的話應該會大爆炸 XD

最後來看一下,如果沒有做 curl_close() 就一直做 curl_exe() 抓多個網頁,到底會不會有 memory leak 問題發生:

for ($i = 0; $i < 10; $i++) {
    curl_exec($ch);
    echo memory_get_usage() . "n";
}

執行結果如下:

369424
369976
372568
370856
372568
372568
372568
372568
370856
372568

所以看起來每次執行 curl_exec() 之前,curl 會自動將上一次的 response 清掉在重新做 request,所以記憶體不會無止境的增加。換而言之,如果今天有很複雜的 curl_setopt() 要處理,可以不用一直 reset curl 也不會有問題,setopt 只要做一次就可以了,可以省下一些時間。

原本想要測試一下 keep alive 的效果如何,但是沒有較為穩定的環境來測試,所以這邊就先跳過了。但大家可以參考 StackOverflow 上面的這篇「Persistent/keepalive HTTP with the PHP Curl library」來設定 keep alive。

Tags:PHP, 資訊學習

文章分頁

上一頁 1 ... 13 14 15 ... 26 下一頁

其他

關於我  (About me)

小額贊助

  文章 RSS Feed

  留言 RSS Feed

Apache AWS Bash C/C++ Docker FreeBSD GCP Git Google Java JavaScript Laravel Linux Microsoft MSSQL MySQL Nginx PHP PHPUnit PostgreSQL Python Qt Ubuntu Unix Vim Web Windows WordPress XD 作業系統 分享 好站推薦 專題 攝影 新奇搞笑 新聞 旅遊 生活雜記 程式設計 網路架站 網頁設計 資訊學習 資訊安全 遊戲 音樂


創用 CC 授權條款
本著作係採用創用 CC 姓名標示-相同方式分享 4.0 國際 授權條款授權.