9.10.3. Drupal में फील्ड्स के साथ काम करना। यूट्यूब से वीडियो जोड़ने के लिए अपना खुद का फील्ड टाइप, विजेट और फॉर्मैटर बनाना।
पिछले लेखों में हमने देखा कि लिंक फील्ड टाइप कैसे काम करता है: स्टोरेज, विजेट, फॉर्मेटर। इस लेख में हम एक नया फील्ड टाइप बनाएंगे जो पेज पर यूट्यूब से वीडियो दिखाने के लिए होगा, जिसमें दो अलग-अलग फॉर्मेट और सेटिंग्स होंगी।
यह लेख Fields API पर केंद्रित है, और यदि आपको अपनी साइट पर यूट्यूब वीडियो फील्ड जोड़ने की आवश्यकता है, तो बेहतर होगा कि आप तैयार मॉड्यूल का उपयोग करें:
https://www.drupal.org/project/video_embed_field
मैंने सारा कोड GitHub पर drupalbook_youtube मॉड्यूल में जोड़ा है, आप मॉड्यूल डाउनलोड करके अपनी साइट में जोड़ सकते हैं:
https://github.com/levmyshkin/drupalbook8
आइए इस मॉड्यूल की संरचना देखें और मैं समझाने की कोशिश करूंगा कि यह फील्ड टाइप कैसे काम करता है:
modules/custom/drupalbook_youtube/drupalbook_youtube.info.yml
name: DrupalBook Youtube
type: module
description: Youtube embed field
core: 8.x
package: Custom
यह मॉड्यूल की मेटाडाटा को निर्धारित करता है।
modules/custom/drupalbook_youtube/src/Plugin/Field/FieldType/DrupalbookYoutubeItem.php
<?php
namespace Drupal\drupalbook_youtube\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
/**
* Plugin implementation of the 'drupalbook_youtube' field type.
*
* @FieldType(
* id = "drupalbook_youtube",
* label = @Translation("Embed Youtube video"),
* module = "drupalbook_youtube",
* description = @Translation("Output video from Youtube."),
* default_widget = "drupalbook_youtube",
* default_formatter = "drupalbook_youtube_thumbnail"
* )
*/
class DrupalbookYoutubeItem extends FieldItemBase {
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return array(
'columns' => array(
'value' => array(
'type' => 'text',
'size' => 'tiny',
'not null' => FALSE,
),
),
);
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
$value = $this->get('value')->getValue();
return $value === NULL || $value === '';
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['value'] = DataDefinition::create('string')
->setLabel(t('Youtube video URL'));
return $properties;
}
}
यह फील्ड टाइप Drupal को बताता है कि इस फील्ड के लिए टेबल में क्या संग्रहित किया जाएगा।
<?php
namespace Drupal\drupalbook_youtube\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
Define namespaces for our type of field.
यहाँ हमारे क्लास के लिए एक एब्स्ट्रैक्ट लिखा गया है, जिससे Drupal हमारे फील्ड टाइप का नाम और मशीन नाम प्राप्त करेगा।
class DrupalbookYoutubeItem extends FieldItemBase {
क्लास के नाम के अंत में "Item" लिखना सर्वोत्तम प्रथा है।
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return array(
'columns' => array(
'value' => array(
'type' => 'text',
'size' => 'tiny',
'not null' => FALSE,
),
),
);
}
हम परिभाषित करते हैं कि हम टेक्स्ट टाइप का value फील्ड संग्रहित करेंगे।
/**
* {@inheritdoc}
*/
public function isEmpty() {
$value = $this->get('value')->getValue();
return $value === NULL || $value === '';
}
यदि किसी तृतीय-पक्ष कोड से फील्ड कॉल किया गया है और फील्ड खाली है, तो हम खाली परिणाम लौटाते हैं।
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['value'] = DataDefinition::create('string')
->setLabel(t('Youtube video URL'));
return $properties;
}
हम MySQL टेबल और एंटिटी ऑब्जेक्ट के लिए कॉलम का वर्णन करते हैं। परिणामस्वरूप, पूरा लिंक संग्रहित किया जाएगा:
अब जब हमने फील्ड टाइप जोड़ लिया है, तो डेटा दर्ज करने के लिए एक विजेट बनाएँ:
modules/custom/drupalbook_youtube/src/Plugin/Field/FieldWidget/DrupalbookYoutubeWidget.php
<?php
namespace Drupal\drupalbook_youtube\Plugin\Field\FieldWidget;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Plugin implementation of the 'drupalbook_youtube' widget.
*
* @FieldWidget(
* id = "drupalbook_youtube",
* module = "drupalbook_youtube",
* label = @Translation("Youtube video URL"),
* field_types = {
* "drupalbook_youtube"
* }
* )
*/
class DrupalbookYoutubeWidget extends WidgetBase {
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$value = isset($items[$delta]->value) ? $items[$delta]->value : '';
$element += array(
'#type' => 'textfield',
'#default_value' => $value,
'#size' => 32,
'#maxlength' => 256,
'#element_validate' => array(
array($this, 'validate'),
),
);
return array('value' => $element);
}
/**
* Validate the color text field.
*/
public function validate($element, FormStateInterface $form_state) {
$value = $element['#value'];
if (strlen($value) == 0) {
$form_state->setValueForElement($element, '');
return;
}
if(!preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+(?=\?)|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $value, $matches)) {
$form_state->setError($element, t("Youtube video URL is not correct."));
}
}
}
यह विजेट हमें एंटिटी एडिटिंग फॉर्म में डेटा दर्ज करने की अनुमति देगा।
क्लास एनोटेशन में हमें field_type
निर्दिष्ट करना होता है, जिसे हमने ऊपर बनाया था, यानी drupalbook_youtube।
क्लास के नाम के अंत में "Widget" जोड़ें ताकि यह स्पष्ट हो कि यह क्लास फील्ड विजेट के लिए है।
हम एक साधारण टेक्स्टफील्ड बनाते हैं जहाँ उपयोगकर्ता यूट्यूब वीडियो का लिंक दर्ज करेगा।
validate() फ़ंक्शन उपयोगकर्ता द्वारा दर्ज लिंक की जाँच करता है कि वह सही यूट्यूब URL है या नहीं। यदि गलत है, तो यह त्रुटि दिखाता है।
अब जब हम फील्ड में डेटा दर्ज कर सकते हैं, तो हमें एक Field Formatter जोड़ना होगा ताकि डेटा प्रदर्शित हो सके।
modules/custom/drupalbook_youtube/src/Plugin/FieldFieldFormatter/DrupalbookYoutubeThumbnailFormatter.php
हमारे पास दो फॉर्मैटर होंगे। पहला एक साधारण होगा, जो केवल वीडियो की थंबनेल और यूट्यूब लिंक दिखाएगा:
<?php
namespace Drupal\drupalbook_youtube\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Field\FieldItemListInterface;
/**
* Plugin implementation of the 'drupalbook_youtube_thumbnail' formatter.
*
* @FieldFormatter(
* id = "drupalbook_youtube_thumbnail",
* module = "drupalbook_youtube",
* label = @Translation("Displays video thumbnail"),
* field_types = {
* "drupalbook_youtube"
* }
* )
*/
class DrupalbookYoutubeThumbnailFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = array();
foreach ($items as $delta => $item) {
preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+(?=\?)|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $item->value, $matches);
if (!empty($matches)) {
$content = '<a href="' . $item->value . '" target="_blank"><img src="http://img.youtube.com/vi/' . $matches[0] . '/0.jpg"></a>';
$elements[$delta] = array(
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => $content,
);
}
}
return $elements;
}
}
यहाँ #type
को html_tag के रूप में उपयोग किया गया है, ताकि HTML सीधे पेज पर प्रदर्शित हो सके। $delta
का उपयोग कई वीडियो फील्ड को सपोर्ट करने के लिए किया जाता है।
अब हम एक जटिल फॉर्मैटर बनाएँगे जो टेम्पलेट और सेटिंग्स का उपयोग करेगा:
modules/custom/drupalbook_youtube/src/Plugin/FieldFieldFormatter/DrupalbookYoutubeVideoFormatter.php
<?php
namespace Drupal\drupalbook_youtube\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
/**
* Plugin implementation of the 'drupalbook_youtube_video' formatter.
*
* @FieldFormatter(
* id = "drupalbook_youtube_video",
* module = "drupalbook_youtube",
* label = @Translation("Displays Youtube video"),
* field_types = {
* "drupalbook_youtube"
* }
* )
*/
class DrupalbookYoutubeVideoFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return array(
'width' => '600',
'height' => '450',
) + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$elements['width'] = array(
'#type' => 'textfield',
'#title' => t('Youtube video width'),
'#default_value' => $this->getSetting('width'),
);
$elements['height'] = array(
'#type' => 'textfield',
'#title' => t('Youtube video height'),
'#default_value' => $this->getSetting('height'),
);
return $elements;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = array();
$width = $this->getSetting('width');
$height = $this->getSetting('height');
foreach ($items as $delta => $item) {
preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+(?=\?)|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $item->value, $matches);
if (!empty($matches)) {
$elements[$delta] = array(
'#theme' => 'drupalbook_youtube_video_formatter',
'#width' => $width,
'#height' => $height,
'#video_id' => $matches[0],
);
}
}
return $elements;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = [];
$settings = $this->getSettings();
if (!empty($settings['width']) && !empty($settings['height'])) {
$summary[] = t('Video size: @width x @height', ['@width' => $settings['width'], '@height' => $settings['height']]);
} else {
$summary[] = t('Define video size');
}
return $summary;
}
}
यहाँ settingsForm()
के माध्यम से हम फील्ड फॉर्मैटर के लिए वीडियो की चौड़ाई और ऊँचाई को बदल सकते हैं।
इसके बाद हमें टेम्पलेट परिभाषित करना होगा:
modules/custom/drupalbook_youtube/templates/drupalbook-youtube-video-formatter.html.twig
{#
/**
* @file
* Default theme implementation of a simple Youtube video.
*
* Available variables:
* - width: Youtube video width.
* - height: Youtube video height.
* - video_id: Youtube video ID.
*/
#}
{% spaceless %}
<iframe width="{{ width }}" height="{{ height }}" src="https://www.youtube.com/embed/{{ video_id }}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen>iframe>
{% endspaceless %}
अब आप यूट्यूब वीडियो फील्ड बना सकते हैं और उसका आउटपुट Drupal के फॉर्मैटर के माध्यम से देख सकते हैं।
यहीं पर हम कस्टम फील्ड निर्माण समाप्त करेंगे और अब Entity API की ओर बढ़ेंगे, जहाँ हम कस्टम एंटिटी प्रकार बनाएंगे।