Form Submits When Fields Called Directly, Fails When Using Callbacks
-
I’m working on a WordPress plugin and facing an issue with the Settings API. I have a settings page with two forms. The first form uses do_settings_sections() to call fields from a public function (callback). The second form renders the fields directly in the HTML.
When I submit the form that calls fields directly, it works fine. However, the form that uses do_settings_sections() and callbacks results in a “400 Bad Request” error when submitted.
Why isn’t the do_settings_sections form submitting correctly?
Here’s a simplified version of my code:
function snap_save_settings() { error_log('triggered snap_save_settings, Success!'); } add_action('admin_post_snap_save_settings', 'snap_save_settings'); class Snap_Settings extends Snap_Settings_Page { protected function initialize_settings() { // General Settings Section $this->add_section('snap_main_settings', '', [$this, 'main_settings_section_callback'], 'snap-main-settings'); $this->add_field('snap_main_settings', 'snap_linking_mode', '', [$this, 'linking_mode_callback'], 'snap-main-settings'); } //callback public function main_settings_section_callback() { } public function linking_mode_callback() { // Output a basic text input form field for testing echo '<label for="snap_test_input">Test Input:</label>'; echo '<input type="text" id="snap_test_input" name="snap_test_input" value="">'; } // Display Settings public function display_settings_page() { ?> <div class="wrap"> <!-- Form using do_settings_sections() --> <form method="post" action="<?php echo admin_url('admin-post.php'); ?>"> <label>This form is rendered using do_settings_sections and does not work</label> <input type="hidden" name="action" value="snap_save_settings"> <?php settings_fields('snap_settings_group'); do_settings_sections('snap-main-settings'); submit_button(); ?> </form> <br> <br> <!-- Form with fields rendered directly --> <form method="post" action="<?php echo admin_url('admin-post.php'); ?>"> <label>This form is rendered directly and it works</label> <input type="hidden" name="action" value="snap_save_settings"> <input type="text" name="snap_test_input" value="Test Value"> <input type="submit" value="Save Changes"> </form> </div> <?php } } new Snap_Settings();
Here is the settings base:
abstract class Snap_Settings_Page { private $sections = []; abstract protected function initialize_settings(); public function __construct() { add_action('admin_menu', [$this, 'add_menu_page']); add_action('admin_init', [$this, 'register_settings']); } public function add_menu_page() { add_options_page( 'Snap Settings', // Page title 'Snap', // Menu title 'manage_options', // Capability 'snap-settings', // Menu slug [$this, 'display_settings_page'] // Callback function ); } public function register_settings() { $this->initialize_settings(); foreach ($this->sections as $section_id => $section) { add_settings_section( $section_id, $section['title'], $section['callback'], $section['page_slug'] ); foreach ($section['fields'] as $field_id => $field) { add_settings_field( $field_id, $field['title'], $field['callback'], $field['page_slug'], // Use the page_slug from the field $section_id ); register_setting('snap_settings_group', $field_id); } } } protected function add_section($id, $title, $callback, $page_slug = 'snap-settings') { $this->sections[$id] = [ 'title' => $title, 'callback' => $callback, 'fields' => [], 'page_slug' => $page_slug // Store the page_slug with the section ]; } protected function add_field($section_id, $field_id, $title, $callback, $page_slug = 'snap-settings') { if (!isset($this->sections[$section_id])) { // Optionally handle the error if the section does not exist return; } $this->sections[$section_id]['fields'][$field_id] = [ 'title' => $title, 'callback' => $callback, 'page_slug' => $page_slug ]; } abstract public function display_settings_page(); }
Viewing 2 replies - 1 through 2 (of 2 total)
Viewing 2 replies - 1 through 2 (of 2 total)
- The topic ‘Form Submits When Fields Called Directly, Fails When Using Callbacks’ is closed to new replies.