logo

Լրացուցիչ Բլոկների Տեսակներ (EBT) - Դասավորության Կառուցողի նոր փորձառություն❗

Լրացուցիչ Բլոկների Տեսակներ (EBT) - ձևավորված, կարգավորելի բլոկների տեսակներ՝ սլայդշոուներ, ներդիրներ, քարտեր, բացվող ցանկեր և շատ ուրիշներ։ Ներառված կարգավորումներ՝ ֆոնի, DOM տուփի, JavaScript փլագինների համար։ Փորձեք դասավորությունների կառուցման ապագան արդեն այսօր։

EBT մոդուլների ցուցադրական տարբերակներ Ներբեռնել EBT մոդուլները

❗Լրացուցիչ Պարբերությունների Տեսակներ (EPT) - Պարբերությունների նոր փորձառություն

Լրացուցիչ պարբերության տեսակներ (EPT) - անալոգիական պարբերության վրա հիմնված մոդուլների հավաքակազմ։

EPT մոդուլների ցուցադրական տարբերակներ Ներբեռնել EPT մոդուլները

Scroll

Դաշտի տեսակներ, դաշտի վիջեթներ և դաշտի ձևաչափավորիչներ

18/06/2025, by Ivan

Վերանայում

Drupal 8-ն ունի մեծ հավաքածու հիմնական դասերի, որոնք թույլ են տալիս աշխատել ձեր սեփական կոնտենտի հետ։ Երբ խոսքը գնում է կոնտենտի էնտիթիների մասին, դուք ցանկանում եք օգտագործել դաշտեր։ Կարևոր է հասկանալ դաշտերը, քանի որ հենց այնտեղ են ձեր էնտիթիները պահում իրենց տվյալները։

Դաշտի տեսակներ (FieldTypes)

Հիմնական դաշտի տեսակներն են՝

 

Հարմարեցված դաշտերի տեսակներ
Երբևէ, երբ ցանկանում եք ներկայացնել տվյալներ այնպես, ինչպես Drupal չի առաջարկում, հնարավոր է ցանկանաք ստեղծել նոր դաշտի տեսակ ձեր տվյալների համար։

Ուրեմն, պատկերացրեք, որ ունեք կոնտենտի էնտիթի, որը պարունակում է գաղտնի տվյալներ։ Այդ կոնտենտի հեղինակը կարող է որոշակի օգտվողների թույլատրել մուտք ունենալ այդ էնտիթի՝ յուրաքանյուր օգտվողի համար տարբեր գաղտնաբառով։ Եթե պատկերացնենք դա տվյալների բազայի աղյուսակներում, ապա ցանկանում եք ունենալ ինչ-որ նման բան՝

| entity_id | uid | password      |
-----------------------------------
| 1         | 1   | 'helloworld'  |
| 1         | 2   | 'goodbye'     |

Ինչպես տեսնում եք, մեր էնտիթին՝ ID 1, ունի երկու տարբեր գաղտնաբառ երկու տարբեր օգտվողների համար։ Հետեւաբար, ինչպես կարող ենք իրականացնել սա Drupal-ում՝ առանց ձեռքով աղյուսակ ստեղծելու։ Մենք ստեղծում ենք նոր դաշտի տեսակ։

Քանի որ Drupal-ում դաշտի տրամաբանությունը իրականացնում է որպես Պլագին, մենք միշտ ունենք հիմքային դաս, որը ժառանգում ենք, որպեսզի այն աշխատի Drupal-ում։ Նոր դաշտի տեսակի համար դուք պետք է ստեղծեք հետևյալ թղթապանակների կառուցվածքը ձեր մոդուլում՝
modules/custom/MODULENAME/src/Plugin/Field/FieldType
Սա բավականին երկար ուղի է և մի քիչ ձանձրալի, բայց Drupal-ը հեշտացնում է աշխատանքը բոլոր տարբեր ֆունկցիաների հետ, որոնք կարող են համատեղ գոյություն ունենալ ձեր մոդուլներում։

Մեր օրինակին համար մենք ստեղծում ենք EntityUserAccessField.php ֆայլը

namespace Drupal\MODULENAME\Plugin\Field\FieldType;
     
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
     
/**
 * @FieldType(
 *   id = "entity_user_access",
 *   label = @Translation("Entity User Access"),
 *   description = @Translation("Այս դաշտը պահպանում է հղում օգտվողի և գաղտնաբառի համար էնտիթի վրա։"),
 * )
 */
     
