Skip to content

PHP Render Callback

Mengapa PHP Render?

Masalah dengan Save Component JSX

Ketika HTML output dari SaveComponent berubah setelah banyak post sudah tersimpan, WordPress mendeteksi ketidakcocokan dan menampilkan pesan error "Attempt Block Recovery".

Bayangkan Anda punya 500+ post dan mengubah satu class name di save component — semua 500 post akan rusak!

Solusi: PHP Render Callback

Dengan PHP render callback:

  • Database hanya menyimpan block comments + attributes (bukan HTML)
  • HTML dirender oleh PHP setiap kali halaman dimuat
  • Mengubah HTML output tidak merusak post yang sudah ada

Update Class JSXBlock

Tambahkan parameter opsional untuk render callback:

php
class JSXBlock {
    function __construct($name, $renderCallback = null, $data = null) {
        $this->name = $name;
        $this->renderCallback = $renderCallback;
        $this->data = $data;
        add_action('init', [$this, 'onInit']);
    }
    
    function onInit() {
        wp_register_script(
            $this->name,
            get_stylesheet_directory_uri() . "/build/{$this->name}.js",
            array('wp-blocks', 'wp-editor')
        );
        
        // Jika ada data untuk dilewatkan ke JavaScript
        if ($this->data) {
            wp_localize_script($this->name, $this->name, $this->data);
        }
        
        $args = array(
            'editor_script' => $this->name
        );
        
        // Jika render callback aktif
        if ($this->renderCallback) {
            $args['render_callback'] = [$this, 'ourRenderCallback'];
        }
        
        register_block_type("ourBlockTheme/{$this->name}", $args);
    }
    
    function ourRenderCallback($attributes, $content) {
        ob_start();
        require get_theme_file_path("/our-blocks/{$this->name}.php");
        return ob_get_clean();
    }
}

Parameter JSXBlock

ParameterDefaultFungsi
$name(wajib)Nama block
$renderCallbacknulltrue = gunakan PHP render
$datanullArray data dari PHP ke JS (via wp_localize_script)

Penggunaan

php
// Tanpa render callback (save ke database sebagai HTML)
new JSXBlock("genericHeading");

// Dengan render callback (PHP render setiap page load)
new JSXBlock("banner", true);

// Dengan render callback + data dari PHP ke JS
new JSXBlock("banner", true, array(
    'fallbackImage' => get_theme_file_uri('/images/library-hero.jpg')
));

Fungsi ourRenderCallback

php
function ourRenderCallback($attributes, $content) {
    ob_start();
    require get_theme_file_path("/our-blocks/{$this->name}.php");
    return ob_get_clean();
}
VariabelIsi
$attributesArray atribut block (imgURL, className, dll.)
$contentHTML konten nested/InnerBlocks

Pattern ob_start() / ob_get_clean()

ob_start()         → Mulai buffering output
  require ...      → File PHP menghasilkan HTML
return ob_get_clean()  → Ambil buffer & kembalikan sebagai string

File PHP Render

Contoh our-blocks/banner.php

php
<?php
if (!isset($attributes['imgURL'])) {
    $attributes['imgURL'] = get_theme_file_uri('/images/library-hero.jpg');
}
?>

<div class="page-banner">
    <div class="page-banner__bg-image"
         style="background-image: url('<?php echo esc_url($attributes['imgURL']); ?>');">
    </div>
    <div class="page-banner__content container">
        <?php echo $content; ?>
    </div>
</div>

Perhatikan Perbedaan

JSX (editor)PHP (render)
className="page-banner"class="page-banner"
style={{backgroundImage: ...}}style="background-image: ..."
<InnerBlocks /><?php echo $content; ?>

Di file PHP, gunakan HTML biasa (class= bukan className=)!


Update Save Component

Sekarang SaveComponent hanya mengembalikan InnerBlocks.Content:

js
function SaveComponent() {
  return <InnerBlocks.Content />;
}

Tidak ada HTML wrapper — semua HTML dirender oleh PHP.


Apa yang Disimpan di Database?

Sebelum (tanpa render callback):

html
<!-- wp:ourBlockTheme/banner {"imgURL":"http://..."} -->
<div class="page-banner">
  <div class="page-banner__bg-image" style="background-image: url(...)">
  </div>
  <div class="page-banner__content container">
    <!-- wp:ourBlockTheme/genericHeading {"text":"Hello","size":"large"} -->
    <h1 class="headline headline--large">Hello</h1>
    <!-- /wp:ourBlockTheme/genericHeading -->
  </div>
</div>
<!-- /wp:ourBlockTheme/banner -->

Sesudah (dengan render callback):

html
<!-- wp:ourBlockTheme/banner {"imgURL":"http://..."} -->
<!-- wp:ourBlockTheme/genericHeading {"text":"Hello","size":"large"} -->
<h1 class="headline headline--large">Hello</h1>
<!-- /wp:ourBlockTheme/genericHeading -->
<!-- /wp:ourBlockTheme/banner -->

Kunci: Hanya block comments + attributes yang tersimpan. HTML wrapper dirender oleh PHP.


Kesimpulan

KonsepPenjelasan
Masalah save HTMLUbah HTML → 500+ post rusak (Block Recovery)
SolusiPHP render callback — HTML dirender per-request
render_callbackFungsi PHP yang return HTML
ob_start/ob_get_cleanBuffer output PHP → return sebagai string
$attributesArray data block dari database
$contentHTML nested blocks (InnerBlocks)
Save componentHanya <InnerBlocks.Content />
File PHPHTML biasa (class=), echo $content untuk nested