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