class EntityUserAccessField extends FieldItemBase {
  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    // Todo: Կիրառել սա։
  }
     
  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    // Todo: Կիրառել սա։
  }
}

Ինչպես տեսնում եք, դաշտի տեսակն շատ նման է կոնտենտի էնտիթի։ Իրականում, նրանց միջև տարբերություն չկա, բայց դա արդեն առանձին թեմա է։

Առաջին հերթին, մենք ունենք անշանագրում մեր դաշտի տեսակի համար՝

  • @FieldType՝ կանչում է FieldType անշանագրման դասը Drupal գրադարանում
  • id՝ դաշտի տեսակի մեքենայական անունը, որպեսզի մենք կարողանանք այն կրկնօրինակել։ Համոզվեք, որ չեք վերագրանցում արդեն գոյություն ունեցող PHP կամ նման անունները։
  • label՝ կարող է լինել օգտվողի համար ընթեռնելի մեքենայական անվան թարգմանություն։
  • description՝ եթե պիտակները բավարար չեն, կարող եք ավելացնել դաշտի տեսակի նկարագրություն։

 

Երկրորդ, մեր դասը ժառանգվում է FieldItemBase-ից, որը պարտադրում է մեզ իրականացնել երկու մեթոդ, որպեսզի կարողանանք ճիշտ օգտագործել դաշտի այս տեսակը՝

  • propertyDefinitions(): Այս մեթոդը նման է baseFieldDefinition մեթոդին կոնտենտի էնտիթի համար (սակայն նույնը չէ)։ Մենք կարող ենք սահմանել տվյալները, որոնք երևում են էնտիթի ձևերում, որտեղ օգտագործվում է այս դաշտի տեսակն։
  • schema(): Այս մեթոդը արդեն հնացել է էնտիթի դեպքում, բայց դաշտերի համար դեռ կա։ Այն պետք է իրականացնի դաշտի տվյալների ներկայացումը տվյալների բազայում։ Կարող է տարբեր լինել propertyDefinitions-ում նշված հատկություններից։

Քանի որ դժվար է հասկանալ, թե ինչ պետք է գրենք այս մեթոդներում, եկեք ավելացնենք նրանց մեջ որոշ կոդ հարմարության համար։

public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
  $properties['uid'] = DataDefinition::create('integer')
      ->setLabel(t('Օգտվողի ID-ի հղում'))
      ->setDescription(t('Հղված օգտվողի ID-ն։'))
      ->setSetting('unsigned', TRUE);

  $properties['password'] = DataDefinition::create('string')
      ->setLabel(t('Գաղտնաբառ'))
      ->setDescription(t('Գաղտնաբառը պահպանված է պարզ տեքստով։ Դա անվտանգ չէ!'));

  $properties['created'] = DataDefinition::create('timestamp')
    ->setLabel(t('Ստեղծման ժամանակը'))
    ->setDescription(t('Ներմանության ստեղծման ժամանակը'));

  // Todo: Ավելացնել ավելի շատ հատկություններ։

  return $properties;
}

Նմանապես հնարավոր է օգտագործել DataReferenceDefinition՝ օգտվողի ID պահելու համար, ինչը կարող է քննարկվել ապագայում։

public static function schema(FieldStorageDefinitionInterface $field_definition) {
  $columns = array(
    'uid' => array(
      'description' => 'Հղված օգտվողի ID-ն։',
      'type' => 'int',
      'unsigned' => TRUE,
    ),
    'password' => array(
      'description' => 'Պարզ տեքստով գաղտնաբառ։',
      'type' => 'varchar',
      'length' => 255,
    ),
    'created' => array(
      'description' => 'Ժամանակահատվածը, երբ այս նիշումն ստեղծվել է։',
      'type' => 'int',
    ),

    // Todo: Ավելացնել ավելի շատ սյուներ։
  );

  $schema = array(
    'columns' => $columns,
    'indexes' => array(),
    'foreign keys' => array(),
  );

  return $schema;
}

schema() մեթոդը անհրաժեշտ է, որպեսզի Drupal-ը իմանա, թե ինչպես պահել մեր տվյալները։ Schema-ի սյուները պետք է լինեն propertyDefinitions-ում սահմանված հատկությունների ենթավիճակ։

Այժմ մենք ունենք նոր դաշտի տեսակ։ Այն չունի որևէ տրամաբանություն տվյալների մուտքագրման մշակման համար, բայց կարող է օգտագործվել ցանկացած կոնտենտի էնտիթի դաշտի նման։ Եթե ցանկանում եք, կարող եք օգտագործել այն որպես baseField ձեր էնտիթի համար՝

public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
  // Որոշ դաշտեր վերևում։

  $fields['entity_user_access'] = BaseFieldDefinition::create('entity_user_access')
    ->setLabel(t('Entity User Access'))
    ->setDescription(t('Նշեք գաղտնաբառերը ցանկացած օգտվողի համար, ով ցանկանում է դիտել այս էնտիթին։'))
    ->setCardinality(-1); // Գործնականում թույլ է տալիս ունենալ ավելի քան մեկ արժեք

  // Ավելի շատ դաշտեր ներքևում։

  return $fields;
}
  • BaseFieldDefinition::create(): Դուք պետք է օգտագործեք դաշտի տեսակի մեքենայական անունը create() մեթոդում։
  • setCardinality(-1): Նշում է, թե քանի արժեք կարող է ունենալ մեկ դաշտի օբյեկտը։ Օրինակ, եթե դրեք 2, ապա միայն երկու օգտվող կարող է մուտք ունենալ, 3՝ երեք օգտվող և այլն։ -1 նշանակում է անսահմանափակ թվով օգտվողներ։

 

Դաշտի Վիջեթներ (FieldWidget)

Եթե դուք ունեք հարմարեցված տվյալներ, ապա ձեզ կարող է անհրաժեշտ լինել այդ տվյալների հարմարեցված ներկայացում։ Վիջեթները օգտագործվում են ցույց տալու, թե ինչպես կարող է օգտվողը մուտքագրել այդ տվյալները ձևերում։ Օրինակ՝

  • եթե ձևում պետք է մուտքագրել ամբողջ թիվ, բայց օգտվողը կարող է պարզապես ընտրել միակ զննարկիչը (checkbox)
  • եթե ցանկանում եք ձեր տվյալների ավտոմատ լրացում
  • եթե գաղտնաբառը մուտքագրվում է հատուկ ինտերֆեյսով

և այլն։

Դաշտի վիջեթները Drupal-ում կարող եք գտնել
modules/custom/MODULENAME/src/Plugin/Field/FieldWidget
այսինքն բավական երկար ճանապարհ է։ Այստեղ պետք է հասկանաք, թե ինչու Drupal-ը այսպես է կազմակերպում .php ֆայլերը․ հեշտ է կորցնել, թե որ ֆայլը որտեղ է պատկանում։

Մենք ստեղծում ենք դաշտի վիջեթը EntityUserAccessWidget.php

namespace Drupal\MODULENAME\Plugin\Field\FieldWidget;
 
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
 
/**
 * Plugin implementation of the 'entity_user_access_w' widget.
 *
 * @FieldWidget(
 *   id = "entity_user_access_w",
 *   label = @Translation("Entity User Access - Widget"),
 *   description = @Translation("Entity User Access - Widget"),
 *   field_types = {
 *     "entity_user_access",
 *   },
 *   multiple_values = TRUE,
 * )
 */
 
class EntityUserAccessWidget extends WidgetBase {
  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    // Todo: Կիրառել սա։
  }
}

Դուք նկատե՞լ եք։ Drupal 8-ում այս կոդային ոճը կրկնվում է միշտ, երբ ցանկանում եք իրականացնել ֆունկցիոնալություն։ Կան անշանագրումներ և հիմքային դասեր, որոնք պետք է ժառանգել։ Այո, Drupal-ը կարող է այսպես աշխատել։

  • @FieldWidget՝ սահմանում է անշանագրման դասը
  • id՝ վիջեթի մեքենայական անունը
  • field_types՝ դաշտի տեսակի մեքենայական անունների զանգվածը, որոնց համար կարելի է օգտագործել այս վիջեթը
  • multiple_values՝ լռելյայն FALSE է։ Եթե ճիշտ է, թույլ է տալիս մեկից ավելի արժեք ուղարկել էնտիթի ձևում

Եթե հիմա ցանկանում եք օգտագործել այս վիջեթը ձեր դաշտի տեսակի հետ, պետք է խմբագրեք դաշտի տեսակի անշանագրումը այսպես՝

// ...

