{"id":82633,"date":"2026-04-06T09:29:08","date_gmt":"2026-04-06T07:29:08","guid":{"rendered":"https:\/\/kinsta.com\/es\/?p=82633&#038;preview=true&#038;preview_id=82633"},"modified":"2026-04-07T09:29:54","modified_gmt":"2026-04-07T07:29:54","slug":"bloques-gutenberg-solo-php","status":"publish","type":"post","link":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/","title":{"rendered":"C\u00f3mo construir bloques Gutenberg s\u00f3lo en PHP"},"content":{"rendered":"<p>Durante a\u00f1os, para dominar el desarrollo de bloques en Gutenberg era necesario tener un conocimiento profundo de tecnolog\u00edas como React y Node.js, adem\u00e1s de seguir pasos de construcci\u00f3n complejos y utilizar herramientas de JavaScript.<\/p>\n<p>Sin embargo, el desarrollo de WordPress est\u00e1 evolucionando, y ahora puedes crear y gestionar bloques de Gutenberg \u00edntegramente en PHP.<\/p>\n<p>Esto resulta especialmente \u00fatil para los desarrolladores que prefieren evitar React y el desarrollo con JavaScript (JS) del lado del servidor. Reduce la curva de aprendizaje, agiliza la experiencia del desarrollador y permite un mayor rendimiento al eliminar la sobrecarga innecesaria de los scripts del front end.<\/p>\n<p>En las siguientes secciones, aprender\u00e1s a sacar partido a estas nuevas funcionalidades para crear bloques de Gutenberg solo con PHP. A lo largo del proceso, aprender\u00e1s a crear sitios web de WordPress m\u00e1s ligeros, r\u00e1pidos y f\u00e1ciles de mantener.<\/p>\n<p>Muy emocionante, \u00bfverdad? Empecemos.<\/p>\n<p><aside role=\"note\" class=\"wp-block-kinsta-notice is-style-important\">\n            <h3>Important<\/h3>\n        <p>Ten en cuenta que los bloques exclusivos de PHP que se mencionan en este art\u00edculo se encuentran actualmente en fase experimental y pueden sufrir cambios. <b>\u00a1No utilices esta funcionalidad en entornos de producci\u00f3n!<\/b><\/p>\n<\/aside>\n<br \/>\n<div><\/div><kinsta-auto-toc heading=\"Table of Contents\" list-style=\"arrow\" selector=\"h2\" count-number=\"-1\"><\/kinsta-auto-toc><\/p>\n<h2>\u00bfQu\u00e9 son los bloques exclusivos de PHP y por qu\u00e9 son importantes?<\/h2>\n<p>Antes, para crear un bloque de Gutenberg se necesitaban conocimientos avanzados de JavaScript del lado del servidor y de programaci\u00f3n con React. Esto supuso un obst\u00e1culo para que los desarrolladores veteranos de WordPress, que quiz\u00e1 no contaban con los conocimientos necesarios de <a href=\"https:\/\/kinsta.com\/es\/blog\/que-es-react-js\/\">React<\/a> y <a href=\"https:\/\/kinsta.com\/es\/blog\/que-es-node-js\/\">Node.js<\/a>.<\/p>\n<p>Ahora las cosas est\u00e1n cambiando. A partir de <a href=\"https:\/\/make.wordpress.org\/core\/2025\/10\/08\/whats-new-in-gutenberg-21-8-08-october\/\">Gutenberg 21.8<\/a>, puedes registrar bloques Gutenberg utilizando \u00fanicamente <a href=\"https:\/\/kinsta.com\/es\/blog\/puntos-de-referencia-php\/\">PHP<\/a>. Esto evita las complejidades de configurar un entorno Node.js para quienes no trabajan con JavaScript del lado del servidor.<\/p>\n<p>Con el registro de bloques solo en PHP, puedes registrar y mostrar bloques tanto en el editor como en la interfaz p\u00fablica utilizando el mismo c\u00f3digo PHP. Esto anima a los sitios que usan temas h\u00edbridos o funciones PHP tradicionales y <a href=\"https:\/\/kinsta.com\/es\/blog\/codigos-cortos-wordpress\/\">shortcodes<\/a> a adoptar y desarrollar en el editor de bloques.<\/p>\n<p>Para los que quieran saber m\u00e1s, aqu\u00ed est\u00e1n las principales solicitudes de incorporaci\u00f3n de cambios (PRs) de GitHub dedicadas a los bloques exclusivos de PHP.<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/71794\" target=\"_blank\" rel=\"noopener noreferrer\">Permitir el registro de bloques s\u00f3lo PHP<\/a>: Este PR implementa el registro autom\u00e1tico de bloques del lado del servidor y cambia el nombre del soporte <code>auto_ssr<\/code> a <code>auto_register<\/code>.<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/73556\">Bloques s\u00f3lo PHP: Pasan todos los metadatos del registro PHP al cliente<\/a>: Los bloques s\u00f3lo PHP con soporte <code>auto_register<\/code> ahora pasan todos los metadatos al cliente desde el registro PHP.<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/74102\">Bloques s\u00f3lo PHP: Generar controles del inspector a partir de atributos<\/a>: Este PR introduce la generaci\u00f3n autom\u00e1tica de la interfaz de usuario (controles del inspector) a partir de los atributos declarados en el servidor.<\/li>\n<\/ul>\n<h2>C\u00f3mo construir tu primer bloque Gutenberg s\u00f3lo con PHP<\/h2>\n<p>Cuando un bloque se registra solo en el lado del servidor \u2014sin archivos JS\u2014 y el nuevo indicador de compatibilidad <code>auto_register<\/code> est\u00e1 establecido en <code>true<\/code>, el editor utiliza autom\u00e1ticamente el componente <code>ServerSideRender<\/code> para registrar el bloque en el lado del cliente y mostrar la vista previa del bloque. En esencia, el contenido del bloque se genera ahora directamente a partir del c\u00f3digo PHP tanto en el editor como en el frontend.<\/p>\n<aside role=\"note\" class=\"wp-block-kinsta-notice is-style-important\">\n            <h3>Important<\/h3>\n        <p>Los ejemplos mostrados en este art\u00edculo s\u00f3lo funcionar\u00e1n si tienes instalado <a href=\"https:\/\/make.wordpress.org\/core\/2025\/12\/17\/gutenberg-22-3-december-17\/\" target=\"_blank\" rel=\"noopener noreferrer\">Gutenberg 22.3<\/a> en tu sitio web de desarrollo<\/p>\n<\/aside>\n\n<p>Para ilustrarlo, aqu\u00ed tienes un sencillo ejemplo PHP que registra un bloque utilizando el m\u00e9todo s\u00f3lo PHP.<\/p>\n<pre><code class=\"language-php\">\/**\n * Render callback (frontend and editor)\n *\/\nfunction my_php_only_block_render( $attributes ) {\n\treturn '&lt;div&gt;\n\t\t&lt;h3&gt;\ud83d\ude80 PHP-only Block&lt;\/h3&gt;\n\t\t&lt;p&gt;This block was created with only PHP!&lt;\/p&gt;\n\t&lt;\/div&gt;';\n}\n\n\/**\n * Register the block on the 'init' hook.\n *\/\nadd_action( 'init', function() {\n\tregister_block_type( 'my-plugin\/php-only-test-block', array(\n\t\t'title'           =&gt; 'My PHP-only Block',\n\t\t'icon'            =&gt; 'welcome-learn-more',\n\t\t'category'        =&gt; 'text',\n\t\t'render_callback' =&gt; 'my_php_only_block_render',\n\t\t'supports'        =&gt; array(\n\t\t\t\/\/ Automatically registers the block in the Editor JS (previously auto_ssr)\n\t\t\t'auto_register' =&gt; true, \n\t\t),\n\t) );\n});<\/code><\/pre>\n<p>Puedes probar este c\u00f3digo copi\u00e1ndolo y peg\u00e1ndolo en el archivo principal de un plugin personalizado. Despu\u00e9s de activar el plugin, deber\u00edas ver \u00abMi bloque s\u00f3lo PHP\u00bb en el selector de bloques.<\/p>\n<figure id=\"attachment_206054\" aria-describedby=\"caption-attachment-206054\" style=\"width: 1644px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-206054 size-full\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2026\/02\/basic-php-only-block.png\" alt=\"Un bloque sencillo solo en PHP en el editor de bloques\" width=\"1644\" height=\"656\"><figcaption id=\"caption-attachment-206054\" class=\"wp-caption-text\">Un bloque sencillo solo en PHP<\/figcaption><\/figure>\n<p>La <a href=\"https:\/\/kinsta.com\/es\/blog\/bloques-dinamicos\/#register-the-block-on-the-server\">funci\u00f3n <code>register_block_type<\/code><\/a> registra un tipo de bloque en el servidor. Ahora <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/73556\" target=\"_blank\" rel=\"noopener noreferrer\">incluye el nuevo soporte <code>auto_register<\/code><\/a>, que indica a Gutenberg que pase los metadatos del registro PHP.<\/p>\n<p>La funci\u00f3n acepta dos argumentos:<\/p>\n<ul>\n<li>El nombre del tipo de bloque, incluido el espacio de nombres. En este ejemplo, el nombre del bloque es <code>my-plugin\/php-only-test-block<\/code>.<\/li>\n<li>Un array de par\u00e1metros para el tipo de bloque. En el c\u00f3digo anterior, establecemos <code>title<\/code>, <code>icon<\/code>, <code>category<\/code>, <code>render_callback<\/code> y <code>supports<\/code>. De nuevo, para los tipos de bloque exclusivos de PHP, el array <code>supports<\/code> debe incluir <code>\u201cauto_register\u201d =&gt; true<\/code>.<\/li>\n<\/ul>\n<p>Adem\u00e1s de simplificar la creaci\u00f3n de tipos de bloques personalizados y facilitar su integraci\u00f3n en temas h\u00edbridos, los bloques solo PHP pueden utilizarse como envoltorios para funciones PHP heredadas y shortcodes. Por otra parte, el uso de bloques solo PHP abre la puerta a nuevas oportunidades para integraciones personalizadas y funcionalidades del lado del servidor.<\/p>\n<p>Seg\u00fan <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/issues\/71792\">H\u00e9ctor Priethor<\/a><\/p>\n<blockquote><p>Un modelo de registro puramente PHP simplificar\u00eda los requisitos m\u00ednimos para el desarrollo de bloques, poni\u00e9ndolos a disposici\u00f3n de un p\u00fablico m\u00e1s amplio de desarrolladores, y ayudar\u00eda a hacer crecer el ecosistema de bloques m\u00e1s all\u00e1 del uso avanzado de JavaScript.<\/p><\/blockquote>\n<h2>Uso de atributos para construir la interfaz de usuario de configuraci\u00f3n de bloques<\/h2>\n<p><a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/74102\">PR 74102<\/a> permite generar autom\u00e1ticamente controles de inspecci\u00f3n a partir de las definiciones de atributos de los bloques. Esto permite a los usuarios configurar el aspecto y la funcionalidad de tus bloques exclusivos de PHP como si fueran cualquier bloque de Gutenberg registrado mediante JavaScript.<\/p>\n<p>Antes, ten\u00edas que crear manualmente un archivo <code>edit.js<\/code> en React y definir varios controles de configuraci\u00f3n mediante componentes React.<\/p>\n<p>Ahora, Gutenberg lee las definiciones de atributos y genera autom\u00e1ticamente los campos de entrada correspondientes en el editor de WordPress.<\/p>\n<p>El sistema mapea los tipos de datos definidos en el array de <code>attributes<\/code>\u00a0a definiciones de campo <code>DataForm<\/code>.<\/p>\n<ul>\n<li><code>'type' =&gt; 'string'<\/code> genera un campo de texto.<\/li>\n<li><code>'type' =&gt; 'number'<\/code> genera un campo num\u00e9rico.<\/li>\n<li><code>'type' =&gt; 'integer'<\/code> genera un campo entero.<\/li>\n<li><code>'type' =&gt; 'boolean'<\/code> genera una casilla de verificaci\u00f3n.<\/li>\n<li><code>'type' =&gt; 'string'<\/code> con <code>'enum' =&gt; array()<\/code> genera un campo select.<\/li>\n<\/ul>\n<p>Te dar\u00e1s cuenta de que s\u00f3lo puedes utilizar unos pocos controles. Si necesitas controles espec\u00edficos, como <code>RichText<\/code>, <code>RangeControl<\/code> o <code>ToggleControl<\/code>, tendr\u00e1s que seguir optando por el enfoque JS\/React.<\/p>\n<p>Sin embargo, esta novedad tiene ventajas considerables. Se reducen a\u00fan m\u00e1s las barreras de entrada y no tendr\u00e1s que aprender a usar React, Webpack o NPM para crear bloques personalizados con opciones sencillas de edici\u00f3n.<\/p>\n<p>En el siguiente ejemplo, ampliamos el bloque de muestra mostrado en la secci\u00f3n anterior a\u00f1adiendo algunos atributos.<\/p>\n<pre><code class=\"language-php\">\/**\n * 1. Define the block's HTML output.\n *\/\nfunction my_php_only_block_render( $attributes ) {\n\t\/\/ Extract attributes\n\t$title   = esc_html( $attributes['blockTitle'] );\n\t$count   = intval( $attributes['itemCount'] );\n\t$enabled = $attributes['isEnabled']; \/\/ Boolean from the ToggleControl\n\t$size    = esc_attr( $attributes['displaySize'] );\n\t\n\t\/\/ Start building the output\n\t$output = sprintf( '&lt;div class=\"my-php-block\" style=\"font-size: %s; border: 1px solid #ccc; padding: 15px;\"&gt;', \n\t\t$size === 'large' ? '20px' : ($size === 'small' ? '12px' : '16px') \n\t);\n\t\n\t$output .= sprintf( '&lt;h3&gt;\ud83d\ude80 %s&lt;\/h3&gt;', $title );\n\t\n\t\/\/ If the toggle is ON, show the list. If OFF, show a fallback message.\n\tif ( $enabled ) {\n\t\t$output .= '&lt;ul&gt;';\n\t\tfor ( $i = 1; $i &lt;= $count; $i++ ) {\n\t\t\t$output .= sprintf( '&lt;li&gt;Item %d&lt;\/li&gt;', $i );\n\t\t}\n\t\t$output .= '&lt;\/ul&gt;';\n\t} else {\n\t\t$output .= '&lt;p&gt;&lt;em&gt;The list is currently disabled.&lt;\/em&gt;&lt;\/p&gt;';\n\t}\n\t\n\t$output .= '&lt;\/div&gt;';\n\treturn $output;\n}\n\n\/**\n * 2. Register the block on 'init'.\n *\/\nadd_action( 'init', function() {\n\tregister_block_type( 'my-plugin\/php-only-test-block', array(\n\t\t'title'           =&gt; 'My PHP-only Block',\n\t\t'icon'            =&gt; 'welcome-learn-more',\n\t\t'category'        =&gt; 'text',\n\t\t'render_callback' =&gt; 'my_php_only_block_render',\n\n\t\t\/\/ Attributes used to generate the Inspector UI\n\t\t'attributes'      =&gt; array(\n\t\t\t'blockTitle'  =&gt; array(\n\t\t\t\t'type'    =&gt; 'string',\n\t\t\t\t'default' =&gt; 'PHP-only Block',\n\t\t\t),\n\t\t\t'itemCount'   =&gt; array(\n\t\t\t\t'type'    =&gt; 'integer',\n\t\t\t\t'default' =&gt; 3,\n\t\t\t),\n\t\t\t'isEnabled'   =&gt; array(\n\t\t\t\t'type'    =&gt; 'boolean',\n\t\t\t\t'default' =&gt; true,\n\t\t\t),\n\t\t\t'displaySize' =&gt; array(\n\t\t\t\t'type'    =&gt; 'string',\n\t\t\t\t'enum'    =&gt; array( 'small', 'medium', 'large' ),\n\t\t\t\t'default' =&gt; 'medium',\n\t\t\t),\n\t\t),\n\n\t\t'supports'        =&gt; array(\n\t\t\t'auto_register' =&gt; true, \n\t\t),\n\t) );\n});<\/code><\/pre>\n<p>Un vistazo r\u00e1pido a este c\u00f3digo revela lo f\u00e1cil que es registrar un bloque personalizado con todos sus ajustes de configuraci\u00f3n utilizando la nueva API. Los atributos se utilizan ahora no s\u00f3lo para almacenar los datos introducidos por el usuario, sino tambi\u00e9n para definir el esquema de la interfaz de usuario. El c\u00f3digo anterior hace lo siguiente:<\/p>\n<ul>\n<li>La funci\u00f3n <code>register_block_type<\/code> registra el tipo de bloque <code>my-plugin\/php-only-test-block<\/code>.<\/li>\n<li>El segundo argumento que se pasa a la funci\u00f3n es un array que contiene los siguientes elementos: <code>title<\/code>, <code>icon<\/code>, <code>category<\/code>, <code>render_callback<\/code>, <code>attributes<\/code> y <code>supports<\/code>.<\/li>\n<li>El array de <code>atributos<\/code> contiene los atributos del bloque. En el ejemplo anterior, el array incluye los elementos <code>blockTitle<\/code>, <code>itemCount<\/code>, <code>isEnabled<\/code> y <code>displaySize<\/code>.<\/li>\n<li><code>'auto_register' =&gt; true<\/code> activa el registro autom\u00e1tico en el servidor.<\/li>\n<\/ul>\n<p>Esto es lo que hace la funci\u00f3n de devoluci\u00f3n de llamada <code>my_php_only_block_render<\/code>:<\/p>\n<ul>\n<li>En primer lugar, la funci\u00f3n extrae los valores de los atributos del array <code>$attributes<\/code> y los asigna a las variables <code>$title<\/code>, <code>$count<\/code>, <code>$enabled<\/code> y <code>$size<\/code>.<\/li>\n<li>A continuaci\u00f3n, genera el contenido del bloque.<\/li>\n<\/ul>\n<p>Aqu\u00ed tienes el resultado en pantalla:<\/p>\n<figure id=\"attachment_206110\" aria-describedby=\"caption-attachment-206110\" style=\"width: 2074px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-206110 size-full\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2026\/02\/php-only-block-settings.png\" alt=\"Un bloque solo para PHP con configuraci\u00f3n de bloque\" width=\"2074\" height=\"1102\"><figcaption id=\"caption-attachment-206110\" class=\"wp-caption-text\">Un bloque s\u00f3lo PHP con la configuraci\u00f3n del bloque<\/figcaption><\/figure>\n<h2>Un ejemplo real de bloques que solo usan PHP<\/h2>\n<p>Aunque hay muchos casos en los que JavaScript sigue siendo necesario, ya se pueden hacer muchas cosas solo con bloques de PHP, sobre todo si se usan junto con las propiedades de los bloques.<\/p>\n<p>En el siguiente ejemplo, utilizamos la <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/get_block_wrapper_attributes\/\" target=\"_blank\" rel=\"noopener noreferrer\">funci\u00f3n <code>get_block_wrapper_attributes()<\/code><\/a>, que genera una cadena de atributos para el bloque actual que se est\u00e1 renderizando. El bloque recibir\u00e1 autom\u00e1ticamente los colores, bordes y sombras establecidos por el usuario, y aplicar\u00e1 los estilos correspondientes al contenedor principal. De este modo, el bloque es personalizable a trav\u00e9s de las herramientas nativas de Gutenberg, igual que un bloque basado en React.<\/p>\n<p>Para verlo en funcionamiento, crea una carpeta <code>smart-pricing-widget<\/code> en tu ordenador. En esta carpeta, crea un archivo <code>style.css<\/code> con el siguiente c\u00f3digo CSS:<\/p>\n<pre><code class=\"language-css\">\/* style.css *\/\n.tarjeta-precios {\n\tdisplay: flex;\n\tflex-direcci\u00f3n: columna;\n\talinear-elementos: centro;\n\talineaci\u00f3n-texto: centro;\n\tbox-sizing: border-box;\n}\n\n.pricing-card h3 {\n\tmargen: 0\n\tfont-size: 1.5rem;\n}\n\n.tarjeta-precio .precio-valor {\n\tfont-size: 3.5rem;\n\tfont-weight: 800;\n\tmargen: 15px 0;\n}\n\n.pricing-card ul {\n\testilo de lista: ninguno;\n\trelleno: 25px 0\n\tmargen: 20px 0;\n\tanchura: 100%;\n\tborde superior: 1px s\u00f3lido rgba(128,128,128,0.3);\n\tmostrar: flex;\n\tflex-direcci\u00f3n: columna;\n\tseparaci\u00f3n: 12px;\n}\n\n.pricing-card li {\n\tmostrar: flex;\n\talinear-elementos: centro;\n\tjustify-content: center;\n\tseparaci\u00f3n: 10px;\n}\n\n.pricing-card .cta-button {\n\tmargin-top: auto;\n\trelleno: 15px 25px;\n\tradio del borde: 8px;\n\tdecoraci\u00f3n del texto: ninguna;\n\tfont-weight: negrita;\n\ttransici\u00f3n: opacidad 0,2s;\n}\n\n.pricing-card .cta-button:hover {\n\topacidad: 0.8;\n}\n\n\/* Variaciones tem\u00e1ticas *\/\n.pricing-card.theme-light { color de fondo: #ffffff; color: #000000; }\n.pricing-card.theme-light .cta-button { color-de-fondo: #21759b; color: #ffffff; }\n\n.pricing-card.theme-dark { color de fondo: #1a1a1a; color: #ffffff; }\n.pricing-card.theme-dark .cta-button { color-de-fondo: #ffffff; color: #1a1a1a; }\n\n.pricing-card.theme-blue { color de fondo: #21759b; color: #ffffff; }\n.pricing-card.theme-blue .cta-button { color-de-fondo: #000000; color: #ffffff; }\n\n\/* Clases de utilidad *\/\n.pricing-card .is-full-width {\n\tanchura: 100%;\n\tdisplay: block;\n\talign-self: stretch;\n}<\/code><\/pre>\n<p>No comentaremos este c\u00f3digo, ya que se trata de una simple hoja de estilos para tu bloque de widgets.<\/p>\n<p>Ahora, crea el archivo principal de tu plugin, ll\u00e1malo <code>smart-pricing-widget.php<\/code>, y pega el siguiente c\u00f3digo:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\/**\n * Plugin Name: Smart Pricing Widget\n * Plugin URI:  https:\/\/example.com\/\n * Description: PHP-only Pricing Table block\n * Version:     1.2.0\n * Author:      Your Name\n * Text Domain: smart-pricing-widget\n *\/\n\nif ( ! defined( 'ABSPATH' ) ) exit;\n\n\/**\n * Render callback\n *\/\nfunction render_smart_pricing_block( $attributes ) {\n\t$plan_name = esc_html( $attributes['planName'] );\n\t$price     = intval( $attributes['price'] );\n\t$theme     = $attributes['blockTheme'];\n\t$btn_text  = esc_html( $attributes['buttonText'] );\n\t$btn_size  = $attributes['buttonSize'];\n\n\t$features_raw = $attributes['featuresList'];\n\t$features_array = array_filter( array_map( 'trim', explode( ',', $features_raw ) ) );\n\n\t$wrapper_attributes = wp_kses_data( get_block_wrapper_attributes( array(\n\t\t'class' =&gt; \"pricing-card theme-{$theme}\",\n\t) ) );\n\n\t$output = sprintf( '&lt;div %s&gt;', $wrapper_attributes );\n\t$output .= sprintf( '&lt;h3&gt;%s&lt;\/h3&gt;', $plan_name );\n\t$output .= sprintf( '&lt;div class=\"price-value\"&gt;\u20ac%d&lt;\/div&gt;', $price );\n\n\tif ( ! empty( $features_array ) ) {\n\t\t$output .= '&lt;ul&gt;';\n\t\tforeach ( $features_array as $feature ) {\n\t\t\t$is_checked = strpos( $feature, '+' ) === 0;\n\t\t\t$clean_text = esc_html( ltrim( $feature, '+- ' ) );\n\t\t\t$icon       = $is_checked ? '\u2705' : '\u274c';\n\t\t\t$style      = $is_checked ? '' : 'style=\"opacity: 0.6;\"';\n\t\t\t\n\t\t\t$output .= sprintf( '&lt;li %s&gt;&lt;span&gt;%s&lt;\/span&gt; %s&lt;\/li&gt;', $style, $icon, $clean_text );\n\t\t}\n\t\t$output .= '&lt;\/ul&gt;';\n\t}\n\n\t$btn_class = 'cta-button' . ( $btn_size === 'full' ? ' is-full-width' : '' );\n\t$output .= sprintf( '&lt;a href=\"#\" class=\"%s\"&gt;%s&lt;\/a&gt;', esc_attr( $btn_class ), $btn_text );\n\t$output .= '&lt;\/div&gt;';\n\n\treturn $output;\n}\n\n\/**\n * Register Assets and Block\n *\/\nadd_action( 'init', function() {\n\t\/\/ 1. Register the CSS file\n\twp_register_style(\n\t\t'smart-pricing-style',\n\t\tplugins_url( 'style.css', __FILE__ ),\n\t\tarray(),\n\t\t'1.2.0'\n\t);\n\n\t\/\/ 2. Register the Block\n\tregister_block_type( 'tutorial\/smart-pricing', array(\n\t\t'api_version'     =&gt; 3,\n\t\t'title'           =&gt; 'Pricing Card',\n\t\t'icon'            =&gt; 'cart',\n\t\t'category'        =&gt; 'widgets',\n\t\t'render_callback' =&gt; 'render_smart_pricing_block',\n\t\t\/\/ Link the registered style handle here\n\t\t'style'           =&gt; 'smart-pricing-style',\n\t\t'attributes'      =&gt; array(\n\t\t\t'planName'     =&gt; array( 'type' =&gt; 'string', 'default' =&gt; 'Professional' ),\n\t\t\t'price'        =&gt; array( 'type' =&gt; 'integer', 'default' =&gt; 49 ),\n\t\t\t'buttonText'   =&gt; array( 'type' =&gt; 'string', 'default' =&gt; 'Choose Plan' ),\n\t\t\t'buttonSize'   =&gt; array( 'type' =&gt; 'string', 'enum' =&gt; array( 'auto', 'full' ), 'default' =&gt; 'auto' ),\n\t\t\t'blockTheme'   =&gt; array( 'type' =&gt; 'string', 'enum' =&gt; array( 'light', 'dark', 'blue' ), 'default' =&gt; 'light' ),\n\t\t\t'featuresList' =&gt; array( 'type' =&gt; 'string', 'default' =&gt; \"+ Support, + Updates, - Domain\" ),\n\t\t),\n\t\t'supports'        =&gt; array(\n\t\t\t'auto_register' =&gt; true,\n\t\t\t'color'         =&gt; array( 'background' =&gt; true, 'text' =&gt; true ),\n\t\t\t'spacing'       =&gt; array( 'margin' =&gt; true, 'padding' =&gt; true ),\n\t\t\t'typography'    =&gt; array( 'fontSize' =&gt; true ),\n\t\t\t'shadow'        =&gt; true,\n\t\t\t'__experimentalBorder' =&gt; array( 'color' =&gt; true, 'radius' =&gt; true, 'style' =&gt; true, 'width' =&gt; true ),\n\t\t\t'border'        =&gt; array( 'color' =&gt; true, 'radius' =&gt; true, 'style' =&gt; true, 'width' =&gt; true ),\n\t\t),\n\t) );\n});<\/code><\/pre>\n<p>Este script incluye dos funciones. La funci\u00f3n <code>register_block_type()<\/code>\u00a0es el motor de tu plugin. \u00c9stos son sus elementos principales:<\/p>\n<ul>\n<li>El primer argumento es el identificador del bloque, incluido el espacio de nombres (<code>tutorial\/precios-inteligentes<\/code>).<\/li>\n<li>El segundo argumento es un array de argumentos. En el c\u00f3digo anterior, hemos establecido la versi\u00f3n de la API, el t\u00edtulo, el icono, la categor\u00eda, la llamada de retorno, el estilo, los atributos y los <a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/block-api\/block-supports\/\" target=\"_blank\" rel=\"noopener noreferrer\">soportes<\/a>.<\/li>\n<li>Los atributos del array generan los controles que utilizar\u00e1n los usuarios para a\u00f1adir contenido y configurar el bloque. El elemento <code>type<\/code> especifica el tipo de control que se a\u00f1adir\u00e1 al inspector de bloques. En este ejemplo, son campos de texto (<code>'type' =&gt; 'string'<\/code>), un entero (<code>'type' =&gt; 'integer'<\/code>), y un par de men\u00fas desplegables (<code>'type' =&gt; 'string', 'enum' =&gt; array()<\/code>).<\/li>\n<li>Los elementos del array <code>supports<\/code> a\u00f1aden caracter\u00edsticas que hacen que el estilo del bloque sea personalizable. Como hemos mencionado antes, el \u00fanico soporte necesario en un bloque s\u00f3lo PHP es <code>auto_register<\/code>, que permite la generaci\u00f3n autom\u00e1tica de la interfaz (UI) para atributos personalizados. Los otros soportes declarados anteriormente incluyen color, espaciado, tipograf\u00eda, sombra y borde.<\/li>\n<\/ul>\n<p>La funci\u00f3n de devoluci\u00f3n de llamada <code>render_smart_pricing_block()<\/code> genera el HTML del bloque. Aqu\u00ed tienes una descripci\u00f3n detallada de lo que hace esta funci\u00f3n:<\/p>\n<ul>\n<li>Extrae y sanea los atributos del bloque y, a continuaci\u00f3n, a\u00f1ade el c\u00f3digo CSS que genera la apariencia del bloque en el frontend y el editor.<\/li>\n<li>Las caracter\u00edsticas que se mostrar\u00e1n en el bloque (<code>$attributes['featuresList'];<\/code>) se gestionan por separado. Actualmente, no es posible a\u00f1adir controles avanzados a la barra lateral de configuraci\u00f3n del bloque. Para crear una lista, como una lista de caracter\u00edsticas, s\u00f3lo puedes utilizar un simple campo de texto. En este ejemplo, debes introducir manualmente las caracter\u00edsticas del producto, separadas por comas.<\/li>\n<li>La variable <code>$wrapper_attributes<\/code> es un contenedor para los atributos envolventes proporcionados por la <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/get_block_wrapper_attributes\/\">funci\u00f3n <code>get_block_wrapper_attributes<\/code><\/a>. Esta funci\u00f3n no se limita a a\u00f1adir las clases especificadas en el c\u00f3digo (<code>pricing-card theme-{$theme}<\/code>), sino que recupera autom\u00e1ticamente todas las personalizaciones de estilo que el usuario establece en el inspector de bloques, incluidos los colores, los bordes, el relleno, el margen, la sombra, la tipograf\u00eda y las clases de bloque est\u00e1ndar (<code>wp-block-tutorial-smart-pricing<\/code>).<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_kses_data\/\"><code>wp_kses_data<\/code><\/a> garantiza que no haya etiquetas o scripts maliciosos (XSS) en la cadena.<\/li>\n<li>El resto del c\u00f3digo genera el contenido del bloque.<\/li>\n<\/ul>\n<p>Activa el plugin y crea una nueva entrada o p\u00e1gina. Abre el insertador de bloques y despl\u00e1zate hasta la secci\u00f3n Widgets. Aqu\u00ed, deber\u00edas ver tu bloque \u00abPricing Card\u00bb identificado por un icono de carrito de la compra.<\/p>\n<figure id=\"attachment_206128\" aria-describedby=\"caption-attachment-206128\" style=\"width: 2034px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-206128 size-full\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2026\/02\/php-only-block-example.png\" alt=\"Un bloque personalizado s\u00f3lo PHP en el editor de bloques\" width=\"2034\" height=\"1322\"><figcaption id=\"caption-attachment-206128\" class=\"wp-caption-text\">Un bloque personalizado s\u00f3lo PHP en el editor de bloques<\/figcaption><\/figure>\n<p>La imagen de arriba muestra el bloque con el tema light por defecto.<\/p>\n<p>En la imagen inferior, puedes ver la versi\u00f3n oscura del bloque y los ajustes que has declarado en tu plugin.<\/p>\n<figure id=\"attachment_206129\" aria-describedby=\"caption-attachment-206129\" style=\"width: 2188px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-206129 size-full\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2026\/02\/php-only-dark-theme-block-settings.png\" alt=\"El bloque solo para PHP con la configuraci\u00f3n del bloque\" width=\"2188\" height=\"1652\"><figcaption id=\"caption-attachment-206129\" class=\"wp-caption-text\">El bloque solo para PHP con la configuraci\u00f3n del bloque<\/figcaption><\/figure>\n<p>La siguiente imagen muestra los controles de estilo que has a\u00f1adido con los ajustes del bloque.<\/p>\n<figure id=\"attachment_206130\" aria-describedby=\"caption-attachment-206130\" style=\"width: 2104px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-206130 size-full\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2026\/02\/php-only-customized-dark-theme.png\" alt=\"El tema oscuro del bloque s\u00f3lo PHP con colores personalizados\" width=\"2104\" height=\"1310\"><figcaption id=\"caption-attachment-206130\" class=\"wp-caption-text\">El tema oscuro del bloque s\u00f3lo PHP con colores personalizados<\/figcaption><\/figure>\n<p>Tambi\u00e9n cabe destacar que los estilos a\u00f1adidos por los soportes anulan los estilos del tema del bloque. Esto permite una mayor personalizaci\u00f3n de la apariencia del bloque, como se muestra en la siguiente imagen:<\/p>\n<figure id=\"attachment_206131\" aria-describedby=\"caption-attachment-206131\" style=\"width: 2406px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-206131 size-full\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2026\/02\/customized-php-only-blocks.png\" alt=\"Una tabla de precios para 3 niveles de servicio con tres instancias de tu bloque s\u00f3lo PHP\" width=\"2406\" height=\"1362\"><figcaption id=\"caption-attachment-206131\" class=\"wp-caption-text\">Una tabla de precios para 3 niveles de servicio con tres instancias de tu bloque s\u00f3lo PHP<\/figcaption><\/figure>\n<h2>Convierte shortcodes antiguos en bloques de Gutenberg con PHP puro<\/h2>\n<p>Uno de los usos m\u00e1s directos de los bloques PHP es como envoltorios de shortcodes. Con Gutenberg, puedes seguir utilizando shortcodes en tu contenido, pero tienes que insertar manualmente tu shortcode en un bloque Shortcode, lo que no es la experiencia m\u00e1s agradable.<\/p>\n<p>Supongamos que tienes el siguiente shortcode<\/p>\n<pre><code class=\"language-php\">function my_custom_alert_shortcode( $atts ) {\n\t$options = shortcode_atts( array(\n\t\t'type'    =&gt; 'info',\n\t\t'message' =&gt; 'Default alert message',\n\t), $atts );\n\n\t$styles = array(\n\t\t'info'    =&gt; 'background: #d1ecf1; color: #0c5460; border-color: #bee5eb;',\n\t\t'warning' =&gt; 'background: #fff3cd; color: #856404; border-color: #ffeeba;',\n\t\t'error'   =&gt; 'background: #f8d7da; color: #721c24; border-color: #f5c6cb;'\n\t);\n\n\t$style = $styles[ $options['type'] ] ?? $styles['info'];\n\n\treturn sprintf(\n\t\t'&lt;div class=\"sc-alert-box\" style=\"%s padding: 20px; border: 1px solid; border-radius: 6px; margin: 10px 0;\"&gt;\n\t\t\t&lt;strong style=\"text-transform: uppercase;\"&gt;%s:&lt;\/strong&gt; %s\n\t\t&lt;\/div&gt;',\n\t\tesc_attr( $style ),\n\t\tesc_html( $options['type'] ),\n\t\tesc_html( $options['message'] )\n\t);\n}\nadd_shortcode( 'sc_alert', 'my_custom_alert_shortcode' );<\/code><\/pre>\n<p>Este c\u00f3digo genera una sencilla caja que puedes insertar en tu contenido con el siguiente shortcode:<\/p>\n<pre><code class=\"language-text\">[sc_alert type=\"alert\" message=\"Hello\"]<\/code><\/pre>\n<p>En Gutenberg, utilizar\u00e1s un bloque Shortcode para insertar la caja en tu contenido, como se muestra en la siguiente imagen:<\/p>\n<figure id=\"attachment_206137\" aria-describedby=\"caption-attachment-206137\" style=\"width: 1304px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-206137 size-full\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2026\/02\/shortcode-block.png\" alt=\"Un bloque Shortcode\" width=\"1304\" height=\"272\"><figcaption id=\"caption-attachment-206137\" class=\"wp-caption-text\">Un bloque Shortcode<\/figcaption><\/figure>\n<p>La situaci\u00f3n cambia por completo con los bloques exclusivos de PHP. Ahora puedes incluir tu shortcode en un bloque de Gutenberg exclusivo de PHP y configurarlo a trav\u00e9s de los controles de la interfaz de usuario. Aqu\u00ed tienes el c\u00f3digo que debes a\u00f1adir a tu plugin:<\/p>\n<pre><code class=\"language-php\">\/**\n * Rendering callback\n *\/\nfunction render_shortcode_alert_wrapper_block( $attributes ) {\n\n\t$type    = esc_attr( $attributes['alertType'] );\n\t$message = esc_attr( $attributes['alertMessage'] );\n\n\t$shortcode_string = sprintf( '[sc_alert type=\"%s\" message=\"%s\"]', $type, $message );\n\n\t$wrapper_attributes = wp_kses_data( get_block_wrapper_attributes( array(\n\t\t'class' =&gt; 'wp-block-shortcode-alert-wrapper',\n\t) ) );\n\n\treturn sprintf(\n\t\t'&lt;div %s&gt;%s&lt;\/div&gt;',\n\t\t$wrapper_attributes,\n\t\tdo_shortcode( $shortcode_string )\n\t);\n}\n\n\/**\n * Register the block type on the server\n *\/\nadd_action( 'init', function() {\n\tregister_block_type( 'tutorial\/alert-wrapper', array(\n\t\t'api_version'     =&gt; 3,\n\t\t'title'           =&gt; 'Alert (Shortcode wrapper)',\n\t\t'icon'            =&gt; 'feedback',\n\t\t'category'        =&gt; 'widgets',\n\t\t'render_callback' =&gt; 'render_shortcode_alert_wrapper_block',\n\t\t\n\t\t'attributes'      =&gt; array(\n\t\t\t'alertType' =&gt; array(\n\t\t\t\t'type'    =&gt; 'string',\n\t\t\t\t'enum'    =&gt; array( 'info', 'warning', 'error' ),\n\t\t\t\t'default' =&gt; 'info',\n\t\t\t),\n\t\t\t'alertMessage' =&gt; array(\n\t\t\t\t'type'    =&gt; 'string',\n\t\t\t\t'default' =&gt; 'Type your alert message here...',\n\t\t\t),\n\t\t),\n\n\t\t'supports'        =&gt; array(\n\t\t\t'auto_register' =&gt; true,\n\t\t\t'spacing'       =&gt; array( 'margin' =&gt; true, 'padding' =&gt; true ),\n\t\t\t'typography'    =&gt; array( 'fontSize' =&gt; true ),\n\t\t),\n\t) );\n});<\/code><\/pre>\n<p>El c\u00f3digo anterior es similar al de la secci\u00f3n anterior. Lo que cambia aqu\u00ed es el callback de renderizado.<\/p>\n<ul>\n<li><code>$shortcode_string<\/code> almacena la cadena del shortcode (<code>[sc_alert type=\"%s\" message=\"%s\"]<\/code>).<\/li>\n<li>La funci\u00f3n devuelve el HTML del bloque contenedor y el shortcode incluido (<code class=\"language-php\">do_shortcode( $shortcode_string )<\/code>).<\/li>\n<\/ul>\n<p>Ahora, abre el insertador de bloques y busca el bloque \u00abShortcode wrapper\u00bb entre los widgets. Ins\u00e9rtalo en tu contenido y config\u00faralo desde la barra de ajustes del bloque. El bloque aparecer\u00e1 id\u00e9ntico tanto en el editor como en el frontend.<\/p>\n<figure id=\"attachment_206135\" aria-describedby=\"caption-attachment-206135\" style=\"width: 2298px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-206135 size-full\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2026\/02\/php-only-shortcode-example.png\" alt=\"Ejemplo de un shortcode envuelto en un bloque s\u00f3lo PHP\" width=\"2298\" height=\"912\"><figcaption id=\"caption-attachment-206135\" class=\"wp-caption-text\">Ejemplo de un shortcode envuelto en un bloque s\u00f3lo PHP<\/figcaption><\/figure>\n<h2>\u00bfC\u00f3mo est\u00e1 cambiando el desarrollo de WordPress con los bloques s\u00f3lo PHP?<\/h2>\n<p>Tal y como est\u00e1n las cosas, los bloques de PHP puro se encuentran en fase experimental y a\u00fan tienen capacidades limitadas. Gutenberg ofrece funcionalidades m\u00e1s potentes, como <a href=\"https:\/\/kinsta.com\/es\/blog\/patrones-de-bloques-wordpress\/\">patrones de bloques<\/a> y <a href=\"https:\/\/kinsta.com\/es\/blog\/variaciones-de-bloque-con-estilos-gutenberg\/\">variaciones de bloques<\/a>, que proporcionan todas las funcionalidades de edici\u00f3n de los bloques nativos de Gutenberg y de los bloques personalizados creados en JavaScript. Sin embargo, hay situaciones en las que los bloques de PHP ofrecen oportunidades importantes.<\/p>\n<p>En primer lugar, los bloques exclusivos para PHP deber\u00edan fomentar una mayor adopci\u00f3n del editor de bloques, sobre todo entre los desarrolladores de WordPress menos familiarizados con el desarrollo de JavaScript del lado del servidor.<\/p>\n<p>Adem\u00e1s, son envoltorios ideales para funciones personalizadas y shortcodes, como se muestra en el ejemplo de este art\u00edculo. Por otra parte, permiten una f\u00e1cil integraci\u00f3n con servicios externos.<\/p>\n<p>Y tambi\u00e9n podemos esperar, de forma razonable, mejoras futuras y nuevas funcionalidades, m\u00e1s opciones de configuraci\u00f3n e integraciones con las herramientas de Gutenberg ya existentes.<\/p>\n<p>Una cosa est\u00e1 clara: con los bloques solo para PHP, crear bloques de Gutenberg se ha vuelto mucho m\u00e1s f\u00e1cil.<\/p>\n<p>Si el desarrollo de WordPress es tu trabajo, Kinsta te proporciona las <a href=\"https:\/\/kinsta.com\/es\/blog\/stack-tecnologico-para-agencias-wordpress\/\">herramientas para desarrolladores que necesitas<\/a>, permiti\u00e9ndote centrarte en el desarrollo de WordPress, eliminando la necesidad de complejas configuraciones y tediosas tareas de mantenimiento: <a href=\"https:\/\/kinsta.com\/es\/blog\/desarrollo-remoto-de-wordpress-en-kinsta-con-ssh\/\">SSH<\/a>, <a href=\"https:\/\/kinsta.com\/es\/blog\/funcionalidades-sftp-ssh\/\">SFTP<\/a>, <a href=\"https:\/\/kinsta.com\/es\/blog\/como-configurar-pipeline-ci-cd\/\">integraci\u00f3n Git<\/a>, <a href=\"https:\/\/kinsta.com\/es\/blog\/actualizaciones-automaticas-de-kinsta\/\">actualizaciones autom\u00e1ticas<\/a>, <a href=\"https:\/\/kinsta.com\/es\/wordpress-hosting\/staging\/\">staging con un solo clic<\/a>, una <a href=\"https:\/\/kinsta.com\/es\/devkinsta\/caracteristicas\/\">herramienta de desarrollo local<\/a> integrada y mucho m\u00e1s. Pru\u00e9balo de primera mano con <a href=\"https:\/\/kinsta.com\/es\/primer-mes-gratis\/\">tu primer mes gratis<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Durante a\u00f1os, para dominar el desarrollo de bloques en Gutenberg era necesario tener un conocimiento profundo de tecnolog\u00edas como React y Node.js, adem\u00e1s de seguir pasos &#8230;<\/p>\n","protected":false},"author":36,"featured_media":82634,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[],"topic":[1345,1316],"class_list":["post-82633","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","topic-desarrollo-wordpress","topic-funcion-php"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v24.6 (Yoast SEO v24.6) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>C\u00f3mo crear bloques de Gutenberg solo con PHP<\/title>\n<meta name=\"description\" content=\"Domina los bloques Gutenberg con PHP puro. Olvida JS y React para crear y desplegar bloques en pocos minutos.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"C\u00f3mo construir bloques Gutenberg s\u00f3lo en PHP\" \/>\n<meta property=\"og:description\" content=\"Domina los bloques Gutenberg con PHP puro. Olvida JS y React para crear y desplegar bloques en pocos minutos.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/kinsta.es\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-04-06T07:29:08+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-07T07:29:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1470\" \/>\n\t<meta property=\"og:image:height\" content=\"735\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Carlo Daniele\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:description\" content=\"Domina los bloques Gutenberg con PHP puro. Olvida JS y React para crear y desplegar bloques en pocos minutos.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png\" \/>\n<meta name=\"twitter:creator\" content=\"@carlodaniele\" \/>\n<meta name=\"twitter:site\" content=\"@Kinsta_ES\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Carlo Daniele\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/\"},\"author\":{\"name\":\"Carlo Daniele\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/person\/962dde02ea6f5df089b5d8d0853bbc63\"},\"headline\":\"C\u00f3mo construir bloques Gutenberg s\u00f3lo en PHP\",\"datePublished\":\"2026-04-06T07:29:08+00:00\",\"dateModified\":\"2026-04-07T07:29:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/\"},\"wordCount\":2564,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/es\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png\",\"inLanguage\":\"es\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/\",\"url\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/\",\"name\":\"C\u00f3mo crear bloques de Gutenberg solo con PHP\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/es\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png\",\"datePublished\":\"2026-04-06T07:29:08+00:00\",\"dateModified\":\"2026-04-07T07:29:54+00:00\",\"description\":\"Domina los bloques Gutenberg con PHP puro. Olvida JS y React para crear y desplegar bloques en pocos minutos.\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png\",\"contentUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png\",\"width\":1470,\"height\":735},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/es\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Desarrollo WordPress\",\"item\":\"https:\/\/kinsta.com\/es\/secciones\/desarrollo-wordpress\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"C\u00f3mo construir bloques Gutenberg s\u00f3lo en PHP\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/es\/#website\",\"url\":\"https:\/\/kinsta.com\/es\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Soluciones de alojamiento premium, r\u00e1pidas y seguras\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/es\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/es\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/es\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/es\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/kinsta.es\/\",\"https:\/\/x.com\/Kinsta_ES\",\"https:\/\/www.instagram.com\/kinstahosting\/\",\"https:\/\/www.linkedin.com\/company\/kinsta\/\",\"https:\/\/www.pinterest.com\/kinstahosting\/\",\"https:\/\/www.youtube.com\/c\/Kinsta\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/person\/962dde02ea6f5df089b5d8d0853bbc63\",\"name\":\"Carlo Daniele\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/429e5568f88110fd9a409b84cb22197e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/429e5568f88110fd9a409b84cb22197e?s=96&d=mm&r=g\",\"caption\":\"Carlo Daniele\"},\"description\":\"Carlo is a passionate lover of webdesign and front-end development. He has been playing with WordPress for more than 20 years, also in collaboration with Italian and European universities and educational institutions. He has written hundreds of articles and guides about WordPress, published both on Italian and international websites, as well as on printed magazines. You can find him on LinkedIn.\",\"sameAs\":[\"https:\/\/frammentidicodice.com\/\",\"https:\/\/x.com\/carlodaniele\"],\"url\":\"https:\/\/kinsta.com\/es\/blog\/author\/carlodaniele\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"C\u00f3mo crear bloques de Gutenberg solo con PHP","description":"Domina los bloques Gutenberg con PHP puro. Olvida JS y React para crear y desplegar bloques en pocos minutos.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/","og_locale":"es_ES","og_type":"article","og_title":"C\u00f3mo construir bloques Gutenberg s\u00f3lo en PHP","og_description":"Domina los bloques Gutenberg con PHP puro. Olvida JS y React para crear y desplegar bloques en pocos minutos.","og_url":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/kinsta.es\/","article_published_time":"2026-04-06T07:29:08+00:00","article_modified_time":"2026-04-07T07:29:54+00:00","og_image":[{"width":1470,"height":735,"url":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png","type":"image\/png"}],"author":"Carlo Daniele","twitter_card":"summary_large_image","twitter_description":"Domina los bloques Gutenberg con PHP puro. Olvida JS y React para crear y desplegar bloques en pocos minutos.","twitter_image":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png","twitter_creator":"@carlodaniele","twitter_site":"@Kinsta_ES","twitter_misc":{"Escrito por":"Carlo Daniele","Tiempo de lectura":"20 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/"},"author":{"name":"Carlo Daniele","@id":"https:\/\/kinsta.com\/es\/#\/schema\/person\/962dde02ea6f5df089b5d8d0853bbc63"},"headline":"C\u00f3mo construir bloques Gutenberg s\u00f3lo en PHP","datePublished":"2026-04-06T07:29:08+00:00","dateModified":"2026-04-07T07:29:54+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/"},"wordCount":2564,"publisher":{"@id":"https:\/\/kinsta.com\/es\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png","inLanguage":"es"},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/","url":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/","name":"C\u00f3mo crear bloques de Gutenberg solo con PHP","isPartOf":{"@id":"https:\/\/kinsta.com\/es\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png","datePublished":"2026-04-06T07:29:08+00:00","dateModified":"2026-04-07T07:29:54+00:00","description":"Domina los bloques Gutenberg con PHP puro. Olvida JS y React para crear y desplegar bloques en pocos minutos.","breadcrumb":{"@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#primaryimage","url":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png","contentUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2026\/03\/how-to-build-php-only-gutenberg-blocks.png","width":1470,"height":735},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/es\/blog\/bloques-gutenberg-solo-php\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/es\/"},{"@type":"ListItem","position":2,"name":"Desarrollo WordPress","item":"https:\/\/kinsta.com\/es\/secciones\/desarrollo-wordpress\/"},{"@type":"ListItem","position":3,"name":"C\u00f3mo construir bloques Gutenberg s\u00f3lo en PHP"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/es\/#website","url":"https:\/\/kinsta.com\/es\/","name":"Kinsta\u00ae","description":"Soluciones de alojamiento premium, r\u00e1pidas y seguras","publisher":{"@id":"https:\/\/kinsta.com\/es\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/es\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/es\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/es\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/kinsta.es\/","https:\/\/x.com\/Kinsta_ES","https:\/\/www.instagram.com\/kinstahosting\/","https:\/\/www.linkedin.com\/company\/kinsta\/","https:\/\/www.pinterest.com\/kinstahosting\/","https:\/\/www.youtube.com\/c\/Kinsta"]},{"@type":"Person","@id":"https:\/\/kinsta.com\/es\/#\/schema\/person\/962dde02ea6f5df089b5d8d0853bbc63","name":"Carlo Daniele","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/kinsta.com\/es\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/429e5568f88110fd9a409b84cb22197e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/429e5568f88110fd9a409b84cb22197e?s=96&d=mm&r=g","caption":"Carlo Daniele"},"description":"Carlo is a passionate lover of webdesign and front-end development. He has been playing with WordPress for more than 20 years, also in collaboration with Italian and European universities and educational institutions. He has written hundreds of articles and guides about WordPress, published both on Italian and international websites, as well as on printed magazines. You can find him on LinkedIn.","sameAs":["https:\/\/frammentidicodice.com\/","https:\/\/x.com\/carlodaniele"],"url":"https:\/\/kinsta.com\/es\/blog\/author\/carlodaniele\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts\/82633","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/users\/36"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/comments?post=82633"}],"version-history":[{"count":10,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts\/82633\/revisions"}],"predecessor-version":[{"id":82682,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts\/82633\/revisions\/82682"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/82633\/translations\/en"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/82633\/translations\/it"},{"embeddable":true,"hreflang":"ja","title":"Japanese","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/82633\/translations\/jp"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/82633\/translations\/fr"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/82633\/translations\/de"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/82633\/translations\/es"},{"embeddable":true,"hreflang":"nl","title":"Dutch","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/82633\/translations\/nl"},{"href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/82633\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/media\/82634"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/media?parent=82633"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/tags?post=82633"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/topic?post=82633"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}