Դաշտի տեսակներ, դաշտի վիջեթներ և դաշտի ձևաչափավորիչներ
Վերանայում
Drupal 8-ն ունի մեծ հավաքածու հիմնական դասերի, որոնք թույլ են տալիս աշխատել ձեր սեփական կոնտենտի հետ։ Երբ խոսքը գնում է կոնտենտի էնտիթիների մասին, դուք ցանկանում եք օգտագործել դաշտեր։ Կարևոր է հասկանալ դաշտերը, քանի որ հենց այնտեղ են ձեր էնտիթիները պահում իրենց տվյալները։
Դաշտի տեսակներ (FieldTypes)
Հիմնական դաշտի տեսակներն են՝
- boolean
- changed
- comment
- created
- datetime
- daterange
- decimal
- entity_reference
- file
- float
- image
- integer
- language
- link
- list_float
- list_integer
- list_string
- map
- password
- path
- string
- string_long
- telephone
- text
- text_long
- text_with_summary
- timestamp
- uri
- uuid
Հարմարեցված դաշտերի տեսակներ
Երբևէ, երբ ցանկանում եք ներկայացնել տվյալներ այնպես, ինչպես 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-ի միջոցով։ Դասի մուտքի հասանելիությունը պետք է իրականացվի էնտիթի մակարդակով։ Այսպիսով, այս իրականացումը ցույց կտա բոլոր օգտվողների անունները, ովքեր ունեն գաղտնաբառ տվյալ էնտիթի վրա։