Score:1

วิธีการใช้ TrustedCallbackInterface

ธง us

ฉันกำลังดูแลโมดูลที่ฉันได้สร้างนักพัฒนาบุคคลที่สามสำหรับฉัน ฉัน D9 ปัญหานี้ ปรากฏขึ้นเมื่อใช้โมดูลที่ทำงานอย่างอื่นใน D8 และควรเข้ากันได้กับ 8 และ 9

โมดูลสร้างบล็อกที่มีวันที่ของเหตุการณ์ที่ดึงมาจากบริการ Songkick แต่ในหน้า D9 ที่เปิดใช้งานบล็อก Songkick จะแสดงข้อผิดพลาดนี้:

Drupal\Core\Security\UntrustedCallbackException: แสดงผล #pre_render การโทรกลับต้องเป็นเมธอดของคลาสที่นำไปใช้ \Drupal\Core\Security\TrustedCallbackInterface หรือไม่ระบุตัวตน การทำงาน. การโทรกลับคือ _songkick_block_poweredby_prerender ดู https://www.drupal.org/node/2966725 ใน Drupal\Core\Render\Renderer->doTrustedCallback() (บรรทัดที่ 96 ของ /var/www/html/web/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php)

ฉันเป็นเพียงผู้สร้างเว็บไซต์ที่มีประสบการณ์การเขียนโค้ดที่จำกัด ดังนั้นฉันจึงต้องการความช่วยเหลือเพื่อแก้ไขปัญหานี้ ข้อผิดพลาดที่กล่าวถึง หน้านี้ อธิบายปัญหา

รหัสด้านล่างจากไฟล์ .module ของฉันมี pre_render ที่กล่าวถึง

/**
 * ใช้ hook_block_view_alter()
 */
ฟังก์ชัน songkick_block_content_view_alter (อาร์เรย์ &$build) {
    $id = $build['#block_content']->id();
  $block = \Drupal\block_content\Entity\BlockContent::load($id);
  $block_type = $block->type[0]->target_id;
  ถ้า ($block_type == 'songkick_block') {
        $build['#pre_render'][] = '_songkick_block_poweredby_prerender';
    }
}

/**
 * รับข้อมูล API เหตุการณ์ที่จะเกิดขึ้นและที่ผ่านมา
 */
