Skip to main content
Better answer
Source Link
Sally CJ
  • 39.9k
  • 2
  • 26
  • 48

ActuallySo I could understand why you "customized" (in response toi.e. use your answerown version of) the do_settings_sections() and do_settings_fields() functions — because you want to use div and not table, right?

But if it's just about styling, you could actually just use CSS to style the more proper waytable so that it doesn't look like a table; however, you'll have to try doing that on your own. And WordPress may change the global variables (their name and/or data structure) in the future, so just keep that in mind, i.e. you'll have to make sure that your code is in sync with the original functions in the current WordPress release.

Making your form works properly (e.g. the fields are saved in the correct database option)

As I said in the comments, instead of callingyour form should submit to options.php (i.e. <form action="options.php" ...>) and call register_setting() in your code to register your form or its settings group, and the database option (the second parameter for that function).

And in the amna_theme_options_page(), there's no need to call the amna_do_settings_fields() because it's already being called in and should only be called in amna_do_settings_sections() which renders all the fields for your settings form, whereby each field should belong in a specific section. So instead, call settings_fields() so that WordPress knows what the options/settings page is and the database option to be updated:

And asAnother issue I saidnoticed is that in amna_do_settings_fields(), if the commentslabel_for arg is not empty, your form should submitthen the field is not actually going to be rendered because the options.phpcall_user_func() and call register_setting()is only being called in your codethe else part.

So it should be more like so:

//echo Make'<p>';
if sure( you! registerempty( your$field['args']['label_for'] setting,) e.g.) with{
 the option your_option:
add_action( 'admin_init',echo function'<label for="' . esc_attr() {
$field['args']['label_for'] ) . '">' register_setting(. 'amna-fields-group',$field['title'] 'your_option'. );'</label>';
} else {
    add_settings_section(echo '<section$field['title'];
}

call_user_func( id>'$field['callback'], '<Title>',$field['args'] '<callback>');
echo '</p>';

Additionally, you should pass the slug of your settings page to settings_errors(), e.g. settings_errors( 'theme_amna' ); if the slug is theme_amna. And if you don't do that, then you'd likely see the same settings errors/messages printed twice.

Also, admin stylesheet files (.css) should be enqueued via the admin_enqueue_scripts hook. For example, to enqueue only on your settings page:

add_action( 'admin_enqueue_scripts', 'theme_amna''my_plugin_load_styles' );
function my_plugin_load_styles( $hook_suffix ) {
    add_settings_fieldif ( '<id>',$hook_suffix '<Title>',=== '<callback>',get_plugin_page_hook( 'theme_amna', '<section id>''' );

   ) ...{
} );

// Then in amna_theme_options_page(), submit the form towp_enqueue_style( 'theme-options.php:-css',
// <form action="options.php" ...>

// And your fields should also use the your_option in the name,get_template_directory_uri() e.g.
 '/inc/admin/assets/css/theme-options-css.css' <input);
 name="your_option[foo]" ...>  }
}

Working Example

Also, ifYou can find it on GitHub.

It's a full working example which gives you haven't already done so,a settings page at check this out on the Plugin developer handbookSettings → Test. :)

Actually (in response to your answer), the more proper way is, instead of calling amna_do_settings_fields(), call settings_fields() so that WordPress knows what the options/settings page is and the database option to be updated:

And as I said in the comments, your form should submit to options.php and call register_setting() in your code:

// Make sure you register your setting, e.g. with the option your_option:
add_action( 'admin_init', function () {
    register_setting( 'amna-fields-group', 'your_option' );

    add_settings_section( '<section id>', '<Title>', '<callback>', 'theme_amna' );

    add_settings_field( '<id>', '<Title>', '<callback>', 'theme_amna', '<section id>' );

    ...
} );

// Then in amna_theme_options_page(), submit the form to options.php:
// <form action="options.php" ...>

// And your fields should also use the your_option in the name, e.g.
// <input name="your_option[foo]" ...>

Also, if you haven't already done so, check this out on the Plugin developer handbook. :)

So I could understand why you "customized" (i.e. use your own version of) the do_settings_sections() and do_settings_fields() functions — because you want to use div and not table, right?

But if it's just about styling, you could actually just use CSS to style the table so that it doesn't look like a table; however, you'll have to try doing that on your own. And WordPress may change the global variables (their name and/or data structure) in the future, so just keep that in mind, i.e. you'll have to make sure that your code is in sync with the original functions in the current WordPress release.

Making your form works properly (e.g. the fields are saved in the correct database option)

As I said in the comments, your form should submit to options.php (i.e. <form action="options.php" ...>) and call register_setting() in your code to register your form or its settings group, and the database option (the second parameter for that function).

And in the amna_theme_options_page(), there's no need to call the amna_do_settings_fields() because it's already being called in and should only be called in amna_do_settings_sections() which renders all the fields for your settings form, whereby each field should belong in a specific section. So instead, call settings_fields() so that WordPress knows what the options/settings page is and the database option to be updated:

Another issue I noticed is that in amna_do_settings_fields(), if the label_for arg is not empty, then the field is not actually going to be rendered because the call_user_func() is only being called in the else part.

So it should be more like so:

echo '<p>';
if ( ! empty( $field['args']['label_for'] ) ) {
    echo '<label for="' . esc_attr( $field['args']['label_for'] ) . '">' . $field['title'] . '</label>';
} else {
    echo $field['title'];
}

call_user_func( $field['callback'], $field['args'] );
echo '</p>';

Additionally, you should pass the slug of your settings page to settings_errors(), e.g. settings_errors( 'theme_amna' ); if the slug is theme_amna. And if you don't do that, then you'd likely see the same settings errors/messages printed twice.

Also, admin stylesheet files (.css) should be enqueued via the admin_enqueue_scripts hook. For example, to enqueue only on your settings page:

add_action( 'admin_enqueue_scripts', 'my_plugin_load_styles' );
function my_plugin_load_styles( $hook_suffix ) {
    if ( $hook_suffix === get_plugin_page_hook( 'theme_amna', '' ) ) {
        wp_enqueue_style( 'theme-options-css',
            get_template_directory_uri() . '/inc/admin/assets/css/theme-options-css.css' );
    }
}

Working Example

You can find it on GitHub.

It's a full working example which gives you a settings page at Settings → Test.

Source Link
Sally CJ
  • 39.9k
  • 2
  • 26
  • 48

Actually (in response to your answer), the more proper way is, instead of calling amna_do_settings_fields(), call settings_fields() so that WordPress knows what the options/settings page is and the database option to be updated:

settings_fields( 'amna-fields-group' );                       // do this
//amna_do_settings_fields('amna-fields-group', 'theme_amna'); // not this

And as I said in the comments, your form should submit to options.php and call register_setting() in your code:

// Make sure you register your setting, e.g. with the option your_option:
add_action( 'admin_init', function () {
    register_setting( 'amna-fields-group', 'your_option' );

    add_settings_section( '<section id>', '<Title>', '<callback>', 'theme_amna' );

    add_settings_field( '<id>', '<Title>', '<callback>', 'theme_amna', '<section id>' );

    ...
} );

// Then in amna_theme_options_page(), submit the form to options.php:
// <form action="options.php" ...>

// And your fields should also use the your_option in the name, e.g.
// <input name="your_option[foo]" ...>

Also, if you haven't already done so, check this out on the Plugin developer handbook. :)