Skip to content

Zeroplex 生活隨筆

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

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

標籤: PHP

PHP 的小故事

Posted on 2025 年 8 月 25 日2025 年 8 月 25 日 By 日落 在〈PHP 的小故事〉中尚無留言

我接觸 PHP 蠻久了,大概從 5.1 還是 5.2 開始用到現在 8.4,避開了聽說很雷的 PHP 4,看著 PHP 引進新的功能,到現在社群開發出各種神奇的工具。

回顧過去一些事情,我覺得很重要的事情,不只可以了解 PHP 是什麼樣子程式語言,或許也可以協助判斷其他程式語言是否適合在你手上的專案使用。


就我所知,PHP 4 到 5 主要是支援物件導向,開始可以使用 class 來設計自己所需的功能,不用擔心 function name 和其他人的衝突。在這個時候,大家可以各自在網路上下載別人寫好的類別來使用,例如那個時候「藍色小舖」就有很多工程師分享自己實做的功能,例如 MySQL driver 之類的。

一些大型的專案仍保有這類的程式,像是 dolibarr ERP 的 /htdocs/core/class 目錄下,就有多個作者實做的 class。

在這個時候,功能比較複雜的專案可能會遇到類似的問題,我想要 require 新的 class 時,發現該 class 也有 require 其他的 class,如 dolibarr 的 fileupload.class.php:

<?php

/* Copyright (C) 2011-2022	Regis Houssin			
 * ....
 */

require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';


/**
 *	This class is used to manage file upload using ajax
 */
class FileUpload
{

在 FileUpload 中需要使用到 files 和 images 這二個類別。

若現有的專案,剛好有這二個類別時,會遇到類別名稱衝突,導致 require 失敗,導致 FileUpload 沒有辦法使用。這個問題其實和更早期 PHP 的狀況相同,大家各自實做自己的 function、和別人分享 function,卻又怕遇到相同的 function 名稱導致衝突。

為了解決 dependency (相依性、依賴關係) 問題,PHP 5.3 開始支援 namespace。

透過 namespace 功能,大家為 class 和 function 設定各自的 namespace,如:

<?php

namesace Zeroplex;

class FileUpload {
}

雖然 class 名稱相同,但只要在不同的 namespace 就不會導致衝突。


再故事往下之前提一下 autoload 功能,當 require 寫到手軟時,就開始有人開始想各種偷懶的方法了。

PHP 的 autoload 功能,允許使用者在建議物件時,針對自訂的邏輯,決定要做什麼事。所以這讓帶來幾個好處:

  • 只要先定好規則,就可以透過類別名稱,找到需要 require 的檔案
  • 透過 autoload,在需要使用時再 require 檔案

當這個功能合併使用時,就獲得合併技能「要使用時在 require」,不僅可以讓程式碼可讀性增加,也可以減少 disk I/O、記憶體使用量。

例如我透過 spl_autoload_register() 先定義好 require 規則:

<?php

spl_autoload_register(function ($className) {
    $classInfo = explode('/', $className);
    $namespace = $classInfo[0];
    $className = $classInfo[1];

    echo "namespace: " . $namespace . "\n";
    echo "class name: " . $className . "\n";

    require __DIR__ . "/library/" . $namespace . "/" . $className . ".php";
}

上述設定會自動將 Zeroplex/FileUploader 拆解成 namespace 和檔案名稱並 require,執行程式時會在 new 階段透過 autoloader 來決定要去哪裡 require 檔案:

<?php

$uploader = new Zeroplex\FileUploader();
namespace: Zeroplex
class name: FileUploader

在百家爭鳴寫 library 時,還會遇到一個問題:A 和 B library 都需要用到 C library,但 A library 中任何版本的 C library 都可,而 B library 則需要 C library 的最新版。這樣開發程式時,就還需要考慮到底要使用 C library 的哪一個版本。

於是 composer 就出現了。composer 是 dependency management,會自動尋找專案中各 library 可正確運作的版本。


時間往後走一段時間, 來到 PHP 7。

PHP 7 做的最大改變,是大幅改寫直譯器,讓效能大幅提升,而且不只是快一點點而已,是快了 100%。以前為了讓 PHP 程式跑得更快,Facebook 開發了 hhvm,現在用不到了。

若想知道為什麼效能可以快這麼多,可以參考 Nikita Popov (PHP 核心工程師之一) 的簡報:PHP 7 – What changed internally?。或是聽他的演講:

除了效能以外,PHP 在此時也慢慢的提供一些資料型態的定義、檢查功能,像是在撰寫 function 時可以定義 argument 的資料型態 (type hint),除了 scalar type 也開始支援使用者自訂 class 的支援。

這些支援,讓原本是 dynamic typing 的 PHP 可以多一些檢查,程式的可讀性和穩定性上都有改善。


PHP 7 到 8 我打算很不負責任得什麼都不說直接跳過 XD

這邊列出一些有趣的專案:

  • 在 awesome-php 上有很多有趣的專案
  • 如果覺得 PHP 效能不佳,可以試試看 Swoole 以及 Phalcon,這二個 framework 使用 C/C++ 實作,在 phpize 與 PHP 串接。
  • 其實有了 interface,不只有 C/C++,連 Rust 也可以開發 PHP extension
  • PHP 沒有 non-blocking I/O?其實也有,實作方法換一下即可 ReactPHP

Tags:PHP, 資訊學習

在 Laravel 中新增 Blade directive

Posted on 2023 年 10 月 15 日2023 年 10 月 15 日 By 日落 在〈在 Laravel 中新增 Blade directive〉中尚無留言

在 Blade template engine 中使用判斷式:

@if (Auth::check())
    <!-- 已登入 -->
@else
    <!-- 未登入 -->
@endif

Laravel 允許自訂 directive,自訂常用的判斷式。

開啟 /app/Providers/AuthServiceProvider.php 並在 boot() 中加入以下設定:

// Illuminate\Support\Facades\Blade;
Blade::if('isLoggedIn', function() {
    return Auth::check();
});

之後,就可以在 Blade 中使用自訂判斷:

@isLoggedIn
    <!-- 已登入 -->
@else
    <!-- 未登入 -->
@endisLoggedIn
Tags:Laravel, PHP

在 Laravel 中使用 PostgreSQL JSONB query

Posted on 2023 年 10 月 14 日2023 年 10 月 13 日 By 日落 在〈在 Laravel 中使用 PostgreSQL JSONB query〉中尚無留言

PostgreSQL 中,要查詢 item 是否在 JSON list (array) 中的語法是:

where user_list::jsonb ? 'user name'

如果使用 DB:raw() 代入 Laravel Eloquent 會出現錯誤訊息:

-- where(DB::raw('user_list::jsonb ? \'user name\''))->get()

SQLSTATE[42601]: Syntax error: 7 ERROR:  syntax error at or near "$1"

原因是 ? 會被視為 prepare/binding 的記號,上面語法沒有給定 bind 條件,所以發生錯誤。

若不使用 prepare/binding,則要 ? escape 為 ??:

-- where(DB::raw('user_list::jsonb ?? \'user name\''))->get()

  Illuminate\Database\Eloquent\Collection {#6157
    ....
  }
Tags:Laravel, PHP, PostgreSQL

Laravel Job methods

Posted on 2023 年 9 月 2 日2023 年 9 月 2 日 By 日落 在〈Laravel Job methods〉中尚無留言

把 Laravel Queue 中提到的 method 列出來,幾乎都會用到的是這幾個:

  • handle()
  • fail()
  • retryUntil()
  • backoff()
class MyJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct($jobData)
    {
        $this->jobData = $jobData;
    }

    public function handle()
    {
        // work
    }

    public function fail(Throwable $e = null)
    {
        // job failed 時要做的事情
    }

    public function retryUntil()
    {
        return now()->addHours(2);
    }

    public function backoff()
    {
        // 下一次 retry 中間要間格多少時間
        return [30, 60, 120];
    }
}

應該還有一些文件上沒寫到的,可能要去翻影片才知道。

Tags:Laravel, PHP

Laravel 表單 validator 以及錯誤訊息顯示

Posted on 2023 年 8 月 12 日2023 年 9 月 29 日 By 日落 在〈Laravel 表單 validator 以及錯誤訊息顯示〉中尚無留言

建立一個 form 其中包含一個 input field:

<form
    method="POST"
    action="">

<input type="text" id="item-amount" name="item-amount">

</form>

表單送出以後,會使用 controller 的 store() 來處理資料。這裡先驗證 item-amount 是否有輸入數值:

public function store(\Illuminate\Http\Request $request)
{
    $validator = Validator::make($request->all(), [
        'item-amount' => 'required',
    ];
}

若使用者沒有輸入資料時 $validator->failes() 會回傳 true:

if ($validator->fails()) {
    // 檢查發現錯誤
} else {
    // 資料都正確
}

More “Laravel 表單 validator 以及錯誤訊息顯示” »

Tags:Laravel, PHP

文章分頁

1 2 ... 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 國際 授權條款授權.