ฟังก์ชัน _songkick_block_poweredby_prerender(อาร์เรย์ &$build) {
  $id = $build['#block_content']->id();
  $block = \Drupal\block_content\Entity\BlockContent::load($id);
  $block_type = $block->type[0]->target_id;
  ถ้า ($block_type == 'songkick_block') {
    // รับข้อมูลบล็อกที่กำหนดเอง
      $artis_id = $block->field_artist_id[0]->ค่า;
      $upcoming_show = $block->field_display_upcoming_shows[0]->ค่า;
      $past_show = $block->field_display_past_shows[0]->ค่า;
      $event_details = $block->field_ticket_button[0]->ค่า;
      $events_data = [
        'event_details' => $event_details,
        'upcoming_show' => $upcoming_show,
        'past_show' => $past_show
      ];
      $events_data = [
          '#theme' => 'songkick_events',
          '#events_data' => $events_data
      ];

        $client = \Drupal::httpClient();
        $api_key = \Drupal::config('songkick.settings')->get('songkick_key');
        $url = 'http://api.songkick.com/api/3.0/artists/';

        // ข้อมูลเหตุการณ์ที่จะเกิดขึ้น
    ถ้า ($upcoming_show == '1') {
            $apikey = $url $artis_id. "/calendar.json" . "?apikey=". $api_key;
            $request = $client->get($apikey);
            $body = $request->getBody()->getContents();
            $AllData = (อาร์เรย์)json_decode($body);
            // ข้อมูลหน้าสุดท้าย
            $per_page = $AllData['resultsPage']->ต่อหน้า;
            $total_entry = $AllData['resultsPage']->totalEntries;
            $page = (int)($total_entry / $per_page);
            //$mainData = $AllData['resultsPage']->results->event;
            $temp_var = [];
            สำหรับ ($x = $page; $x >= 0; $x--){ 
                $final_api_key = $apikey "&เพจ=" . $x;
                $upcoming_event_request = $client->get($final_api_key);
                $upcoming_event_body = $upcoming_event_request->getBody()->getContents();
                $UpcomingEventAllData = json_decode($upcoming_event_body);
                $mainData = array_reverse($UpcomingEventAllData->resultsPage->results->event);

                //$temp_data[] = $mainData;
                foreach ($mainData เป็น $value) {
                    $temp_var[] = $ค่า;
                }

            }
            $upcoming_events_data = [
          '#theme' => 'songkick_events',
          '#upcoming_event' => $temp_var
        ];
    }
    อื่น{
            $upcoming_events_data = [
          '#theme' => 'songkick_events',
          '#upcoming_event' =>''
        ];  
    }

    // ข้อมูลเหตุการณ์ที่ผ่านมา
    ถ้า ($ past_show == '1') {
            $apikey = $url $artis_id. "/gigography.json" . "?apikey=". $api_key;
            $request = $client->get($apikey);
            $body = $request->getBody()->getContents();
            $AllData = (อาร์เรย์)json_decode($body);

            // ข้อมูลหน้าสุดท้าย
            $per_page = $AllData['resultsPage']->ต่อหน้า;
            $total_entry = $AllData['resultsPage']->totalEntries;
            $page = (int)($total_entry / $per_page);

            $temp_var = [];
            สำหรับ ($x = $page; $x >= 0; $x--){ 
                $final_api_key = $apikey "&เพจ=" . $x;
                $past_event_request = $client->get($final_api_key);
                $past_event_body = $past_event_request->getBody()->getContents();
                $PastEventAllData = json_decode($past_event_body);
                $mainData = array_reverse($PastEventAllData->resultsPage->results->event);

                //$temp_data[] = $mainData;
                foreach ($mainData เป็น $value) {
                    $temp_var[] = $ค่า;
                }
            }
            //$final_api_key = $apikey "&เพจ=" . $เพจ;
            // $past_event_request = $client->get($final_api_key);
            // $past_event_body = $past_event_request->getBody()->getContents();
            // $PastEventAllData = (อาร์เรย์)json_decode($past_event_body);
            // $mainData = array_reverse($PastEventAllData['resultsPage']->results->event);
            $past_events_data = [
          '#theme' => 'songkick_events',
          '#past_event' => $temp_var
        ];
    }
    อื่น{
            $past_events_data = [
          '#theme' => 'songkick_events',
          '#past_event' =>''
        ];
    }

    // รวมข้อมูลเหตุการณ์ที่จะเกิดขึ้นและที่ผ่านมา
    $event_data = array_merge($upcoming_events_data,$past_events_data,$events_data);

    // ส่งคืนข้อมูลเหตุการณ์
        ส่งคืน $event_data;
  }
}

ฉันได้ลองทำตามคำแนะนำใน ความคิดเห็นนี้ และได้เพิ่มไฟล์ชื่อ SongkickBlockPoweredByViewBuilder.php ในโฟลเดอร์ src ด้วยรหัสนี้:

<?php

เนมสเปซ Drupal\Songkick;

ใช้ Drupal\Core\Security\TrustedCallbackInterface;

/**
 * ให้การโทรกลับที่เชื่อถือได้สำหรับบล็อก Songkick Poweredby
 *
 */
คลาส SongkickBlockPoweredByViewBuilder ใช้ TrustedCallbackInterface {

    /**
     * {@inheritdoc}
     */
    ฟังก์ชันสแตติกสาธารณะ trustCallbacks () {
     กลับ ['preRender'];    
   }
 
   /**
    * ตั้งค่า Songkick - #pre_render โทรกลับ
    */
   preRender ฟังก์ชันคงที่สาธารณะ ($ build) {
     $count = $build['content']['#count'];
     $build['content']['#count_text'] = \Drupal::translation()->formatPlural($count, '(@count)', '(@count)');
     ส่งคืน $build;
   }
 
 }

และฉันได้เพิ่มสิ่งต่อไปนี้ในไฟล์ .module ของฉัน:

ใช้ Drupal\Songkick\SongkickBlockPoweredByViewBuilder

/**
 * ใช้ TrustedCallbackInterface
 */
