可以使用纯PHP创建带有区块的WordPress插件吗?

huangapple go评论65阅读模式
英文:

Is it possible to create a WordPress plugin with blocks in pure PHP?

问题

// dp_extensions-blocks.php 

include('dp_extensions-functions.php');

// Register a block to display the current time in any timezone

// Render the block
function dp_extensions__block_render__current_time($attributes) {
    $time = dp_extensions__functions__get_current_time($attributes);
    $html = '<p>' . $attributes['message_before'] . $time . $attributes['message_after'] . '</p>';
    return $html;
}

// Render the block in the block editor
function dp_extensions__block_edit__current_time($attributes) {
    $html = '<div class="dp-extensions-block-current-time">';
    $html .= '<label for="timezone">' . __('Timezone', 'dp_extensions') . ':</label>';
    $html .= '<input type="text" id="timezone" value="' . $attributes['timezone'] . '" onBlur="{ (value) => setAttributes({ timezone: value }) }" /><br />';
    $html .= '<label for="format">' . __('Format', 'dp_extensions') . ':</label>';
    $html .= '<input type="text" id="format" value="' . $attributes['format'] . '" onBlur="{ (value) => setAttributes({ format: value }) }" /><br />';
    $html .= '<label for="message_before">' . __('Message before', 'dp_extensions') . ':</label>';
    $html .= '<input type="text" id="message_before" value="' . $attributes['message_before'] . '" onBlur="{ (value) => setAttributes({ message_before: value }) }" /><br />';
    $html .= '<label for="message_after">' . __('Message after', 'dp_extensions') . ':</label>';
    $html .= '<input type="text" id="message_after" value="' . $attributes['message_after'] . '" onBlur="{ (value) => setAttributes({ message_after: value }) }" />';
    $html .= '</div>';
    return $html;
}

// Register the block
function dp_extensions__blocks__current_time() {
    $block = register_block_type('dp-extensions/dp-current-time', array(
        'title' => __('DP Current Time', 'dp_extensions'),
        'description' => __('Show the current time in any available timezone, in your favorite format', 'dp_extensions'),
        'category' => 'widgets',
        'attributes' => array(
            'timezone' => array(
                'type' => 'string',
                'default' => 'Europe/Madrid'
            ),
            'format' => array(
                'type' => 'string',
                'default' => get_option('time_format')
            ),
            'message_before' => array(
                'type' => 'string',
                'default' => ''
            ),
            'message_after' => array(
                'type' => 'string',
                'default' => ''
            )
        ),
        'styles' => array(
            array(
                'name' => 'dp-extensions-grapes-style',
                'label' => __('Grapes', 'dp_extensions'),
                'style' => plugin_dir_url(__FILE__ . 'css/style-grapes.css'),
                'isDefault' => true
            ),
            array(
                'name' => 'dp-extensions-cherry-style',
                'label' => __('Cherry', 'dp_extensions'),
                'style' => plugin_dir_url(__FILE__ . 'css/style-cherry.css'),
            ),
            array(
                'name' => 'dp-extensions-pineapple-style',
                'label' => __('Pineapple', 'dp_extensions'),
                'style' => plugin_dir_url(__FILE__ . 'css/style-pineapple.css'),
            ),
            array(
                'name' => 'dp-extensions-mandarine-style',
                'label' => __('Mandarine', 'dp_extensions'),
                'style' => plugin_dir_url(__FILE__ . 'css/style-mandarine.css'),
            ),
            array(
                'name' => 'dp-extensions-plum-style',
                'label' => __('Plum', 'dp_extensions'),
                'style' => plugin_dir_url(__FILE__ . 'css/style-plum.css'),
            )
        ),
        'example' => array(
            'attributes' => array(
                'timezone' => 'Europe/Madrid',
                'format' => 'G:i',
                'message_before' => 'In Madrid, right now it is ',
                'message_after' => ', perfect time for reading!'
            )
        ),
        'render_callback' => 'dp_extensions__block_render__current_time',
        'supports' => array(
            'align' => true,
            'anchor' => true,
            'customClassName' => true,
            'html' => true,
            'inserter' => true,
            'multiple' => true,
            'reusable' => true,
            'color' => array(
                'background' => true,
                'gradient' => true,
                'text' => true,
            ),
            'styles' => true,
            'typography' => true,
        ),
        'edit_callback' => 'dp_extensions__block_edit__current_time'
    ));
}

add_action('init', 'dp_extensions__blocks__current_time');

