0

My WordPress and PHP knowledge is limited, but I am working on a plugin, and in the admin page I have three settings - two text inputs and one checkbox.

On save, the values are stored in the wp_options table. If the options exist, the page then shows the values of the text inputs underneath the inputs. So far so good.

My question is how can submit the form, without overriding the wp_options with blank values if the text fields are blank when saved?

Use case: Allow users to update the checkbox (turn off/on) without the need to re-enter the text details.

<?php

defined('ABSPATH') or die('This page may not be accessed directly.');

add_action('admin_menu', 'myplugin_admin_menu');

function myplugin_admin_menu()
{
  add_menu_page('MyPlugin', 'MyPlugin', 'manage_options', 'myplugin-admin-page.php', 'myplugin_admin_page', 81);
}

add_action('admin_init', 'register_myplugin_settings');

function register_myplugin_settings()
{
  register_setting('myplugin_settings_group', 'myplugin_id');
  register_setting('myplugin_settings_group', 'myplugin_api_key');
  register_setting('myplugin_settings_group', 'myplugin_checkbox');
}

add_action('admin_print_styles', 'admin_styles');

function admin_styles()
{
  wp_enqueue_style('style', plugins_url('myplugin-admin.css', __FILE__), array(), time());
}


// Content for WP Admin Page
function myplugin_admin_page()
{
?>
  <header><img src="<?php echo plugins_url('/images/myplugin.svg', __FILE__); ?>"></header>
  <div class="mp-content">
    <h2>Settings</h2>
    <form method="POST" action="<?php echo admin_url('options.php'); ?>">
      <?php settings_fields('myplugin_settings_group'); ?>
      <?php do_settings_sections('myplugin_settings_group'); ?>
      <label for="appid">ID </label>
      <input type="text" id="appid" name="myplugin_id" />
      <p>
        <?php
        $ID = esc_attr(get_option('myplugin_id'));
        if (!empty($ID)) {
          echo '✅ ' . $ID;
        } else {
          echo '❌ Please enter your ID';
        }
        ?>
      </p>
      <label for="apikey">API Key </label>
      <input type="text" id="apikey" name="myplugin_api_key" />
      <p>
        <?php
        $api = esc_attr(get_option('myplugin_api_key'));
        if (!empty($apiKey)) {
          // Get the last four characters
          $lastFour = substr($apiKey, -4);
          // Hide the rest of the key with asterisks
          $hiddenKey = str_repeat('*', strlen($apiKey) - 4) . $lastFour;

          echo '✅ ' . $hiddenKey;
        } else {
          echo '❌ Please enter your API Key';
        }
        ?>
      </p>
      <div class="checkbox-wrapper">
        <label for="checkbox-option">
          <input id="checkbox-option" type="checkbox" name="myplugin_checkbox" <?php echo get_option('myplugin_checkbox') && get_option('myplugin_checkbox') == 'on' ? 'checked' : '' ?>>
          <span class="checkbox"></span>
          Checkbox option label
        </label>
        <div class="more-information" aria-label="More information"><svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="currentColor">
            <g fill="currentColor">
              <path d="M8 0a8 8 0 108 8 8.009 8.009 0 00-8-8zm0 12.667a1 1 0 110-2 1 1 0 010 2zm1.067-4.054a.667.667 0 00-.4.612.667.667 0 01-1.334 0 2 2 0 011.2-1.834A1.333 1.333 0 106.667 6.17a.667.667 0 01-1.334 0 2.667 2.667 0 113.734 2.444z"></path>
            </g>
          </svg>
        </div>
      </div>
      <?php submit_button(); ?>
    </form>
  </div>
<?php
}

I was searching Google for "ignore empty inputs on settings save", and similar. Which didn't return what I was looking for, so I tried chat GPT which offered the solution below, but the form is still submitted and the options overwritten with blank values.

 // Check if the form has been submitted
  if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Check if the form fields are set and not empty before updating options
    $ID = isset($_POST['myplugin_id']) ? sanitize_text_field($_POST['myplugin_id']) : '';
    $apiKey = isset($_POST['myplugin_api_key']) ? sanitize_text_field($_POST['myplugin_api_key']) : '';

    // Update options only if the corresponding form fields are not empty
    if (!empty($ID)) {
      update_option('myplugin_app_id', $ID);
    }

    if (!empty($apiKey)) {
      update_option('myplugin_api_key', $apiKey);
    }
  }