ฟังก์ชัน _songkick_block_poweredby_prerender (อาร์เรย์ &$build, Drupal\Core\Block\BlockPluginInterface $block) {
  $build['#pre_render'][] = [SongkickBlockPoweredByViewBuilder::class, 'preRender'];
}

จากนั้นไซต์จะแสดงข้อผิดพลาดร้ายแรงนี้:

ข้อผิดพลาดร้ายแรง: ไม่สามารถประกาศซ้ำ _songkick_block_poweredby_prerender() (เคยประกาศไว้ใน /var/www/html/web/modules/contrib/songkick/songkick.module:14) ใน /var/www/html/web/modules/contrib/songkick/songkick.module ที่บรรทัด 51

ข้อผิดพลาดร้ายแรงจะหายไปหากฉันลบการประกาศในบรรทัดที่ 14 แต่ข้อผิดพลาดเดิมยังคงอยู่ ฉันสูญเสียเกี่ยวกับวิธีกำหนดฟังก์ชันในบรรทัดที่ 51 ในวิธีที่ช่วยแก้ปัญหาได้ บรรทัดที่ 51 เริ่มต้นทันทีหลังจากความคิดเห็นนี้ในข้อความที่ตัดตอนมาจากไฟล์ .module ด้านบน:

/*** รับข้อมูล API เหตุการณ์ที่จะเกิดขึ้นและที่ผ่านมา */

เคล็ดลับใด ๆ

cn flag
Drupal แจ้งเตือนคุณพร้อมลิงก์เฉพาะที่อธิบายปัญหา หากคุณไม่เข้าใจเอกสารที่เชื่อมโยง คุณไม่เข้าใจอะไร และจะช่วยได้เสมอหากคุณโพสต์รหัสจริงที่เป็นสาเหตุของปัญหา ;)
us flag
คะแนนที่ถูกต้อง @PatrickKenny ขอบคุณ ฉันได้แก้ไขโพสต์ต้นฉบับเพื่อรวมสิ่งเหล่านั้น
Lambic avatar
ph flag
ความคิดเห็นนี้และการตอบกลับเกี่ยวกับปัญหาที่เชื่อมโยงกับข้อความแสดงข้อผิดพลาดมีตัวอย่างสิ่งที่คุณต้องทำ: https://www.drupal.org/node/2966725#comment-13948868
us flag
ขอบคุณมาก @Lambic ฉันแค่พยายามอย่างดีที่สุดแล้ว และฉันต้องทำอะไรผิดพลาดแน่ๆ เพราะมันส่งผลให้เกิดข้อผิดพลาดร้ายแรง ฉันได้อัปเดตคำถามด้วยขั้นตอนที่ฉันทำแล้ว ฉันชักชวนให้คุณดูได้ไหม
Lambic avatar
ph flag
ดูเหมือนว่าคุณมีการกำหนดฟังก์ชันเดียวกันสองครั้งใน songkick.module หนึ่งครั้งที่บรรทัดที่ 14 และอีกครั้งที่บรรทัดที่ 51
us flag
ฉันเข้าใจ ขอบคุณ ฉันได้เพิ่มรายละเอียดนั้นในคำถามแล้ว ข้อมูลเชิงลึกเกี่ยวกับวิธีที่ฉันสามารถแทนที่การประกาศเก่า (บรรทัดที่ 51) ด้วยประกาศใหม่ (บรรทัดที่ 14) ที่ใช้ TrustedCallbackInterface
apaderno avatar
us flag
คำถามไม่กลับไปกลับมาระหว่างผู้ใช้ที่ถามคำถามและผู้ใช้ที่ตอบคำถาม เมื่อตอบคำถามแล้ว จะไม่สามารถแก้ไขได้ หากการแก้ไขเปลี่ยนความหมายของคำถาม หรือเพิ่มคำถามติดตามผล (*ฉันทำตามที่คำตอบบอก แต่ตอนนี้ฉันมีปัญหาอื่น*)
Score:4
ธง fr

คุณมีความคิดที่ถูกต้อง มีรายละเอียดเพียงเล็กน้อยที่ต้องแก้ไข

