9.11.3. Էնթիթի կեռիկներ
Նախորդ հոդվածներում մենք արդեն հանդիպել ենք hook-երին։ Այս հոդվածում մենք մանրամասն կդիտարկենք այն hook-երը, որոնք օգնում են աշխատել էակների հետ։
Այս հոդվածում դուք կարող եք ընդհանուր տեղեկություն ստանալ այն մասին, թե ինչ են hook-երը և ինչու են դրանք անհրաժեշտ՝
http://drupalbook.org/drupal/92-what-hook-drupal-8
Մենք կօգտագործենք hook-եր՝ մեր սեփական կոդը ավելացնելու համար, որը կգործարկվի որոշակի իրադարձությունների դեպքում՝ կապված էակների հետ՝ ավելացում, ջնջում, թարմացում։
Դուք կարող եք տեսնել բոլոր Drupal hook-երը հետևյալ էջում՝
https://api.drupal.org/api/drupal/core!core.api.php/group/hooks/8.2.x
Մենք կդիտարկենք միայն դրանց մի մասը, որոնք հաճախ օգտագործվում են բովանդակության հետ աշխատող սեփական մոդուլներում։
Ես ամբողջ կոդը ավելացրել եմ GitHub-ում՝ drupalbook_examples մոդուլում։ Դուք կարող եք ներբեռնել մոդուլը և ավելացնել ձեր կայքում՝
https://github.com/levmyshkin/drupalbook8
hook_entity_presave()
/**
* Implements hook_entity_presave().
*/
function drupalbook_examples_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
if ($entity->getEntityTypeId() == 'node' && $entity->getType() == 'article') {
$entity->title->value = $entity->title->value . 'by ' . date('d-m-Y');
}
}
Hook_entity_presave() գործարկվում է ամեն անգամ, երբ էակը պահպանվում է։
Դուք կարիք չունեք կանչել $entity->save() hook-ի ներսում, քանի որ էակի օբյեկտը կփոփոխվի պահպանելուց առաջ։ Այս օրինակում մենք հոդվածի վերնագրին ավելացնում ենք ընթացիկ ամսաթիվը։ Եթե հաջորդ օրը թարմացնենք հոդվածը, նոր ամսաթիվը կրկին կավելացվի։ Եթե վերնագրից չհեռացնենք հին ամսաթվերը, ապա վերնագիրը ամեն անգամ կերկարաձգվի։ Ամենաշատը մենք ստուգում ենք որոշակի դաշտերում արժեքների առկայությունը կամ ուղարկում ենք էլ․ նամակ՝ հոդվածի փոփոխության մասին։
Նշենք, որ սկզբում ստուգում ենք էակի տեսակը, քանի որ hook_entity_presave() աշխատում է բոլոր էակների՝ բովանդակության, բլոկների, մեկնաբանությունների, տաքսոնոմիաների համար։ Նաև ստուգում ենք հանգույցի bundle-ը։
hook_entity_insert()
/**
* Implements hook_entity_insert().
*/
function drupalbook_examples_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {
if ($entity->getEntityTypeId() == 'node' && $entity->getType() == 'page') {
$node = Node::create([
'type' => 'article',
'title' => 'New page created: ' . $entity->title->value,
]);
$node->save();
}
}
Hook_entity_insert() գործարկվում է նոր էակ ավելացնելիս։ Օրինակ՝ եթե կայքում ստեղծվում է նոր էջ, ապա ավտոմատ կստեղծվի նաև հոդված։ Եթե ունեք նախորդ hook-ը, ապա հոդվածի վերնագրին կավելացվի նաև ամսաթիվ։
Նշենք, որ hook_entity_insert() տարբեր է hook_entity_presave()-ից։ Առաջինը աշխատում է միայն էակը ավելացնելիս և չի փոխում դաշտերի արժեքները։ Եթե նույն կոդը տեղադրեք երկրորդ hook-ում, ապա այն չի աշխատի՝
/**
* Implements hook_entity_insert().
*/
function drupalbook_examples_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {
if ($entity->getEntityTypeId() == 'node' && $entity->getType() == 'article') {
$entity->title->value = $entity->title->value . 'by ' . date('d-m-Y');
}
}
Իհարկե, կարելի է պահպանել փոփոխությունները՝
function your_module_entity_insert(Drupal\Core\Entity\EntityInterface $entity){
if ($entity->getType() == 'article') {
drupal_register_shutdown_function('_your_module_post_insert', $entity);
}
}
function _your_module_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {
if ($entity) {
$entity->save();
}
}
Բայց խորհուրդ չի տրվում այդպես անել։ Ավելի լավ է hook_entity_presave()-ը օգտագործել՝ հենց էակը փոփոխելու, իսկ hook_entity_insert()-ը՝ այլ էակների կամ գործողությունների համար։
hook_entity_update()
/**
* Implements hook_entity_update().
*/
function drupalbook_examples_entity_update(Drupal\Core\Entity\EntityInterface $entity) {
if ($entity->getEntityTypeId() == 'node' && $entity->getType() == 'page') {
\Drupal::messenger()->addMessage('Page has been changed: ' . $entity->title->value);
}
}
Hook_entity_update() գործարկվում է ամեն անգամ, երբ էակը թարմացվում է։ Այստեղ նույնպես խորհուրդ չի տրվում փոխել էակի դաշտերը։ Ինչպես insert hook-ը, այս hook-ը ևս նախատեսված է գործողությունների համար, որոնք կապված չեն էակի դաշտերի հետ։ Օգտագործեք այն լոգավորման, հաղորդագրությունների կամ այլ գործողությունների համար։
Նաև մի կատարեք $entity->save(), որպեսզի չգործարկեք hook_entity_update() կրկին։ Եթե անում եք՝ համոզվեք, որ ցիկլ չի առաջանում։
hook_entity_delete()
Այլ hook՝ լոգավորման և գործողությունների համար՝ էակ ջնջելուց հետո։
hook_entity_access()
<?php
use Drupal\Core\Access\AccessResult;
...
/**
* Implements hook_entity_access().
*/
function drupalbook_examples_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account) {
if ($entity->getEntityTypeId() == 'node' && $entity->getType() == 'article' && $operation == 'view' && in_array('administrator', $account->getRoles())) {
AccessResult::forbidden();
}
}
?>
Այս օրինակում մենք արգելափակում ենք article տիպի հանգույցները բոլոր այն օգտատերերի համար, ովքեր չունեն administrator դերը։ Եթե ձեզ բավարարում են իրավունքների ստանդարտ կարգավորումները, ապա ավելի լավ է օգտագործել դրանք։
Hook_entity_access()-ը թույլ է տալիս ճկուն կերպով վերահսկել մատչելիությունը՝ օրինակ՝ ըստ ժամանակացույցի, օգտատիրոջ վարկանիշի, մակարդակի և այլն։ Բայց եթե դուք պարզապես այս hook-ով սահմանափակում եք մատչելիությունը, դա կարող է ապակողմնորոշել մյուս ծրագրավորողին։
Սա hook-երի հիմնական թերություններից մեկն է՝ երրորդ կողմի կոդի անտեսանելիությունը։ Եթե չիմանաք, որ կա մոդուլ, որն իրականացնում է hook_entity_presave(), ապա չեք հասկանա, թե ինչու է հոդվածի վերնագիրը փոփոխվում։ Այդ պատճառով նման պահվածքի դեպքում անհրաժեշտ է փնտրել համապատասխան hook-երը ամբողջ նախագծում։
Մենք դիտարկեցինք միայն մի քանի hook, բայց կարծում եմ, արդեն պատկերացնում եք՝ երբ պետք է օգտագործել hook-երը։ Որքան շատ աշխատեք Drupal-ի հետ, այնքան ավելի հաճախ ձեզ անհրաժեշտ կլինի գրել սեփական կոդ։ Եթե hook-ը հարմար է ձեր նպատակների համար, մի վախեցեք այն կիրառելուց ձեր մոդուլում։