0
135

SHARE

Como Criar um Bloco Dinâmico no WordPress com Renderização PHP

Bloco Dinâmico com Renderização no Servidor

Aprenda a criar um bloco Gutenberg que carrega posts no editor e renderiza via PHP no frontend. Estrutura profissional com render_callback!
Este post é a parte 3 de 20 da Série WordPress Extremo: Gutenberg + React + Blocos Customizados

Neste dia, exploramos como criar um bloco dinâmico que se adapta tanto no editor quanto no frontend, utilizando atributos do Gutenberg e a função render_callback() no PHP para gerar o HTML final — o famoso bloco com renderização via servidor.


✍️ O que você vai aprender:

  • Criar um bloco com lista de posts via REST API no editor.
  • Exibir os posts de forma dinâmica no frontend com PHP.
  • Separar responsabilidades: JS (editor) e PHP (renderização).
  • Evitar erros de conflito de blocos duplicados.
  • Estruturar o código com qualidade de produção.

✅ Pré-requisitos:

  • Plugin wp-arquitetura-extrema já iniciado.
  • Pasta blocks/posts criada.
  • WP-CLI, Composer e @wordpress/scripts funcionando.
  • Webpack configurado no webpack.config.js.

🛠️ Estrutura do bloco posts:

blocks/
└── posts/
    ├── block.json
    ├── edit.js
    ├── save.js
    ├── index.js
    └── components/
        └── PostList.js

🔁 Código do Bloco

📦 block.json

{
  "apiVersion": 2,
  "name": "wp24h/posts",
  "title": "Lista de Posts WP24H",
  "category": "widgets",
  "icon": "list-view",
  "description": "Um bloco que exibe os últimos posts via REST API.",
  "attributes": {
    "quantidade": {
      "type": "number",
      "default": 3
    }
  },
  "supports": {
    "html": false
  }
}

🧠 edit.js

import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, RangeControl } from '@wordpress/components';
import { useState, useEffect } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';
import PostList from './components/PostList';

export default function Edit({ attributes, setAttributes }) {
  const { quantidade } = attributes;
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    apiFetch({ path: `/wp/v2/posts?per_page=${quantidade}` })
      .then(setPosts);
  }, [quantidade]);

  return (
    <>
      <InspectorControls>
        <PanelBody title="Configurações">
          <RangeControl
            label="Quantidade de posts"
            min={1}
            max={10}
            value={quantidade}
            onChange={(val) => setAttributes({ quantidade: val })}
          />
        </PanelBody>
      </InspectorControls>

      <div {...useBlockProps()}>
        <PostList posts={posts} />
      </div>
    </>
  );
}

💾 save.js

import { useBlockProps } from '@wordpress/block-editor';

export default function save() {
  return null; // Usamos render_callback no PHP
}

🧩 index.js

import { registerBlockType } from '@wordpress/blocks';
import edit from './edit';
import save from './save';
import metadata from './block.json';

registerBlockType(metadata.name, {
  ...metadata,
  edit,
  save,
});

🧷 components/PostList.js

export default function PostList({ posts }) {
  if (!posts.length) return <p>Carregando posts...</p>;

  return (
    <ul className="wp24h-post-list">
      {posts.map(post => (
        <li key={post.id}>
          <strong>{post.title.rendered}</strong>
        </li>
      ))}
    </ul>
  );
}

⚙️ PHP — inc/register/posts.php

<?php

function wp24h_render_block_posts($attributes) {
  $qtd = isset($attributes['quantidade']) ? intval($attributes['quantidade']) : 3;

  $query = new WP_Query([
    'post_type' => 'post',
    'posts_per_page' => $qtd,
  ]);

  if (!$query->have_posts()) {
    return '<p>Sem posts recentes no momento.</p>';
  }

  ob_start();
  echo '<ul class="wp24h-post-list-frontend">';
  while ($query->have_posts()) {
    $query->the_post();
    echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
  }
  echo '</ul>';

  wp_reset_postdata();
  return ob_get_clean();
}