2
  • 2
    This isn't something you normally need to do, because the current values are typically used to populate the inputs. This is how the core settings pages work, for example. Is there a reason you're doing it this way? Dec 22, 2023 at 14:28
  • I do agree that it could be made easier by keeping the values in those inputs. I neglected to mention in the original post: As its an api key in the second input, I want to obfuscate after save (which is now happening underneath the input). When I left the obfuscated value it in the input previously, a save would update the value with the asterixes (*) that I'd used.
    – mjlu
    Dec 22, 2023 at 17:40

2 Answers 2

0

First you need to catch the input then you can save it from $_POST So i assume your input fields names are myplugin_id , myplugin_api_key and myplugin_checkbox what you are currently doing is just going to replace the option with myplugin_checkbox

You can try

    function register_myplugin_settings() {
       if ( isset( $_POST['myplugin_id'] ) && ! empty( $_POST['myplugin_id'] ) ) {
          update_option( 'myplugin_id', sanitize_text_field( $_POST['myplugin_id'] ) );
       }
       if ( isset( $_POST['myplugin_api_key'] ) && ! empty( $_POST['myplugin_api_key'] ) ) {
          update_option( 'myplugin_api_key', sanitize_text_field( $_POST['myplugin_api_key'] ) );
       }
       if ( isset( $_POST['myplugin_checkbox'] ) && ! empty( $_POST['myplugin_checkbox'] ) ) {
          update_option( 'myplugin_checkbox', sanitize_text_field( $_POST['myplugin_checkbox'] ) );
       }
    }

update_option is straight to save the setting or option with its name. And to retrive data back from database you can use get_option function like

$myplugin_id = get_option( 'myplugin_id' );

if ( ! empty( $myplugin_id ) ) {
   //Dosomething when id is not empty
} else {
   //Do something when empty
}

If you still want to use the register_setting function just replace update_option with that one and check their documentation how to save the input there https://developer.wordpress.org/reference/functions/register_setting/

Good luck.

5
  • Thanks for this! this seems to achieve what I need, however I have now run into another problem. The value of the checkbox is updated in the database, however if I refresh, or navigate away / back to the settings page, the value defaults to off. Do I still need this line? add_action('admin_init', 'register_myplugin_settings')? Should admin_init be replaced with something else?
    – mjlu
    Jan 2 at 12:36
  • Corrected this by wrapping your suggestion in if ($_SERVER['REQUEST_METHOD'] === 'POST') {}
    – mjlu
    Jan 2 at 14:30
  • I thought my comment above solved the problem, however I have noticed that If I view the site, then go back to the admin area the checkbox will default to off.
    – mjlu
    Jan 3 at 13:35
  • Try changing <input id="checkbox-option" type="checkbox" name="myplugin_checkbox" <?php echo get_option('myplugin_checkbox') && get_option('myplugin_checkbox') == 'on' ? 'checked' : '' ?>> with <?php $checkBox = ( get_option( 'myplugin_checkbox' ) == 'on' ) ? 'checked' : ''; ?> and use name="myplugin_checkbox" <?php echo esc_attr( $checkBox ); ?> If don't work try to print the value of myplugin_checkbox and see what it returns from get_option Jan 4 at 1:00
  • Thanks for the reply. I solved this by ensuring that values were only updated when there was a submit in the post: if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_POST["submit"])) { }}
    – mjlu
    Jan 5 at 11:52
0

you could check for an empty string before updating the option..

if ( isset($_POST['myplugin_id']) && trim($_POST['myplugin_id']) != '' ) {
    update_option('myplugin_app_id', sanitize_text_field($_POST['myplugin_id']));
}
2
  • Thanks for the feedback. Forgive me, but where would this be placed into my code?
    – mjlu
    Dec 22, 2023 at 13:21
  • .... and how is that different to what I included at the bottom of the original post?
    – mjlu
    Dec 22, 2023 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.