/**
 * @FieldType(
 *   id = "entity_user_access",
 *   label = @Translation("Entity User Access"),
 *   description = @Translation("Այս դաշտը պահպանում է հղում օգտվողի և գաղտնաբառի համար էնտիթի վրա։"),
 *   default_widget = "entity_user_access_w",
 * )
 */
     
// ...

Այժմ ամեն ինչ պատրաստ է։ Բայց մի սպասեք փոփոխություններ, քանի որ պետք է իրականացնել formElement() մեթոդը մեր վիջեթում։

public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element['userlist'] = array(
      '#type' => 'select',
      '#title' => t('Օգտվող'),
      '#description' => t('Ընտրեք խմբի անդամներին ցուցակից։'),
      '#options' => array(
         0 => t('Անանուն'),
         1 => t('Ադմինիստրատոր'),
         2 => t('foobar'),
         // Սա պետք է ավելի լավ իրականացվի։
       ),
  
    );
  
    $element['passwordlist'] = array(
      '#type' => 'password',
      '#title' => t('Գաղտնաբառ'),
      '#description' => t('Ընտրեք գաղտնաբառը օգտվողի համար'),
    );

    // Գտնել լռելյայն արժեքը բոլոր դաշտերի համար վերևում
    $childs = Element::children($element);
    foreach ($childs as $child) {
        $element[$child]['#default_value'] = isset($items[$delta]->{$child}) ? $items[$delta]->{$child} : NULL;
    }
   
    return $element;
}

Եթե հիմա բացեք ձևը այս վիջեթով, կտեսնեք առնվազն երկու մուտքի դաշտ։ Մեկը օգտվողի ընտրությունն է, մյուսը՝ գաղտնաբառի դաշտը։ Եթե ցանկանում եք իրականացնել տվյալների պահպանման եղանակ, պետք է ավելացնել ստուգման մեթոդներ այս վիջեթում կամ էնտիթի ձևում։ Տեսեք Drupal 8 Form API-ն ավելին իմանալու համար։

Դուք արդեն կատարել եք հարմարեցված դաշտի մեծ մասը։ Եթե չեք հասկանում, թե ինչ է տեղի ունենում, փորձեք կոդը կամ ուսումնասիրեք հիմնական մոդուլները ավելի լավ ընկալման համար։

Դաշտի ձևաչափավորիչներ (FieldFormatters)

Վերջին մասը, որը պակասում է, տվյալների ներկայացումն է էնտիթի դիտման ռեժիմում (իսկ վիջեթը՝ ձևի ռեժիմում)։ Դա սովորաբար տեղի է ունենում, երբ կանչում եք էնտիթին՝ yourdrupalpage.com/myentity/1/view հասցեով։

Որպեսզի շատ չխոսենք, անցնենք անմիջապես կոդին։ modules/custom/MODULENAME/src/Plugin/Field/FieldFormatter թղթապանակում ստեղծեք EntityUserAccessFormatter.php ֆայլը։

namespace Drupal\MODULENAME\Plugin\Field\FieldFormatter;
     
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
     
/**
 * Plugin implementation of the 'entity_user_access_f' formatter.
 *
 * @FieldFormatter(
 *   id = "entity_user_access_f",
 *   label = @Translation("Entity User Access - Formatter"),
 *   description = @Translation("Entity User Access - Formatter"),
 *   field_types = {
 *     "entity_user_access",
 *   }
 * )
 */
     
class EntityUserAccessFormatter extends FormatterBase {
  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = array();
     
    foreach ($items as $delta => $item) {
      $elements[$delta] = array(
        'uid' => array(
          '#markup' => \Drupal\user\Entity\User::load($item->uid)->getUsername(),
          ),
        // Ավելացնել ավելի բովանդակություն
      );
    }
     
    return $elements;
  }
}

Այս օրինակն ունի շատ նման անշանագրություն, ինչպիսին վիջեթն էր, ուստի շատ բան չպետք է խոսենք։ viewElements() մեթոդը պարզապես ցույց է տալիս օգտագործողի անունը, որը պահպանված է դաշտի տեսակին պատկանող օգտվողի ID-ի միջոցով։ Դասի մուտքի հասանելիությունը պետք է իրականացվի էնտիթի մակարդակով։ Այսպիսով, այս իրականացումը ցույց կտա բոլոր օգտվողների անունները, ովքեր ունեն գաղտնաբառ տվյալ էնտիթի վրա։

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.