Skip to content

Instantly share code, notes, and snippets.

@Shelob9
Last active February 4, 2024 20:38
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save Shelob9/144055408101e2fdfc4bf34adc85dd04 to your computer and use it in GitHub Desktop.
Save Shelob9/144055408101e2fdfc4bf34adc85dd04 to your computer and use it in GitHub Desktop.
Example Gutenberg block with server-side rendering. Gutenberg edit() block creates interface. Gutenberg saves settings automatically, the PHP function passed as `render_callback` to `register_block_type` is used to create HTML for front-end rendering of block.
const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;
const el = wp.element.createElement;
registerBlockType( 'hiRoy/serverSide', {
title: __( 'Server Side Block', 'text-domain' ),
icon: 'networking',
category: 'common',
attributes: {
images : {
default: [],
type: 'array',
}
},
edit({attributes, setAttributes, className, focus, id}) {
//Put a user interface here.
},
save({attributes, className}) {
//gutenberg will save attributes we can use in server-side callback
return null;
},
} );
<?php
register_block_type('hiRoy/serverSide', array(
'render_callback' => 'hi_roy_render_callback',
'attributes' => array(
'images' => array(
'type' => 'array'
)
)
)
);
function hi_roy_render_callback( $attributes ){
$images = $attributes[ 'images' ];
return '<div><!-- put image gallery here--></div>';
}
@bizm
Copy link

bizm commented Feb 15, 2022

How is it supposed to work without calling wp_enqueue_script? Below is the example how i do it in my custom wordpress theme:

<?php
  // this is probably your functions.php file

  function register_hiroy_serverside_block() {
    $script_path = get_template_directory_uri() . '/path/to/your/block/index.js';
    $asset_file = include( '/path/to/your/block/index.asset.php' );

    wp_enqueue_script(
      'hiroy-server-side',
      $script_path,
      $asset_file['dependencies'],
      $asset_file['version']
    );

    register_block_type('hiRoy/serverSide', array(
            'render_callback' => 'hi_roy_render_callback',
            'attributes' => array(
                'images' => array(
                    'type' => 'array'
                )
            )
        )
    );
  }

  function hiroy_render_callback( $attributes ){
    $images = $attributes[ 'images' ];
    return '<div><!-- put image gallery here--></div>';
  }

  add_action( 'init', 'register_hiroy_serverside_block' );
?>

That is the only way i could've got it working. All the tutorials and articles i found did not help me. I still don't understand how your example above can work at all. I mean it is in fact not registering anything, thus no blocks should appear in UI. Please anyone explain me what is it that i'm missing here. The whole wordpress architecture is driving me mad!

@wpexplorer
Copy link

@bizm - This gist isn't intended to explain how to register blocks it's just an example showing how to use the render_callback argument. Now, you don't actually have to use wp_enqueue_script to load your block JS file - you can and probably should be loading the file via your block.json file, see here: https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/ and scroll down to "Editor Script".

@Shelob9
Copy link
Author

Shelob9 commented Feb 16, 2022

@bizm Here is a more up to date example of how to set up a server-side rendered block: https://github.com/imaginarymachines/everything-all-of-the-time/blob/main/blocks/php-block/init.php

Two issues with your snippet that need corrected:

@ducktype
Copy link

ducktype commented Nov 21, 2023

add_action('init',function(){
  $block_meta = [
    'name' => 'test/test',
    'title' => 'Test',
    'render_callback' => function($attrs,$content,$block){
      return "TEST";
    }
  ];
  register_block_type($block_meta['name'],$block_meta);
  add_action('enqueue_block_editor_assets',function()use($block_meta){
    $screen = get_current_screen();
    if(!$screen->is_block_editor()) return;
    add_action('admin_print_footer_scripts',function()use($block_meta){
      echo "
       <script>
        var block = {
          edit: function({attributes, setAttributes, className, focus, id}) {
            return "HELLO"
          },
          save: function({attributes, className}) {
            return
          }
        }
        wp.blocks.registerBlockType('{$block_meta['name']}',block)
      </script>
      ";
    });
  });
});

@1ucay
Copy link

1ucay commented Dec 3, 2023

$block_metas = array(
    array(
        'name'  => 'domain/faq',
        'title' => __( 'FAQ', 'domain' ),
        'description' => '',
        'category' => 'text',
        'icon'  => 'star-filled',
        'api_version' => 2
    ),
    array(
        'name'  => 'domain/accordion',
        'title' => __( 'Accordion', 'domain' ),
        'description' => '',
        'category' => 'text',
        'icon'  => 'star-filled',
        'api_version' => 2
    )
);
foreach( $block_metas as $block_meta ) {

    $block_meta['render_callback'] = function ( $block_attributes, $content ) use ( $block_meta ) {
        ob_start();

        $file = ( str_contains( $block_meta['name'], '/' ) ) ? explode( '/', $block_meta['name'] )[1] : $block_meta['name'];

        if ( ob_get_level() ) {
            // https://wordpress.stackexchange.com/questions/4462/passing-variables-through-locate-template
            if ( $filepath = locate_template( "blocks/{$file}/{$file}.php", true, true, array_merge( $_REQUEST, $block_meta, $block_attributes ) ) )
                include_once( $filepath );

            $output = ob_get_contents();
            ob_end_clean();
        }

        return $output;
    };
    register_block_type( $block_meta['name'], $block_meta );

    add_action( 'enqueue_block_editor_assets', function() use ( $block_meta ) {
        add_action( 'admin_print_footer_scripts', function() use ( $block_meta ) {
            echo "
            <script>
                wp.blocks.registerBlockType('{$block_meta['name']}', {
                    edit: function( props ) {
                        return wp.element.createElement(
                            wp.serverSideRender, {
                                block: props.name
                            }
                        );
                    },
                    save: function({attributes, className}) {
                        return null;
                    }
                })
            </script>
            ";
        });
    });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment