跳到內容

recipe 慣例

整合 cookbook 中每個可執行的 recipe 都遵循同一份契約。本頁說明這份契約,讓讀者知道一個 recipe 應包含哪些內容,也讓作者知道一個 recipe 必須滿足哪些條件。本頁屬於描述性說明:它記錄這項慣例。實際的強制性檢查由 repository 工具與樣式覆寫表(style override sheet)負責,不在這裡。

各整合的原始碼 repository 會把自己的 recipe 放在 docs/public/ 底下,再由負責 aggregate(聚合)的 aggregator(文件聚合器)拉進本站。以下慣例適用於 recipe 所在的任何位置。

1. 範例是真實程式碼,不是手打的片段

標題為「1. 範例是真實程式碼,不是手打的片段」的區段

一個 recipe 中的程式碼,是 repository 裡實際存在的真實程式碼,而不是直接寫在內文中的片段。

  • 任何超過五行的 PHP 程式碼區塊,都來自對應 repository 中的 examples/ 目錄,或來自 tests/Cookbook/ 目錄。
  • 區塊會在 fenced-block 資訊字串中宣告其來源,例如 title="examples/standalone.php"
  • 對應的測試會斷言該範例仍可編譯,且仍會產生文件所記載的輸出,因此算繪出來的頁面不會與它所展示的程式碼脫節。

這項慣例就是文件樣式覆寫表(style override sheet)§3.4(「範例必須可執行」)。一個只展示程式碼、卻沒有對應範例或測試支撐的 recipe,並不符合這項慣例。

2. 一個區塊一種語言,錯誤處理要看得到

標題為「2. 一個區塊一種語言,錯誤處理要看得到」的區段
  • 一個 fenced 程式碼區塊只包含一種語言,並明確宣告( ```php, ```bash, ```yaml, ```json)。不使用沒有標示語言的裸 fence。
  • 標記為可用於正式環境的 how-to recipe 會明確寫出 try / catch,捕捉最具體、最適用的例外型別,而不是直接捕捉 \Exception,而且 catch 區塊會執行讀者可以照抄的處理(記錄、重新拋出,或回傳一個已定義的錯誤物件)。不使用空的 catch 區塊。
  • 對於以 HTTP 傳輸的整合,recipe 會把傳輸失敗與非成功的 HTTP 狀態當成兩種不同情況來處理。PSR-18 用戶端只在請求根本送不出去時,才會拋出具型別的用戶端例外。4xx5xx 回應是 recipe 會檢視的正常回傳值,而不是 recipe 要捕捉的例外。

每個 recipe 都會宣告它的輸出可重現到什麼程度,並依循本站內容 schema 強制執行的 §5.1 front-matter 契約。相關欄位如下:

  • reproducibility_profile — 為 bitwisestructuralsemantic 其中之一。bitwise 表示在輸入已釘選的前提下,每次執行所輸出的位元組完全相同。structural 表示文件結構完全相同,但隨附位元組(時間戳、物件順序)可能不同。semantic 表示算繪結果等價,但不保證位元組或結構相同。一個 recipe 應宣告它能誠實做到的最強 profile,而不是宣告可用 profile 中最強的一個。
  • output_hash — 當 profile 為 bitwise 時,記錄預期輸出的 SHA-256,讓讀者可以驗證文件所記載的結果。當 profile 不支援穩定的雜湊時,此欄位留空。
  • runnable_example — 產生此 recipe 輸出的 examples/… 路徑,會把頁面繫結到 §1 中那個由原始碼支撐的範例。
  • performance_budget — recipe 的選用上限,包含實際時間(wall-clock)與尖峰記憶體,讓同時構成效能宣稱的 recipe 維持在可界定、可測試的範圍內。
  • compatibility — recipe 宣稱能執行的 PHP 版本。recipe 預設以 PHP 8.4 為準;若 recipe 用到僅 8.4 才有的功能,會在它的 front-matter 中列出 backport,並在程式碼區塊中特別標出該功能。

可重現性 profile 就是 §8.4 的可重現性契約。讀者會用它判斷「輸出」指的是完全相同的位元組,還是一份等價的文件。

本 cookbook 裡的每一頁在通過 Writing Gate 之前,都帶有 publish: false。預設為拒絕:合併一個頁面並不會把它發布;只有在 front-matter 中記錄一個明確的 gate 決定,才會發布。若某個 recipe 的規範性引用因為 compliance-engine 確實發生中斷而無法釘選,它還會額外帶有一個 resolve(解析)尚未完成的引用標記(unresolved-citation)。它會維持 publish: false,直到該引用重新釘選為止。該標記由 repository 的 RAG 基礎設施中斷回退協定管控;recipe 作者應遵循該協定,而不是自行捏造引用或捨棄這項宣稱。

5. aggregator 寫入 provenance(來源資訊)欄位

標題為「5. aggregator 寫入 provenance(來源資訊)欄位」的區段

recipe 作者不會手寫這四個由 aggregator 擁有的來源 provenance 欄位:source_reposource_refsource_hashmanifest_hash。aggregator 從原始碼 repository 拉取 recipe 時會填入這些欄位,因此發布的頁面會精確記錄是哪個 repository 版本產生了它。若作者在任一欄位留下佔位內容,aggregator 會將其覆寫;該佔位內容永遠不會出現在發布的頁面上。

本 cookbook 裡的一個 recipe 是:具備測試支撐且來自原始碼的程式碼、一個區塊一種語言、可用於正式環境的 how-to 具備明確錯誤處理、一份誠實的可重現性 profile、在通過 Writing Gate 之前預設 publish: false,以及由 aggregator 注入的 provenance。同時滿足全部六項的頁面是一個 recipe;只滿足較少項的頁面則是一份草稿。