add_action('init', function () {
  $block_path = plugin_dir_path(__FILE__) . '../../blocks/posts';
  $script_path = plugin_dir_path(__FILE__) . '../../dist/posts.asset.php';

  if (!file_exists($script_path)) return;

  $asset = include $script_path;

  wp_register_script(
    'wp24h-posts',
    plugins_url('../../dist/posts.js', __FILE__),
    $asset['dependencies'],
    $asset['version']
  );

  register_block_type($block_path, [
    'editor_script'   => 'wp24h-posts',
    'render_callback' => 'wp24h_render_block_posts',
  ]);
});

🔁 Encaixe no seu plugin:

No wp-arquitetura-extrema.php:

require_once plugin_dir_path(__FILE__) . 'inc/register/posts.php';

E no Init.php, remova 'posts' da lista de blocos:

$blocks = ['hello', 'card'];

🧱 Webpack

Garanta que o webpack.config.js está configurado para gerar múltiplos blocos:

const path = require('path');
const defaultConfig = require('@wordpress/scripts/config/webpack.config');

module.exports = {
  ...defaultConfig,
  entry: {
    hello: path.resolve(__dirname, 'blocks/hello/index.js'),
    card: path.resolve(__dirname, 'blocks/card/index.js'),
    posts: path.resolve(__dirname, 'blocks/posts/index.js'),
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
    clean: false
  },
};

✅ Resultado

Agora você tem um bloco 100% funcional, que:

  • Exibe posts no editor (JS com REST API).
  • Renderiza no frontend com HTML puro via PHP (render_callback).
  • Está separado, modular e pronto pra produção.

📣 CTA final

Se você curtiu esse conteúdo e quer se tornar um desenvolvedor WordPress de elite, conheça:

Navegação<< Filtrando Posts por Categoria no Editor do BlocoConectando Blocos com a REST API do WordPress >>

Não perca mais nenhuma atualização aqui!

Ative as Notificações!

Clique aqui e, em seguida, clique em Permitir na caixa que aparecerá na parte superior da janela, próximo à barra de endereços.

Torne-se um Assinante e Eleve seu Conhecimento do WordPress!

Acesso Exclusivo, Suporte Especializado e Muito Mais.

Se você está aproveitando nosso conteúdo gratuito, vai adorar os benefícios exclusivos que oferecemos aos nossos assinantes! Ao se tornar um assinante do WP24Horas, você terá acesso a:

Não perca a oportunidade de maximizar seu potencial no WordPress. Clique no botão abaixo para se tornar um assinante e leve suas habilidades ao próximo nível!

Não perca mais nenhuma atualização aqui!

Tabela de Conteúdo
PUBLICIDADE
Últimos Posts
Listagem e Detalhes de Posts WordPress com API REST no Next.js

Listagem de Posts e Roteamento Dinâmico no Next.js

Frontend com Next.js - Setup e Integração Inicial com WordPress

Frontend com Next.js: Setup e Integração Inicial

Configurando o WordPress como Backend Headless

Configurando o WordPress como Backend Headless

REST API do WordPress

REST API do WordPress: Visão Geral

Introdução ao WordPress Headless

Introdução ao WordPress Headless

Como Distribuir Seus Blocos Gutenberg em Plugins ou no GitHub

Distribuindo Seus Blocos: Plugins, Repositório e GitHub

Você precisa estar logado para ver esta informação.

Torne-se um Assinante e Eleve seu Conhecimento do WordPress!

Acesso Exclusivo, Suporte Especializado e Muito Mais.

Se você está aproveitando nosso conteúdo gratuito, vai adorar os benefícios exclusivos que oferecemos aos nossos assinantes! 

Não perca a oportunidade de maximizar seu potencial no WordPress. Clique no botão abaixo para se tornar um assinante e leve suas habilidades ao próximo nível!