// Register a block to output challenge progress

// Render the block
function dp_extensions__block_render__challenge_progress($attributes) {
    $current_value = $attributes['current_value'];
    $max_value = $attributes['max_value'];
    $html = '<div style="width: 100%;" class="dp-extensions-block-challenge-progress">';
    $html .= '<span class="custom_cell__label">';
    $html .= '<label for="progress">' . __('My progress', 'dp_extensions') . ': </label>';
    $html .= '</span>';
    $html .= '<span class="custom_cell__content">';
    $html .= '<progress id="progress" value="' . $current_value . '" max="' . $max_value . '" title="' . $current_value . ' / ' . $max_value . '">' . $current_value . ' / ' . $max_value . '</progress>';
    $html .= '</span>';
    $html .= '</div>';
    return $html;
}

// Render the block in the block editor
function dp_extensions__block_edit__challenge_progress($attributes) {
    $html = '<div class="dp-extensions-block-challenge-progress">';
    $html .= '<label for="current_value">' . __('Current value', 'dp_extensions') . ':</label>';
    $html .= '<input type="text" id="current_value" value="' . $attributes['current_value'] . '" onBlur={ (value) => setAttributes({ current_value: value }) } />';
    $html .= '<label for="max_value">' . __('Maximal value', 'dp_extensions') . ':</label>';
    $html .= '<input type="text" id="max_value" value="' . $attributes['max_value'] . '" onBlur={ (value) => setAttributes({ max_value: value }) } />';
    $html .= '</div>';
    return $html;
}

