WordPress短代码可显示默认Widget但无法显示自定义Widget的修复问询
I see the issue here — your shortcode works for default WordPress widgets because they often have fallback default values when no instance data is passed, but your custom widgets (like the Newsletter widget) depend on the configuration you saved in the WordPress admin. The problem is you're not passing the saved instance data to the_widget() when calling custom widgets.
Why This Happens
When you use the_widget($widget_type, $instance, $args), the second parameter $instance holds all the custom settings (title, description, form code, etc.) you saved for that specific widget instance. For default widgets like Calendar, WordPress can render a basic version without this data, but your custom widgets need it to display correctly. Your current code passes an undefined $instance variable, which means your custom widget gets empty values for all its fields.
Step-by-Step Fix
Here's how to modify your shortcode to fetch and pass the correct instance data for custom widgets:
- Fetch the saved widget instance from the WordPress options table (where widget configurations are stored).
- Pass the instance data to
the_widget()so your custom widget can access its saved settings.
Updated Shortcode Code
function widget_shortcodes($atts) { global $wp_widget_factory; // Use shortcode_atts to handle defaults properly $parts = shortcode_atts(array( 'id' => '1', 'type' => 'text' ), $atts ); $widget_id = $parts['id']; $widget_type = ''; // Clean up widget type mapping with a switch statement switch($parts['type']) { case 'calendar': $widget_type = 'WP_Widget_Calendar'; break; case 'posts': $widget_type = 'My_Recent_Posts_Widget'; break; case 'text': $widget_type = 'WP_Widget_Text'; break; case 'form': $widget_type = 'quickform_widget'; break; case 'newsletter': $widget_type = 'newsletter_widget'; break; case 'reviews': $widget_type = 'reviews_widget'; break; default: $widget_type = ''; } ob_start(); if(!empty($widget_type)) { // Get the widget object from the factory $widget_obj = $wp_widget_factory->widgets[$widget_type]; // Build the option name where this widget's instances are stored $option_name = 'widget_' . $widget_obj->id_base; // Fetch all saved instances for this widget type $widget_options = get_option($option_name, array()); // Extract the specific instance matching our widget_id $instance = isset($widget_options[$widget_id]) ? $widget_options[$widget_id] : array(); // Now call the_widget with the correct instance data the_widget($widget_type, $instance, array('widget_id' => $widget_id)); $widget_output = ob_get_contents(); } else { echo "<p>Please make sure you have set a valid type in your shortcode.</p>"; echo "<p>Accepted Types: calendar, posts, text, form, newsletter and reviews.</p>"; $widget_output = ob_get_contents(); } ob_end_clean(); return $widget_output; } add_shortcode('widget','widget_shortcodes');
Key Changes Explained
- Proper use of
shortcode_atts: We now use$parts['id']and$parts['type']instead of directly accessing$atts, ensuring default values are applied when users omit parameters. - Fetching instance data:
- We get the widget object from
$wp_widget_factoryto retrieve itsid_base(the base identifier used for storing options). - We fetch all saved instances for the widget type using
get_option(). - We extract the specific instance matching the
idpassed in the shortcode.
- We get the widget object from
- Passing instance to
the_widget(): The saved instance data is now passed as the second parameter, so your custom widget can access the title, description, and form code you saved in the admin.
Testing the Fix
Make sure your shortcode uses the correct id for your widget instance. For example, if you added the Newsletter widget once in the admin, its instance ID is likely 1, so your shortcode would be:
[widget type="newsletter" id="1"]
Your custom Newsletter widget code looks correct (it properly uses $instance values in the widget() method), so once you update the shortcode, it should display the saved content as expected.
内容的提问来源于stack exchange,提问作者Daniel Vickers

