我创建了一个简单的php抽象小部件类,它可以用数组中的字段生成表单。当我尝试保存字段时,所有更改都将被删除。
抽象小部件类:
<?php
/**
* Abstract widget class
*
* @class MOD_Widget
*/
// Exit if accessed directly.
if ( ! defined( \'ABSPATH\' ) ) {
exit;
}
/**
* MOD_Widget
*
* @version 1.0.0
* @extends WP_Widget
*/
abstract class MOD_Widget extends WP_Widget {
/**
* CSS class.
*
* @var string
*/
public $widget_cssclass;
/**
* Widget description.
*
* @var string
*/
public $widget_description;
/**
* Widget ID.
*
* @var string
*/
public $widget_id;
/**
* Widget name.
*
* @var string
*/
public $widget_name;
/**
* Fields.
*
* @var array
*/
public $fields;
/**
* Constructor.
*/
public function __construct() {
$widget_ops = array(
\'classname\' => $this->widget_cssclass,
\'description\' => $this->widget_description,
\'customize_selective_refresh\' => true,
);
parent::__construct( $this->widget_id, $this->widget_name, $widget_ops );
}
public function save_fields( $new_instance, $old_instance, $parent_container = null ) {
// Vars
$instance = $old_instance;
$widget_fields = $this->fields;
if( isset( $parent_container ) ){
$widget_fields = $widget_fields[ $parent_container ][\'sub_fields\'];
}
// Loop fields and get values to save.
foreach ( $widget_fields as $key => $setting ) {
$setting_type = isset( $setting[\'type\'] ) ? $setting[\'type\'] : \'\';
// Format the value based on fields type.
switch ( $setting_type ) {
case \'group\':
$group_instance = $this->save_fields( $new_instance, $old_instance, $key );
$instance = array_merge( $group_instance, $instance );
break;
case \'number\':
$instance[ $key ] = (int) $new_instance[ $key ];
if ( isset( $setting[\'min\'] ) && \'\' !== $setting[\'min\'] ) {
$instance[ $key ] = max( $instance[ $key ], $setting[\'min\'] );
}
if ( isset( $setting[\'max\'] ) && \'\' !== $setting[\'max\'] ) {
$instance[ $key ] = min( $instance[ $key ], $setting[\'max\'] );
}
break;
case \'text\':
$instance[ $key ] = isset( $new_instance[ $key ] ) ? sanitize_text_field( $new_instance[ $key ] ) : ( isset( $setting[\'default_value\'] ) ? $setting[\'default_value\'] : \'\' );
break;
case \'textarea\':
$instance[ $key ] = wp_kses_post( $new_instance[ $key ] );
break;
case \'checkbox\':
$instance[ $key ] = empty( $new_instance[ $key ] ) ? 0 : 1;
break;
default:
$instance[ $key ] = isset( $new_instance[ $key ] ) ? sanitize_text_field( $new_instance[ $key ] ) : ( isset( $setting[\'default_value\'] ) ? $setting[\'default_value\'] : \'\' );
break;
}
}
return $instance;
}
/**
* Handles updating settings for the current widget instance.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
if ( empty( $this->fields ) ) {
return $instance;
}
$instance = $this->save_fields( $new_instance, $old_instance );
return $instance;
}
/**
* Back-end widget fields
*/
public function field_generator( $instance, $parent_container = null ) {
// Vars
$widget_fields = $this->fields;
if( isset( $parent_container ) ){
$widget_fields = $widget_fields[ $parent_container ][\'sub_fields\'];
}
foreach ( $widget_fields as $key => $setting ) {
$setting_type = isset( $setting[\'type\'] ) ? $setting[\'type\'] : \'\';
$input_css_classes = isset( $setting[\'class\'] ) ? $setting[\'class\'] : \'\';
if( !isset( $setting_type ) ){
return;
}
if( \'group\' !== $setting_type ){
$default_value = isset( $setting[\'default_value\'] ) ? $setting[\'default_value\'] : \'\';
$value = isset( $instance[ $key ] ) ? $instance[ $key ] : $default_value;
} else {
$value = \'\';
}
switch ( $setting_type ) {
case \'group\':
?>
<div id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" class="mod-widget-section<?php if ( ! empty( $input_css_classes ) ) echo \' \' . implode( \' \', $input_css_classes ); ?>">
<div class="section-header"><?php echo esc_html( $setting[\'label\'] ); ?></div>
<div class="section-content">
<?php
if ( !isset( $setting[\'sub_fields\'] ) || empty( $setting[\'sub_fields\'] ) ) {
echo \'<p>\' . esc_html( \'This section is empty.\', \'mod\' ) . \'</p></div></div></div>\';
return;
} ?>
<?php $this->field_generator( $instance, $key ); ?>
</div>
</div>
<?php
break;
case \'text\':
?>
<div class="mod-widget-option mod-option-type-<?php echo esc_attr( $setting[\'type\'] ); ?>">
<label for="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" class="mod-field-label"><?php echo esc_html( $setting[\'label\'] ); ?></label>
<input id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" type="text" class="widefat<?php if ( ! empty( $input_css_classes ) ) echo \' \' . implode( \' \', $input_css_classes ); ?>" name="<?php echo esc_attr( $this->get_field_name( $key ) ); ?>" value="<?php echo esc_attr( $value ); ?>" />
<?php if ( ! empty( $setting[\'desc\'] ) ) : ?>
<p class="small-desc"><?php echo esc_html( $setting[\'desc\'] ); ?></p>
<?php endif; ?>
</div>
<?php
break;
case \'textarea\':
?>
<div class="mod-widget-option mod-option-type-<?php echo esc_attr( $setting[\'type\'] ); ?>">
<label for="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" class="mod-field-label"><?php echo esc_html( $setting[\'label\'] ); ?></label>
<textarea id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" class="widefat<?php if ( ! empty( $input_css_classes ) ) echo \' \' . implode( \' \', $input_css_classes ); ?>" name="<?php echo esc_attr( $this->get_field_name( $key ) ); ?>" rows="4" cols="20"><?php echo esc_textarea( $value ); ?></textarea>
<?php if ( ! empty( $setting[\'desc\'] ) ) : ?>
<p class="small-desc"><?php echo esc_html( $setting[\'desc\'] ); ?></p>
<?php endif; ?>
</div>
<?php
break;
case \'number\':
?>
<div class="mod-widget-option mod-option-type-<?php echo esc_attr( $setting[\'type\'] ); ?>">
<label for="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" class="mod-field-label"><?php echo esc_html( $setting[\'label\'] ); ?></label>
<input id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" type="number" class="tiny-text<?php if ( ! empty( $input_css_classes ) ) echo \' \' . implode( \' \', $input_css_classes ); ?>" name="<?php echo esc_attr( $this->get_field_name( $key ) ); ?>" step="<?php echo esc_attr( $setting[\'step\'] ); ?>" min="<?php echo esc_attr( $setting[\'min\'] ); ?>" <?php if ( ! empty( $setting[\'max\'] ) ) : ?>max="<?php echo esc_attr( $setting[\'max\'] ); ?>"<?php endif; ?> value="<?php echo esc_attr( $value ); ?>" />
<?php if ( ! empty( $setting[\'desc\'] ) ) : ?>
<p class="small-desc"><?php echo esc_html( $setting[\'desc\'] ); ?></p>
<?php endif; ?>
</div>
<?php
break;
case \'checkbox\':
?>
<div class="mod-widget-option mod-option-type-<?php echo esc_attr( $setting[\'type\'] ); ?>">
<input id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" type="checkbox" class="checkbox<?php if ( ! empty( $input_css_classes ) ) echo \' \' . implode( \' \', $input_css_classes ); ?>" name="<?php echo esc_attr( $this->get_field_name( $key ) ); ?>" <?php echo checked( $value, 1 ); ?> />
<label for="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" class="mod-checkbox-label"><?php echo esc_html( $setting[\'label\'] ); ?></label>
<?php if ( ! empty( $setting[\'desc\'] ) ) : ?>
<p class="small-desc"><?php echo esc_html( $setting[\'desc\'] ); ?></p>
<?php endif; ?>
</div>
<?php
break;
// Default: run an action.
default:
do_action( \'mod_widget_field_\' . $setting_type, $key, $value, $setting, $instance );
break;
}
}
}
/**
* Outputs the settings form for the widget.
*/
public function form( $instance ) {
if ( empty( $this->fields ) ) {
return;
}
$this->field_generator( $instance );
}
}
小部件代码:
<?php
/**
* Widget -
*
* @version 1.0.0
*/
defined( \'ABSPATH\' ) || exit;
/**
* Widget - Test.
*/
class MOD_Widget_Test extends MOD_Widget {
/**
* Constructor.
*/
public function __construct() {
$this->widget_cssclass = \'mod mod_widget_test_abstract\';
$this->widget_description = __( \'A widget description.\', \'mod\' );
$this->widget_id = \'mod-widget-test\';
$this->widget_name = __( \'MOD Widget - Test\', \'mod\' );
$this->fields = array(
\'base_title\' => array(
\'label\' => __( \'Base Title\', \'mod\' ),
\'type\' => \'text\',
\'class\' => \'\',
\'default_value\' => \'Test\',
),
\'about_title\' => array(
\'label\' => __( \'About Title\', \'mod\' ),
\'type\' => \'text\',
\'class\' => \'\',
\'default_value\' => \'\',
),
\'base_num\' => array(
\'label\' => __( \'Base Number\', \'mod\' ),
\'type\' => \'number\',
\'class\' => \'\',
\'default_value\' => 10,
\'min\' => -1,
\'step\' => 1,
),
\'base_checkbox\' => array(
\'label\' => __( \'Base Checkbox\', \'mod\' ),
\'type\' => \'checkbox\',
\'class\' => \'\',
\'default_value\' => 0,
),
// General
\'group_general\' => array(
\'label\' => __( \'General\', \'mod\' ),
\'type\' => \'group\',
\'sub_fields\' => array(
\'general_title\' => array(
\'label\' => __( \'General Title\', \'mod\' ),
\'type\' => \'text\',
\'class\' => \'\',
\'default_value\' => \'\',
),
\'general_num\' => array(
\'label\' => __( \'General Number\', \'mod\' ),
\'type\' => \'number\',
\'class\' => \'\',
\'default_value\' => \'\',
\'min\' => -1,
\'step\' => 1,
),
\'general_checkbox\' => array(
\'label\' => __( \'General Checkbox\', \'mod\' ),
\'type\' => \'checkbox\',
\'class\' => \'\',
\'default_value\' => 1,
),
),
),
// Special
\'group_special\' => array(
\'label\' => __( \'Special Parameters\', \'mod\' ),
\'type\' => \'group\',
\'sub_fields\' => array(
\'special_title\' => array(
\'label\' => __( \'Special Title\', \'mod\' ),
\'type\' => \'text\',
\'class\' => \'\',
\'default_value\' => \'\',
),
\'special_desc\' => array(
\'label\' => __( \'Special Description\', \'mod\' ),
\'type\' => \'textarea\',
\'class\' => \'\',
\'default_value\' => \'\',
),
),
),
);
parent::__construct();
}
/**
* Output widget.
*
* @see WP_Widget
*
* @param array $args Arguments.
* @param array $instance Widget instance.
*/
public function widget( $args, $instance ) {
ob_start();
echo $args[\'before_widget\'];
echo \'<pre>\';
var_dump( $instance );
echo \'</pre>\';
echo $args[\'after_widget\'];
}
}
提前非常感谢!