// Register the block
function dp_extensions__blocks__challenge_progress() {
    register_block_type('dp-extensions/dp-challenge-progress', array(
        'attributes' => array(
            'current

<details>
<summary>英文:</summary>

I am trying to create a WordPress plugin which will include blocks for some small improvements I need on my blog. I&#39;m not really used to the JSX / React syntax, even less to node.js, so I&#39;m trying to do it writing exclusively PHP. 

Please look at my code below, and tell me if I&#39;m missing something out, since the plugin activates, but the blocks don&#39;t appear in the editor. 


```php
// dp_extensions-blocks.php 

include(&#39;dp_extensions-functions.php&#39;);


// Register a block to display the current time in any timezone

// Render the block
function dp_extensions__block_render__current_time($attributes) {
	$time = dp_extensions__functions__get_current_time($attributes);
	$html = &#39;&lt;p&gt;&#39; . $attributes[&#39;message_before&#39;] . $time . $attributes[&#39;message_after&#39;] . &#39;&lt;/p&gt;&#39;;
	return $html;
}

// Render the block in the block editor
function dp_extensions__block_edit__current_time($attributes) {
	$html = &#39;&lt;div class=&quot;dp-extensions-block-current-time&quot;&gt;&#39;;
	$html .= &#39;&lt;label for=&quot;timezone&quot;&gt;&#39; . __(&#39;Timezone&#39;, &#39;dp_extensions&#39;) . &#39;:&lt;/label&gt;&#39;;
	$html .= &#39;&lt;input type=&quot;text&quot; id=&quot;timezone&quot; value=&quot;&#39; . $attributes[&#39;timezone&#39;] . &#39;&quot; onBlur=&quot;{ (value) =&gt; setAttributes({ timezone: value }) }&quot; /&gt;&lt;br /&gt;&#39;;
	$html .= &#39;&lt;label for=&quot;format&quot;&gt;&#39; . __(&#39;Format&#39;, &#39;dp_extensions&#39;) . &#39;:&lt;/label&gt;&#39;;
	$html .= &#39;&lt;input type=&quot;text&quot; id=&quot;format&quot; value=&quot;&#39; . $attributes[&#39;format&#39;] . &#39;&quot; onBlur=&quot;{ (value) =&gt; setAttributes({ format: value }) }&quot; /&gt;&lt;br /&gt;&#39;;
	$html .= &#39;&lt;label for=&quot;message_before&quot;&gt;&#39; . __(&#39;Message before&#39;, &#39;dp_extensions&#39;) . &#39;:&lt;/label&gt;&#39;;
	$html .= &#39;&lt;input type=&quot;text&quot; id=&quot;message_before&quot; value=&quot;&#39; . $attributes[&#39;message_before&#39;] . &#39;&quot; onBlur=&quot;{ (value) =&gt; setAttributes({ message_before: value }) }&quot; /&gt;&lt;br /&gt;&#39;;
	$html .= &#39;&lt;label for=&quot;message_after&quot;&gt;&#39; . __(&#39;Message after&#39;, &#39;dp_extensions&#39;) . &#39;:&lt;/label&gt;&#39;;
	$html .= &#39;&lt;input type=&quot;text&quot; id=&quot;message_after&quot; value=&quot;&#39; . $attributes[&#39;message_after&#39;] . &#39;&quot; onBlur=&quot;{ (value) =&gt; setAttributes({ message_after: value }) }&quot; /&gt;&#39;;
	$html .= &#39;&lt;/div&gt;&#39;;
	return $html;
}

// Register the block
function dp_extensions__blocks__current_time() {
	$block = register_block_type(&#39;dp-extensions/dp-current-time&#39;, array(
		&#39;title&#39; =&gt; __(&#39;DP Current Time&#39;, &#39;dp_extensions&#39;),
		&#39;description&#39; =&gt; __(&#39;Show the current time in any available timezone, in your favorite format&#39;, &#39;dp_extensions&#39;),
		&#39;category&#39; =&gt; &#39;widgets&#39;,
		&#39;attributes&#39; =&gt; array(
			&#39;timezone&#39; =&gt; array(
				&#39;type&#39; =&gt; &#39;string&#39;,
				&#39;default&#39; =&gt; &#39;Europe/Madrid&#39;
			),
			&#39;format&#39; =&gt; array(
				&#39;type&#39; =&gt; &#39;string&#39;,
				&#39;default&#39; =&gt; get_option(&#39;time_format&#39;)
			),
			&#39;message_before&#39; =&gt; array(
				&#39;type&#39; =&gt; &#39;string&#39;,
				&#39;default&#39; =&gt; &#39;&#39;
			),
			&#39;message_after&#39; =&gt; array(
				&#39;type&#39; =&gt; &#39;string&#39;,
				&#39;default&#39; =&gt; &#39;&#39;
			)
		),
		&#39;styles&#39; =&gt; array(
			array(
				&#39;name&#39; =&gt; &#39;dp-extensions-grapes-style&#39;,
				&#39;label&#39; =&gt; __(&#39;Grapes&#39;, &#39;dp_extensions&#39;),
				&#39;style&#39; =&gt; plugin_dir_url(__FILE__ . &#39;css/style-grapes.css&#39;),
				&#39;isDefault&#39; =&gt; true
			),
			array(
				&#39;name&#39; =&gt; &#39;dp-extensions-cherry-style&#39;,
				&#39;label&#39; =&gt; __(&#39;Cherry&#39;, &#39;dp_extensions&#39;),
				&#39;style&#39; =&gt; plugin_dir_url(__FILE__ . &#39;css/style-cherry.css&#39;),
			),
			array(
				&#39;name&#39; =&gt; &#39;dp-extensions-pineapple-style&#39;,
				&#39;label&#39; =&gt; __(&#39;Pineapple&#39;, &#39;dp_extensions&#39;),
				&#39;style&#39; =&gt; plugin_dir_url(__FILE__ . &#39;css/style-pineapple.css&#39;),
			),
			array(
				&#39;name&#39; =&gt; &#39;dp-extensions-mandarine-style&#39;,
				&#39;label&#39; =&gt; __(&#39;Mandarine&#39;, &#39;dp_extensions&#39;),
				&#39;style&#39; =&gt; plugin_dir_url(__FILE__ . &#39;css/style-mandarine.css&#39;),
			),
			array(
				&#39;name&#39; =&gt; &#39;dp-extensions-plum-style&#39;,
				&#39;label&#39; =&gt; __(&#39;Plum&#39;, &#39;dp_extensions&#39;),
				&#39;style&#39; =&gt; plugin_dir_url(__FILE__ . &#39;css/style-plum.css&#39;),
			)
		),
		&#39;example&#39; =&gt; array(
			&#39;attributes&#39; =&gt; array(
				&#39;timezone&#39; =&gt; &#39;Europe/Madrid&#39;,
				&#39;format&#39; =&gt; &#39;G:i&#39;,
				&#39;message_before&#39; =&gt; &#39;In Madrid, right now it is &#39;,
				&#39;message_after&#39; =&gt; &#39;, perfect time for reading!&#39;
			)
		),
		&#39;render_callback&#39; =&gt; &#39;dp_extensions__block_render__current_time&#39;,
		&#39;supports&#39; =&gt; array(
			&#39;align&#39; =&gt; true,
			&#39;anchor&#39; =&gt; true,
			&#39;customClassName&#39; =&gt; true,
			&#39;html&#39; =&gt; true,
			&#39;inserter&#39; =&gt; true,
			&#39;multiple&#39; =&gt; true,
			&#39;reusable&#39; =&gt; true,
			&#39;color&#39; =&gt; array(
				&#39;background&#39; =&gt; true,
				&#39;gradient&#39; =&gt; true,
				&#39;text&#39; =&gt; true,
			),
			&#39;styles&#39; =&gt; true,
			&#39;typography&#39; =&gt; true,
		),
		&#39;edit_callback&#39; =&gt; &#39;dp_extensions__block_edit__current_time&#39;
	));
}

add_action(&#39;init&#39;, &#39;dp_extensions__blocks__current_time&#39;);


// Register a block to output challenge progress

// Render the block
function dp_extensions__block_render__challenge_progress($attributes) {
	$current_value = $attributes[&#39;current_value&#39;];
	$max_value = $attributes[&#39;max_value&#39;];
	$html = &#39;&lt;div style=&quot;width: 100%;&quot; class=&quot;dp-extensions-block-challenge-progress&quot;&gt;&#39;;
	$html .= &#39;&lt;span class=&quot;custom_cell__label&quot;&gt;&#39;;
	$html .= &#39;&lt;label for=&quot;progress&quot;&gt;&#39; . __(&#39;My progress&#39;, &#39;dp_extensions&#39;) . &#39;: &lt;/label&gt;&#39;;
	$html .= &#39;&lt;/span&gt;&#39;;
	$html .= &#39;&lt;span class=&quot;custom_cell__content&quot;&gt;&#39;;
	$html .= &#39;&lt;progress id=&quot;progress&quot; value=&quot;&#39; . $current_value . &#39;&quot; max=&quot;&#39; . $max_value . &#39;&quot; title=&quot;&#39; . $current_value . &#39; / &#39; . $max_value . &#39;&quot;&gt;&#39; . $current_value . &#39; / &#39; . $max_value . &#39;&lt;/progress&gt;&#39;;
	$html .= &#39;&lt;/span&gt;&#39;;
	$html .= &#39;&lt;/div&gt;&#39;;
	return $html;
}

// Render the block in the block editor
function dp_extensions__block_edit__challenge_progress($attributes) {
	$html = &#39;&lt;div class=&quot;dp-extensions-block-challenge-progress&quot;&gt;&#39;;
	$html .= &#39;&lt;label for=&quot;current_value&quot;&gt;&#39; . __(&#39;Current value&#39;, &#39;dp_extensions&#39;) . &#39;:&lt;/label&gt;&#39;;
	$html .= &#39;&lt;input type=&quot;text&quot; id=&quot;current_value&quot; value=&quot;&#39; . $attributes[&#39;current_value&#39;] . &#39;&quot; onBlur={ (value) =&gt; setAttributes({ current_value: value }) } /&gt;&#39;;
	$html .= &#39;&lt;label for=&quot;max_value&quot;&gt;&#39; . __(&#39;Maximal value&#39;, &#39;dp_extensions&#39;) . &#39;:&lt;/label&gt;&#39;;
	$html .= &#39;&lt;input type=&quot;text&quot; id=&quot;max_value&quot; value=&quot;&#39; . $attributes[&#39;max_value&#39;] . &#39;&quot; onBlur={ (value) =&gt; setAttributes({ max_value: value }) } /&gt;&#39;;
	$html .= &#39;&lt;/div&gt;&#39;;
	return $html;
}

// Register the block
function dp_extensions__blocks__challenge_progress() {
	register_block_type(&#39;dp-extensions/dp-challenge-progress&#39;, array(
		&#39;attributes&#39; =&gt; array(
			&#39;current_value&#39; =&gt; array(
				&#39;type&#39; =&gt; &#39;string&#39;,
				&#39;default&#39; =&gt; &#39;0&#39;
			),
			&#39;max_value&#39; =&gt; array(
				&#39;type&#39; =&gt; &#39;string&#39;,
				&#39;default&#39; =&gt; &#39;30&#39;
			)
		),
		&#39;render_callback&#39; =&gt; &#39;dp_extensions__block_render__challenge_progress&#39;,
		&#39;supports&#39; =&gt; array(
			&#39;align&#39; =&gt; true,
			&#39;anchor&#39; =&gt; true,
			&#39;customClassName&#39; =&gt; true,
			&#39;html&#39; =&gt; true,
			&#39;inserter&#39; =&gt; true,
			&#39;multiple&#39; =&gt; true,
			&#39;reusable&#39; =&gt; true,
			&#39;styles&#39; =&gt; true,
			&#39;typography&#39; =&gt; true,
			&#39;color&#39; =&gt; array(
				&#39;background&#39; =&gt; true,
				&#39;gradient&#39; =&gt; true,
				&#39;text&#39; =&gt; true,
			),
		),
		&#39;edit_callback&#39; =&gt; &#39;dp_extensions__block_edit__challenge_progress&#39;
	));
}

add_action(&#39;init&#39;, &#39;dp_extensions__blocks__challenge_progress&#39;);
// dp_extensions-functions.php 

// A function to get the current time in any timezone

function dp_extensions__functions__get_current_time($attributes) {
	date_default_timezone_set($attributes[&#39;timezone&#39;]);
	if ($attributes[&#39;format&#39;] == &#39;&#39;) {
		$time = date(get_option(&#39;time_format&#39;));
	}
	else {
		$time = date($attributes[&#39;format&#39;]);
	}
	return $time;
}
// dp_extensions.php 

/*
 * Plugin Name: DP extensions
 * Plugin URI: &lt;plugin URL here&gt;
 * Description: A plugin to add different small enhancements (custom types, blocks, shortcodes...)
 * Version: 1.0
 * Author: Danijela Popović
 * Author URI: &lt;domain here&gt;
 * Text domain: dp_extensions
 * License: GPLv2
*/


// Load the plugin text domain

function dp_extensions__load_textdomain() {
	load_plugin_textdomain(&#39;dp_extensions&#39;, false, dirname(plugin_basename(__FILE__)) . &#39;/languages/&#39;);
}

add_action(&#39;plugins_loaded&#39;, &#39;dp_extensions__load_textdomain&#39;);


// Include other plugin files

include(&#39;dp_extensions-blocks.php&#39;);

Also, is there a way to detect the currently selected style for the block and other block attributes? The get_block_attributes() function doesn't seem to be available, not even when I try to use it in the function which is set as the edit callback function.

答案1

得分: 1

Short answer: No..

I appreciate you've put quite a bit of effort into trying to get this to work, and this probably isn't the answer you were hoping for..

While blocks can be registered with PHP and dynamic blocks use a PHP function for the render_callback, there is no edit_callback in register_block_type(). The edit() function is expected to be JavaScript, to render the UI for the Editor; this is why your block does not appear in the Editor even though your block registers without error.

The transition to Gutenberg blocks with JSX seems hard, given that most WordPress developers are strong PHP developers. I really recommend you give it a try using the @wordpress/create-block tool; this will get you started quickly and give you a solid base to build out your own plugin with all the files needed created for you.

If you need to have PHP render the frontend, it's still possible by creating a dynamic block by using:

npx @wordpress/create-block dp-current-time --variant dynamic

This will create a render.php file where you would put the content of your dp_extensions__block_render__current_time($attributes) function.

In the edit.js, you can use ServerSideRender to render the PHP within the Editor and add your own InspectorControls to set the timezone, format, message_before and message_after attributes. Hope this helps you feel confident to take the plunge and give @wordpress/create-block a go - it will enable you to generate blocks so much easier/faster in the future..

英文:

Short answer: No..

I appreciate you've put quite a bit of effort into trying to get this to work, and this probably isn't the answer you were hoping for..

While blocks can be registered with PHP and dynamic blocks use a PHP function for the render_callback, there is no edit_callback in register_block_type(). The edit() function is expected to be JavaScript, to render the UI for the Editor; this is why your block does not appear in the Editor even though your block registers without error.

The transition to Gutenberg blocks with JSX seems hard, given that most WordPress developers are strong PHP developers. I really recommend you give it a try using the @wordpress/create-block tool; this will get you started quickly and give you a solid base to build out your own plugin with all the files needed created for you.

If you need to have PHP render the frontend, it's still possible by creating a dynamic block by using:

npx @wordpress/create-block dp-current-time --variant dynamic

This will create a render.php file where you would put the content of your dp_extensions__block_render__current_time($attributes) function.

In the edit.js, you can use ServerSideRender to render the PHP within the Editor and add your own InspectorControls to set the timezone, format, message_before and message_after attributes. Hope this helps you feel confident to take the plunge and give @wordpress/create-block a go - it will enable you to generate blocks so much easier/faster in the future..

huangapple
  • 本文由 发表于 2023年3月7日 04:41:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75655622.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定