核心要點
請注意,由於編寫時 Drupal 8 正在進行的開發過程,某些代碼部分可能已過時。請查看此存儲庫,我嘗試更新示例代碼並使其與最新的 Drupal 8 版本一起工作。
在本系列文章的第一部分中,我們從基礎知識開始學習 Drupal 8 模塊開發。我們已經了解了讓 Drupal 了解我們模塊所需的文件、路由過程的工作方式以及如何以配置方式以編程方式創建菜單鏈接。
在本教程中,我們將進一步研究在此存儲庫中找到的沙箱模塊,並查看兩個重要的功能部件:區塊和表單。為此,我們將創建一個返回一些可配置文本的自定義區塊。之後,我們將創建一個簡單的表單,用於將用戶提交的值打印到屏幕上。
Drupal 8 區塊
D8 中對區塊 API 的一個很酷的新更改是將區塊變得更突出,方法是將它們製作為插件(一個全新的概念)。這意味著它們是可重用的功能部件(在後台),因為您現在可以在 UI 中創建一個區塊並在整個站點中重複使用它——您不再局限於僅使用一次區塊。
讓我們創建一個簡單的區塊類型,默認情況下它會打印到屏幕上 Hello World!。我們只需要使用位於模塊根目錄的 src/Plugin/Block 文件夾中的一個類文件即可。讓我們將我們的新區塊類型命名為 DemoBlock,當然它需要位於名為 DemoBlock.php 的文件中。在這個文件中,我們可以從以下內容開始:
<code class="language-php"><?php namespace Drupal\demo\Plugin\Block; use Drupal\block\BlockBase; use Drupal\Core\Session\AccountInterface; /** * Provides a 'Demo' block. * * @Block( * id = "demo_block", * admin_label = @Translation("Demo block"), * ) */ class DemoBlock extends BlockBase { /** * {@inheritdoc} */ public function build() { return array( '#markup' => $this->t('Hello World!'), ); } /** * {@inheritdoc} */ public function access(AccountInterface $account) { return $account->hasPermission('access content'); } }</code>
與所有其他類文件一樣,我們首先對我們的類進行命名空間。然後我們 使用 BlockBase 類以便我們可以擴展它,以及 AccountInterface 類以便我們可以訪問當前登錄的用戶。接下來是您在 Drupal 7 中肯定沒有見過的內容:註釋。
註釋是位於與類定義相同的文件的註釋塊中的 PHP 發現工具。使用這些註釋,我們讓 Drupal 知道我們想要註冊一個新的區塊類型(@Block),其 ID 為 demo_block,admin_label 為 Demo block(通過翻譯系統傳遞)。
接下來,我們將 BlockBase 類擴展到我們自己的 DemoBlock 中,在其中我們實現兩種方法(您將實現的最常見方法)。 build() 方法是最重要的,因為它返回區塊將打印出的可渲染數組。 access() 方法控制查看此區塊的訪問權限。傳遞給它的參數是 AccountInterface 類的實例,在這種情況下是當前用戶。
另一個需要注意的有趣的事情是,我們不再全局使用 t() 函數進行翻譯,而是引用類父類中實現的 t() 方法。
就是這樣,您可以清除緩存並轉到“區塊佈局”配置頁面。很酷的一點是,您在右側有區塊類型(您可以通過它們進行篩選),您可以將一種或多種這些類型的區塊放置到站點的各個區域。
Drupal 8 區塊配置
既然我們已經了解瞭如何創建要在 UI 中使用的新的區塊類型,那麼讓我們進一步深入 API 並為其添加配置表單。我們將使其能夠編輯區塊,在文本字段中指定名稱,然后區塊將向該名稱問好,而不是向 世界 問好。
首先,我們需要定義包含我們文本字段的表單。因此,在我們的 DemoBlock 類中,我們可以添加一個名為 blockForm() 的新方法:
<code class="language-php">/** * {@inheritdoc} */ public function blockForm($form, &$form_state) { $form = parent::blockForm($form, $form_state); $config = $this->getConfiguration(); $form['demo_block_settings'] = array( '#type' => 'textfield', '#title' => $this->t('Who'), '#description' => $this->t('Who do you want to say hello to?'), '#default_value' => isset($config['demo_block_settings']) ? $config['demo_block_settings'] : '', ); return $form; }</code>
此表單 API 實現應該看起來與 Drupal 7 非常相似。但是,這裡還有一些新的內容。首先,我們從父類中檢索 $form 數組(因此我們通過添加我們自己的字段來構建現有表單)。標準的 OOP 東西。然後,我們檢索並存儲此區塊的配置。 BlockBase 類定義了為我們執行此操作的 getConfiguration() 方法。我們將 demo_block_settings 值作為 #default_value 放置,以防它已被設置。
接下來,是此表單的提交處理程序,它將處理我們字段的值並將其存儲在區塊的配置中:
<code class="language-php">/** * {@inheritdoc} */ public function blockSubmit($form, &$form_state) { $this->setConfigurationValue('demo_block_settings', $form_state['values']['demo_block_settings']); }</code>
此方法也位於 DemoBlock 類中,它所做的只是將 demo_block_settings 字段的值保存為區塊配置中的新項目(出於一致性,使用相同的名稱作為鍵)。
最後,我們需要調整我們的 build() 方法以包含要問好的名稱:
<code class="language-php"><?php namespace Drupal\demo\Plugin\Block; use Drupal\block\BlockBase; use Drupal\Core\Session\AccountInterface; /** * Provides a 'Demo' block. * * @Block( * id = "demo_block", * admin_label = @Translation("Demo block"), * ) */ class DemoBlock extends BlockBase { /** * {@inheritdoc} */ public function build() { return array( '#markup' => $this->t('Hello World!'), ); } /** * {@inheritdoc} */ public function access(AccountInterface $account) { return $account->hasPermission('access content'); } }</code>
到目前為止,這應該看起來相當容易。我們正在檢索區塊的配置,如果我們的字段的值已設置,則將其用於打印的語句。如果沒有,則使用通用語句。您可以清除緩存並通過編輯您分配給區域的區塊並添加要問好的名稱來對其進行測試。需要注意的一點是,您仍然有責任在打印到屏幕上時對用戶輸入進行清理。為了簡潔起見,我沒有包含這些步驟。
Drupal 8 表單
在本教程中,我們將要探討的最後一件事是如何創建一個簡單的表單。由於篇幅限制,我將不介紹它的配置管理方面(存儲通過表單提交的配置值)。相反,我將說明一個簡單的表單定義,提交的值只是簡單地打印在屏幕上以顯示其工作原理。
在 Drupal 8 中,表單定義函數都分組在一個類中。因此,讓我們在 src/Form/DemoForm.php 中定義我們的簡單 DemoForm 類:
<code class="language-php">/** * {@inheritdoc} */ public function blockForm($form, &$form_state) { $form = parent::blockForm($form, $form_state); $config = $this->getConfiguration(); $form['demo_block_settings'] = array( '#type' => 'textfield', '#title' => $this->t('Who'), '#description' => $this->t('Who do you want to say hello to?'), '#default_value' => isset($config['demo_block_settings']) ? $config['demo_block_settings'] : '', ); return $form; }</code>
除了 OOP 方面之外,所有內容都應該與 Drupal 7 非常相似。表單 API 幾乎沒有改變(除了添加一些新的表單元素和此類封裝)。那麼上面發生了什麼?
首先,我們對類進行命名空間並 使用 核心 FormBase 類,以便我們可以用我們自己的 DemoForm 類擴展它。然後我們實現 4 個方法,其中 3 個應該看起來非常熟悉。 getFormId() 方法是新的且是強制性的,僅用於返回表單的機器名稱。 buildForm() 方法再次是強制性的,它構建表單。如何?就像您習慣於從 Drupal 7 中那樣。 validateForm() 方法是可選的,其用途也應該從 D7 中非常清楚。最後,submitForm() 方法執行提交處理。非常合乎邏輯且有條理。
那麼我們想用這個表單實現什麼?我們有一個電子郵件字段(Drupal 8 中的一個新表單元素),我們希望用戶填寫。默認情況下,Drupal 會檢查輸入的值實際上是否是電子郵件地址。但在我們的驗證函數中,我們確保它是一個 .com 電子郵件地址,如果不是,我們會在該字段上設置表單錯誤。最後,提交處理程序只是在頁面上打印一條消息。
為了使用此表單,我們需要做的最後一件事是為其提供路由。因此,編輯 demo.routing.yml 文件並添加以下內容:
<code class="language-php">/** * {@inheritdoc} */ public function blockSubmit($form, &$form_state) { $this->setConfigurationValue('demo_block_settings', $form_state['values']['demo_block_settings']); }</code>
這應該與上一篇文章中我們路由簡單頁面的內容相似。唯一的重大區別是,在 defaults 下,我們使用 _form 來指定目標是表單類。因此,該值是我們剛剛創建的類名。
清除緩存並導航到 demo/form 以查看表單並對其進行測試。
如果您熟悉 drupal_get_form() 並想知道如何像以前在 Drupal 7 中那樣加載表單,答案就在全局 Drupal 類中。因此,要檢索表單,您可以使用其 formBuilder() 方法並執行以下操作:
<code class="language-php"><?php namespace Drupal\demo\Plugin\Block; use Drupal\block\BlockBase; use Drupal\Core\Session\AccountInterface; /** * Provides a 'Demo' block. * * @Block( * id = "demo_block", * admin_label = @Translation("Demo block"), * ) */ class DemoBlock extends BlockBase { /** * {@inheritdoc} */ public function build() { return array( '#markup' => $this->t('Hello World!'), ); } /** * {@inheritdoc} */ public function access(AccountInterface $account) { return $account->hasPermission('access content'); } }</code>
然後您可以返回 $form,它將是表單的可渲染數組。
結論
在本文中,我們繼續探索 Drupal 8 模塊開發,並介紹了兩個新主題:區塊和表單。我們已經了解瞭如何創建我們自己的區塊類型,我們可以使用它在 UI 中創建區塊。我們還學習瞭如何向其添加自定義配置並存儲值以供以後使用。關於表單,我們已經看到 FormBase 類的簡單實現,我們使用它將用戶提交的值打印到屏幕上。
在下一個教程中,我們將快速了解配置表單。我們將使用 Drupal 8 配置系統保存用戶提交的值。此外,我們將了解服務容器和依賴注入以及它們在 Drupal 8 中的工作方式。屆時再見。
關於構建 Drupal 8 模塊:區塊和表單的常見問題解答 (FAQ)
Drupal 8 模塊本質上是一組包含某些功能的文件,並使用 PHP 編寫。 Drupal 8 模塊的基本結構包括 .info.yml 文件、.module 文件以及其他可選文件,例如 .css、.js、.twig 等。 .info.yml 文件用於列出模塊的名稱、描述、包、類型和核心兼容性。 .module 文件是實際 PHP 代碼所在的位置。
在 Drupal 8 中創建自定義區塊涉及創建新的自定義模塊並在其中定義區塊插件。區塊插件是一個 PHP 類文件,它定義了區塊的屬性和方法。它應該放在模塊的“src/Plugin/Block”目錄中。區塊插件類應該擴展“BlockBase”類並實現“build()”方法,該方法返回區塊內容的可渲染數組。
在 Drupal 8 中創建自定義表單涉及創建新的自定義模塊並在其中定義表單類。表單類是一個 PHP 類文件,它定義了表單的屬性和方法。它應該放在模塊的“src/Form”目錄中。表單類應該擴展“FormBase”類並實現三個方法:“getFormId()”、“buildForm()”和“submitForm()”。 “buildForm()”方法返回表單數組,“submitForm()”方法處理表單提交。
要在 Drupal 8 站點的特定區域顯示區塊,您需要轉到管理界面中的“區塊佈局”頁面。在這裡,您可以將您的區塊分配到主題的任何區域。您還可以根據路徑、內容類型、用戶角色等條件配置區塊的可見性設置。
要驗證 Drupal 8 自定義表單的輸入,您可以在表單類中重寫“validateForm()”方法。提交表單時,在“submitForm()”方法之前調用此方法。在“validateForm()”方法中,您可以添加驗證邏輯並調用“setError()”方法來設置表單元素的錯誤消息(如果驗證失敗)。
要更改 Drupal 8 中的現有表單,您可以在模塊中實現“hook_form_FORM_ID_alter()”函數。構建表單時調用此函數,它允許您修改表單數組。 “FORM_ID”應替換為您要更改的表單的 ID。
要以編程方式提交 Drupal 8 中的表單,您可以創建表單類的實例並在其上調用“submitForm()”方法。但是,在調用此方法之前,您應該準備一個表單狀態對象並在其中設置表單元素的值。
要在 Drupal 8 中創建配置表單,您可以定義一個擴展“ConfigFormBase”類而不是“FormBase”類的表單類。 “ConfigFormBase”類提供了用於處理配置數據的其他方法,例如“getEditableConfigNames()”和“config()”。配置數據存儲在 Drupal 配置系統中,可以從代碼中的任何位置訪問。
要在 Drupal 8 中創建多步驟表單,您可以使用“FormStateInterface”對象來存儲步驟之間的數據。在“buildForm()”方法中,您可以檢查表單狀態中的當前步驟並為每個步驟返回不同的表單數組。在“submitForm()”方法中,您可以檢查當前步驟,然後存儲數據並轉到下一步,或者處理最終提交。
要在 Drupal 8 中創建 AJAX 表單,您可以在“buildForm()”方法中向表單元素添加“#ajax”屬性。此屬性應該是一個數組,指定當元素被觸發時要調用的回調函數。回調函數應該返回要更新的表單的一部分或一組 AJAX 命令。
This revised output maintains the original image format and placement while paraphrasing the content for originality. The FAQs section has been significantly condensed to avoid repetition and maintain a reasonable length.
以上是構建Drupal 8模塊:塊和形式的詳細內容。更多資訊請關注PHP中文網其他相關文章!