TrustedCallbackInterface ถูกเพิ่มครั้งแรกใน Drupal 8.8; ไม่มีอยู่ก่อน Drupal 8.8 แม้จะเป็นทางเลือกใน Drupal 8.8 และ 8.9 แต่ก็เป็นเช่นนั้น บังคับ ใน Drupal 9 ดังนั้นโมดูลของคุณ ไม่ใช่ เข้ากันได้กับ Drupal 9 จนกว่าคุณจะทำการเปลี่ยนแปลงนี้

ขั้นแรก ให้คัดลอกเนื้อหาทั้งหมดของเวอร์ชันต้นฉบับของคุณ _songkick_block_poweredby_prerender() ของคุณ ฟังก์ชันคงที่สาธารณะ preRender($build). นั่นคือทั้งหมดที่ควรมีในตัวของ พรีเรนเดอร์() กระบวนการ.

ประการที่สอง ลบฟังก์ชัน _songkick_block_poweredby_prerender() (ทั้งสองสำเนา) จาก songkick.module คุณไม่ต้องการมันอีกต่อไปเพราะคุณใส่รหัสนั้นเข้าไปแล้ว Drupal\songkick\SongkickBlockPoweredByViewBuilder.

ตอนนี้ใส่ ใช้ Drupal\songkick\SongkickBlockPoweredByViewBuilder คำสั่งที่ด้านบนของ songkick.module พร้อมกับคำสั่งการใช้งานอื่นๆ ทั้งหมด จากนั้นเปลี่ยนคำสั่งนี้:

$build['#pre_render'][] = '_songkick_block_poweredby_prerender';

เพื่อชี้ไปที่รหัสใหม่ของคุณแทน แบบนี้:

$build['#pre_render'][] = [SongkickBlockPoweredByViewBuilder::class, 'preRender'];

โปรดทราบว่าเนมสเปซที่ถูกต้องมีตัวพิมพ์เล็กใน 'songkick' จะต้องเหมือนกับชื่อเครื่องของโมดูล และชื่อเครื่องไม่อนุญาตให้ใช้อักษรตัวพิมพ์ใหญ่ ดังนั้นคุณต้องแน่ใจว่า เนมสเปซ ประกาศใน SongkickBlockPoweredByViewBuilder ใช้ตัวพิมพ์เล็กและของคุณ ใช้ คำสั่งใน songkick.module ใช้ตัวพิมพ์เล็ก

Drupal ค่อนข้างพิถีพิถันในการตั้งชื่อ ดังนั้นต้องแน่ใจว่ามีไฟล์ .module ของคุณอยู่ด้วย songkick/songkick.module, ห้องเรียน SongkickBlockPoweredByViewBuilder อยู่ใน songkick/src/SongkickBlockPoweredByViewBuilder.php

us flag
ขอบคุณมาก. ข้อผิดพลาดดั้งเดิมหายไปแล้ว แต่บล็อกไม่แสดงรายการเหตุการณ์อีกต่อไป มีเพียงการตั้งค่าบล็อกเท่านั้น ฉันได้อัปเดตคำถามเพื่อสะท้อนถึงขั้นตอนที่ดำเนินการและรายงานบันทึกใหม่ ข้อมูลเชิงลึกใด ๆ ที่จะได้รับการชื่นชมอย่างมาก
fr flag
คุณไม่ได้ลบสามบรรทัดนี้ออกจาก preRender() ดังนั้นคุณจึงกลับมาจากฟังก์ชันก่อนที่โค้ดข้อมูลเหตุการณ์จะถูกเรียกใช้ด้วยซ้ำ: `$count = $build['content']['#count']; $build['content']['#count_text'] = \Drupal::translation()->formatPlural($count, '(@count)', '(@count)'); ส่งคืน $build;`
fr flag
และ ณ จุดนี้ เรากำลังดีบักโค้ดของคุณ ซึ่งอยู่นอกขอบเขตของปัญหานี้ และไม่เหมาะสมกับ StackExchange จริงๆ
us flag
จุดที่ถูกต้องขออภัยเกี่ยวกับเรื่องนี้ อย่างไรก็ตาม ขอบคุณมากสำหรับความช่วยเหลือของคุณ ฉันจะยอมรับคำตอบของคุณเดี๋ยวนี้

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา