9.8.1. hook_form_alter() का उपयोग करके मौजूदा फॉर्म के लिए सबमिट और वैलिडेट जोड़ना।
पिछले पाठों में हमने जाना कि हुक क्या होते हैं, इस पाठ में हम hook_form_alter() हुक्स के साथ अभ्यास करेंगे और मौजूदा फॉर्म में कार्यक्षमता जोड़ेंगे।
कोड के उदाहरण आप github पर देख सकते हैं:
https://github.com/levmyshkin/drupalbook8
इस पाठ में हम हुक्स को व्यवहार में देखना शुरू करेंगे, बाद में हम हुक्स पर वापस लौटेंगे और कुछ अन्य उदाहरण देखेंगे। अब, चलिए hook_form_alter() से शुरू करते हैं।
मॉड्यूल में हुक जोड़ने के लिए, हमें MODULENAME.module नामक एक फाइल बनानी होगी, इसलिए हम drupalbook.module नामक एक फाइल बनाएंगे। यह एक PHP फाइल होगी जहां हमारे हुक्स और सहायक कार्य होंगे, बाकी के लिए अलग-अलग फाइलों और क्लासेस का उपयोग करना बेहतर है जो src फोल्डर में हों। फिलहाल आप बस फाइल में एक ओपनिंग टैग जोड़ सकते हैं।
अब चलिए hook_form_alter() जोड़ते हैं। यदि आप PhpStorm का उपयोग कर रहे हैं, तो हुक्स का नाम लिखना शुरू करें और PhpStorm आपको एक हुक चुनने का प्रस्ताव देगा। जब आप इस तरीके से हुक का चयन करते हैं, तो PhpStorm स्वचालित रूप से फंक्शन में आर्ग्युमेंट्स सम्मिलित कर देगा और आपको यह याद रखने की आवश्यकता नहीं होगी कि कौन से आर्ग्युमेंट्स जोड़ने हैं:
जब आप एक हुक जोड़ना चाहते हैं, तो आपको शब्द hook को अपने मॉड्यूल के नाम से बदलना होगा, और फिर Drupal स्वचालित रूप से आपके कोड को हुक के स्थान पर सम्मिलित कर देगा। परिणामस्वरूप, आपको यह फंक्शन प्राप्त करना चाहिए:
/**
* Implements hook_form_alter().
*/
function drupalbook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
}
पिछले पाठ में हम पहले ही देख चुके हैं कि $form, $form_state में क्या स्टोर किया जाता है, और $form_id में हमें फॉर्म आईडी स्टोर करनी होती है, जिसे हमने उपयुक्त मेथड में परिभाषित किया था:
9.8. Drupal में फॉर्म के साथ काम करना। प्रोग्रामेटिकली कॉन्फ़िगरेशन फॉर्म जोड़ना।
अब हम पिछले पाठ में जो API की फील्ड जोड़ने का फॉर्म था, उसे बढ़ाते हैं। इसके लिए, हमें फॉर्म आईडी परिभाषित करनी होगी, आप इसे इस मेथड में देख सकते हैं:
function getFormId() {
return 'drupalbook_admin_settings';
}
या DOM इंस्पेक्टर खोलकर HTML में id एट्रिब्यूट देख सकते हैं:
यहां हमें - (हाइफन) को _ (लोअर अंडरस्कोर) से बदलना होगा। लेकिन सावधान रहें, फॉर्म टैग एट्रिब्यूट में आईडी AJAX-रिक्वेस्ट के बाद बढ़ाई जा सकती है, उदाहरण के लिए, drupalbook-admin-settings-0, drupalbook-admin-settings-1, drupalbook-admin-settings-2 आदि। हमें अंत में नंबर के बिना हिस्सा चाहिए, यह वह हिस्सा है जो फॉर्म आईडी से उत्पन्न होता है, जो getFormId() मेथड में निर्दिष्ट किया गया है।
अब हमें अपने कोड को केवल drupalbook_admin_settings फॉर्म के लिए सीमित करना होगा, क्योंकि जो कोड hook_form_alter() में है, वह सभी फॉर्म्स के लिए निष्पादित होगा जो Drupal Form API के माध्यम से जनरेट होते हैं:
($form_id == 'drupalbook_admin_settings') {
// आगे का कोड यहां।
}
if के अंदर हम API की फील्ड फॉर्म के लिए अपना कोड लिख सकते हैं। चलिए टेक्स्ट फील्ड्स के लिए प्लेसहोल्डर्स जोड़ते हैं ताकि खाली फील्ड्स पर लिखा हुआ दिखे:
($form_id == 'drupalbook_admin_settings') {
$form['drupalbook_api_key']['#attributes']['placeholder'] = 'API key';
$form['drupalbook_api_client_id']['#attributes']['placeholder'] = 'API client ID';
}
hook_form_alter() लागू करने के लिए, कैश साफ़ करें।
हालाँकि #attributes को डॉक्यूमेंटेशन में टेक्स्टफील्ड के लिए एक संभावित कुंजी के रूप में सूचीबद्ध नहीं किया गया है:
https://api.drupal.org/api/drupal/core%2
फिर भी, इस कुंजी का उपयोग टैग्स के गुण (जैसे क्लास, प्लेसहोल्डर, विभिन्न rel-गुण) को निर्दिष्ट करने के लिए किया जा सकता है। एक और स्पष्ट तालिका Drupal 7 Form API के लिए है:
https://api.drupal.org/api/drupal/developer%21topics%21forms_api_reference.html/7.x
आप यहां टेक्स्टफील्ड फील्ड्स के लिए #attributes देख सकते हैं।
एट्रिब्यूट वैल्यूज़ फॉर्म API में सेट किए जाते हैं जब फॉर्म एलिमेंट को सेटAttributes मेथड में रेंडर (जनरेट) किया जाता है:
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%
हालांकि यह API डॉक्यूमेंटेशन फॉर्म में स्पष्ट रूप से नहीं कहा गया है, आप खुद देख सकते हैं कि यह काम करता है।
आप बेस FormElement क्लास में भी देख सकते हैं कि आप फॉर्म फील्ड्स के लिए और कौन-कौन से वैल्यू सेट कर सकते हैं:
https://api.drupal.org/api/drupal/core%21lib%2
Drupal Form API थोड़ी अस्पष्ट और भ्रमित करने वाली लगती है, लेकिन इसे उपयोग में लाना काफी सरल और स्पष्ट है, अगर आपके पास एक कामकाजी उदाहरण है। इसलिए, यदि आपके पास कोई सवाल है और आपको यह नहीं पता कि फॉर्म में इसे कैसे करें, तो इंटरनेट पर देखें और आप 100% कार्यशील उदाहरण पाएंगे। आपको यह जानना जरूरी है कि सभी फॉर्म Drupal के सभी APIs, Cache, Render, Theming से गुजरते हैं और फॉर्म में कोई भी फील्ड आप hook_form_alter() के माध्यम से बदल सकते हैं, और आप गूगल के माध्यम से यह पता कर सकते हैं कि इसे कैसे करें। इसके अलावा, जितना अधिक आप Form API का सामना करेंगे और इसके उदाहरणों को पार्स करेंगे, उतना ही यह आपके लिए आसान और स्पष्ट होता जाएगा। और चिंता न करें कि यह इतना बड़ा है, बस वही भाग उपयोग करें जो आपको अभी चाहिए।
Validate
अब हम Form API के माध्यम से वैलिडेट फंक्शन्स का उपयोग करना देखते हैं। चलिए हम Key API फील्ड की जांच करते हैं ताकि वह शब्द google से शुरू हो, जैसे google-KEY123a3sa। अगर हमने अपने फॉर्म के लिए कोड पहले ही लिखा होता, तो हम validateForm() मेथड जोड़ सकते थे और इसमें सभी चेक्स कर सकते थे:
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
}
लेकिन अक्सर हम जिन फॉर्म्स के साथ काम करते हैं, वे योगदानित मॉड्यूल्स में होते हैं और ऐसे फॉर्म्स के लिए कोड कस्टम मॉड्यूल्स में लिखना बेहतर होता है। तो चलिए हम फॉर्म में एक नया वैलिडेशन फंक्शन जोड़ते हैं:
['#validate'][] = 'drupalbook_settings_validate';
#validate ऐरे में हम सभी कॉलबैक और वैलिडेशन फंक्शन्स को स्टोर करते हैं। कॉलबैक एक फंक्शन को उसके नाम से कॉल करना है, यानी हम ['callback_function1', 'callback_function2'] ऐरे जोड़ेंगे और फिर इन नामों को ऐरे से लेकर Drupal इन फंक्शन्स को कॉल करेगा। इस मामले में, Drupal इन फंक्शन्स को हमारे फॉर्म की जांच करने के लिए कॉल करेगा। अब हमें drupalbook_settings_validate फंक्शन को drupalbook.module फाइल में बनाना होगा। इस फंक्शन में हमारे पास $form और $form_state पैरामीटर होंगे:
/**
* Custom validation callback.
*/
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
}
अब चलिए हम API Key फील्ड की जांच जोड़ते हैं:
/**
* Custom validation callback.
*/
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
if (strpos($form_state->getValue('drupalbook_api_key'), 'google') === FALSE) {
$form_state->setErrorByName('drupalbook_api_key', t('API Key must start from "google".'));
}
}
हम हार्ड-कंपेरिजन ऑपरेटर === का उपयोग करते हैं, क्योंकि अगर google स्ट्रिंग के शुरू में है, तो strpos() 0 लौटाता है और PHP (0 == FALSE) TRUE लौटाएगा, क्योंकि PHP में '', 0, NULL, FALSE ये सभी खाली मान होते हैं और वे साधारण तुलना == में बराबर होते हैं।
अब हर बार जब आप सेटिंग्स का फॉर्म सहेजते हैं, तो एक चेक किया जाएगा, और यदि चेक पास नहीं हुआ, तो Drupal एक त्रुटि उत्पन्न करेगा और सेटिंग्स सहेजी नहीं जाएंगी:
Submit
सभी वैलिडेट फंक्शन्स के काम करने के बाद और कोई त्रुटियाँ नहीं होने पर, Drupal सबमिट फंक्शन्स को कॉल करता है, जो डेटा को फॉर्म से भेजने के बाद काम करते हैं। आपने पिछले पाठ में submitForm() मेथड को देखा था, जहां हम डेटा को कॉन्फ़िगरेशन में सहेजते हैं। लेकिन हम सबमिट पर अन्य क्रियाएँ भी कर सकते हैं, जैसे डेटा को बदलना या अन्य एंटिटीज़ में डेटा सहेजना। चलिए एक और वैलिडेशन फंक्शन करते हैं जो API Key का उपयोग करने के तरीके पर एक अतिरिक्त संदेश दिखाएगा। हम hook_form_alter() में एक फंक्शन नाम जोड़ेंगे:
['#submit'][] = 'drupalbook_settings_submit';
अब हम drupalbook_settings_settings_submit() फंक्शन में, जहां हम $form और $form_state को पैरामीटर के रूप में पास करते हैं, संदेश दिखाते हैं।
/**
* Custom submit callback.
*/
function drupalbook_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
\Drupal::messenger()->addStatus(
t(htmlentities('Insert API key in your tag: .'))
);
}
हम htmlentities() फंक्शन का उपयोग करते हैं ताकि यह सुनिश्चित किया जा सके कि हम जो विशेष करैक्टर इस्तेमाल कर रहे हैं उन्हें Drupal द्वारा न हटाया जाए। सभी HTML टेक्स्ट को t() फंक्शन से काट लिया जाता है, ताकि इसे टेक्स्ट में पेस्ट किया जा सके, उदाहरण के लिए, यदि ऐसा कोड जावास्क्रिप्ट रीडायरेक्ट करता है तो यह संदेश दिखाते समय रीडायरेक्ट हो जाएगा। यही कारण है कि हम tags को प्रदर्शित करने के लिए htmlentities फंक्शन का उपयोग करते हैं।
संदेश तब तक प्रदर्शित नहीं होगा जब तक कि वैलिडेशन फंक्शन्स सफल नहीं हो जाते, केवल जब फॉर्म में कोई त्रुटियाँ नहीं होंगी, तभी हम संदेश देखेंगे।
पहले, Drupal में संदेश प्रदर्शित करने के लिए drupal_set_message फंक्शन का उपयोग किया जाता था:
(t('An error occurred and processing did not complete.'));
लेकिन अब सभी लोग इसे OOP के उपयोग की ओर एकीकृत करने की कोशिश कर रहे हैं।
नीचे drupalbook.module फाइल का पूरा वर्तमान कोड है:
/**
* Implements hook_form_alter().
*/
function drupalbook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if ($form_id == 'drupalbook_admin_settings') {
$form['drupalbook_api_key']['#attributes']['placeholder'] = 'API key';
$form['drupalbook_api_client_id']['#attributes']['placeholder'] = 'API client ID';
$form['#validate'][] = 'drupalbook_settings_validate';
$form['#submit'][] = 'drupalbook_settings_submit';
}
}
/**
* Custom validation callback.
*/
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
if (strpos($form_state->getValue('drupalbook_api_key'), 'google') === FALSE) {
$form_state->setErrorByName('drupalbook_api_key', t('API Key must start from "google".'));
}
}
/**
* Custom submit callback.
*/
function drupalbook_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
// drupal_set_message is deprecated
// drupal_set_message(t('An error occurred and processing did not complete.'));
\Drupal::messenger()->addStatus(
t(htmlentities('Insert API key in your tag: .'))
);
}
यह हमारी Form API पर पाठ समाप्त करता है, लेकिन Form API के अध्ययन की समाप्ति नहीं है, हम इसके साथ validate, submit और विभिन्न फील्ड्स के फंक्शन्स से बार-बार सामना करेंगे। हम अगले पाठों में यह भी समझेंगे कि AJAX और form_states का Form API के माध्यम से कैसे उपयोग किया जाता है।
कोड के उदाहरण आप github पर देख सकते हैं:
https://github.com/levmyshkin/drupalbook8