Make WordPress Core

Opened 12 years ago

Closed 7 years ago

#21488 closed enhancement (duplicate)

Add Default Callback Functions for add_settings_field()

Reported by: mordauk's profile mordauk Owned by:
Milestone: Priority: normal
Severity: normal Version:
Component: Plugins Keywords: has-patch dev-feedback
Focuses: administration Cc:

Description (last modified by scribu)

By default, when creating options in plugins and themes, every developer is required to create custom callback functions for rendering their option's HTML. The HTML for most options is nothing more than a standard INPUT field, a SELECT field, TEXTAREA field, etc, so there's really no reason there shouldn't be default callback options in place.

For example, if I have a plugin that registers one text field option in the General settings page, it really doesn't make sense that I should be forced to create a callback function, especially not when probably 99% of all text fields are outputted in exactly the same way:

<input name="FIELD NAME" id="FIELD ID" value="FIELD VALUE" class="regular-text"/>
<div class="description">The description of the field (if present)</div>

With default field callbacks available, developers can do this:

function pw_register_settings() {
	register_setting( 'general', 'pw_sample_option', 'esc_attr' );
	add_settings_section( 'pw_sample_section', 'This is a Sample Section', 'pw_sample_section_cb', 'general');
	add_settings_field( 'pw_sample_option', 'A Sample Setting', 'text', 'general', 'pw_sample_section', array( 'description' => 'The field description' ) );
}
add_action('admin_init', 'pw_test_settings');

function pw_sample_section_cb() {
	// this is the section HTML (if you want it)
}

This is much simpler than also having to write the callback function to render the HTML for the option.

The patch attached adds the following default callbacks:

  • text
  • textarea
  • select
  • radio
  • checkbox
  • checkbox_group

For select, radio, and checkbox groups, the options are passed as an array of "choices" in the last, optional $args parameter for add_settings_field():

$options = array( 
	'one' => 'The Choice Name',
	'two' => 'The Second name', 
	'three' => 'The Third option'
);
add_settings_field( 'pw_sample_option', 'A Sample Setting', 'select', 'general', 'pw_sample_section', array( 'choices' => $options, 'description' => 'This is a select' ) );

When a user wants to create a custom callback function, this is still allowed as call_user_func() is the default in the $field['callback'] switch statement for the do_settings_fields() function.

Attachments (2)

default_callbacks.diff (5.4 KB) - added by mordauk 12 years ago.
Adds default callbacks for add_settings_field()
add_args_to_settings_section_callback.patch (1.6 KB) - added by cfoellmann 11 years ago.
hand over args to add_settings_section callback function

Download all attachments as: .zip

Change History (48)

@mordauk
12 years ago

Adds default callbacks for add_settings_field()

#1 @themeblvd
12 years ago

  • Cc themeblvd added

#2 @scribu
12 years ago

Overloading the $callback parameter seems like a slick solution. +1

#3 @scribu
12 years ago

  • Description modified (diff)

#4 @sabreuse
12 years ago

  • Cc sabreuse@… added

#5 @Japh
12 years ago

  • Cc japh@… added

#6 @jbobich
12 years ago

This would really help make it easier to create basic option pages and add more consistency among plugin and theme authors with their option panels. Make it so. +1

Some issues mordauk and I had when putting this together today was getting "default" option values to work with checkbox and checkbox groups, so we left it off those option types.

Also, if one does choose to use these default option type callbacks the way we've got them here, you must have each option setup as a standard, single option field. In other words, you couldn't have your settings page work by saving all your settings to a single option field as a multi-dimensional array. -- Not sure if this is too serious of an issue, but maybe someone could have a look at that part of things and see if it's possible to allow that somehow.

Last edited 12 years ago by jbobich (previous) (diff)

#7 follow-ups: @scribu
12 years ago

How about, instead of overloading the callback arg, you just skip it entirely and use a 'type' option instead? For example:

$args = array(
	'type' => 'select',
	'choices' => array(
		'one' => 'The Choice Name',
		'two' => 'The Second name', 
		'three' => 'The Third option'
	),
	'description' => 'This is a dropdown.'
);

add_settings_field( 'pw_sample_option', 'A Sample Setting', false, 'general', 'pw_sample_section', $args );

Starts to look a lot like Customizer fields, don't it?

Version 0, edited 12 years ago by scribu (next)

#8 in reply to: ↑ 7 @sc0ttkclark
12 years ago

We actually use this same format for Pods 2.0 field handling, I recommend it. Maybe instead of choices, 'data', but that's just a suggestion. I'd also like to see a custom callback available for the type, or as long as the type can be anything and runs through an action through an 'else', then that's great.

Replying to scribu:

How about, instead of overloading the callback arg, you just skip it entirely and use a 'type' option instead?

#9 @sc0ttkclark
12 years ago

  • Cc lol@… added

#10 follow-up: @boonebgorges
12 years ago

  • Cc boonebgorges@… added

A big +1.

In fact, I suggest that these be moved out of wp-admin and into wp-includes, so that front-end plugin and theme developers could use the same methods for building form markup. There's nothing settings-specific about them as they're currently written.

#11 in reply to: ↑ 7 @mordauk
12 years ago

  • Resolution set to fixed
  • Status changed from new to closed

Replying to scribu:

How about, instead of overloading the callback arg, you just skip it entirely and use a 'type' option instead? For example:

$args = array(
	'type' => 'select',
	'choices' => array(
		'one' => 'The Choice Name',
		'two' => 'The Second name', 
		'three' => 'The Third option'
	),
	'description' => 'This is a dropdown.'
);

add_settings_field( 'pw_sample_option', 'A Sample Setting', false, 'general', 'pw_sample_section', $args );

Starts to look a lot like Customizer fields, don' it?

jbobich and I thought about that for a while and ultimately thought it made more sense to overload the callback instead of having a type option in the $args parameter. The default field types we've proposed here are still callbacks in terms of what they do, so I don't think they should be separated. I have a feeling it would get confusing for users if they saw that they could define a callback AND a type but only one could actually be used. There would be some users who would create a text field callback and then also set the type to "text" not realizing that only one or the other was necessary.

#12 @mordauk
12 years ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

#13 in reply to: ↑ 10 ; follow-up: @sc0ttkclark
12 years ago

Replying to boonebgorges:

A big +1.

In fact, I suggest that these be moved out of wp-admin and into wp-includes, so that front-end plugin and theme developers could use the same methods for building form markup. There's nothing settings-specific about them as they're currently written.

Oh this is gold.

#14 in reply to: ↑ 13 @mordauk
12 years ago

Replying to sc0ttkclark:

Replying to boonebgorges:

A big +1.

In fact, I suggest that these be moved out of wp-admin and into wp-includes, so that front-end plugin and theme developers could use the same methods for building form markup. There's nothing settings-specific about them as they're currently written.

Oh this is gold.

Completely agree. Perhaps instead of do_settings_text(), the functions should just be text_field(), select_field(), etc. This would match the pattern already used for the submit_button() function.

#15 @ocean90
12 years ago

  • Cc ocean90 added

#16 @toscho
12 years ago

  • Cc info@… added

#17 @WraithKenny
12 years ago

I've done something similar (with the $args overloading) but without the switch ($field['callback']) stuff:
https://github.com/unFocus/Scripts-n-Styles/blob/master/includes/class-sns-settings-page.php#L57

It references the methods here (it's only a class for naming collision prevention):
https://github.com/unFocus/Scripts-n-Styles/blob/master/includes/class-sns-form.php

The difference is I had to dual purpose label_for which *should* match the $field['id']

+1 for any sort of input html library in core tho :)

#18 @rzen
12 years ago

+1000 to this. I want to see this happen very much. I built the Options API for http://wpstartbox.com because I wanted to have something handy for all my callbacks (of course, I made it do a bunch of other things too).

I'll give this a test and report back.

#19 @cais
12 years ago

  • Cc edward.caissie@… added

#20 @husobj
12 years ago

  • Cc ben@… added

#21 @stephenh1988
12 years ago

  • Cc contact@… added

#22 @nvwd
12 years ago

  • Cc nowell@… added

#23 follow-up: @nacin
12 years ago

Rather than overloading add_settings_field()'s $callback argument with a type-like name (as scribu points out), why not just name the actual function there?

add_settings_field( 'upload_path', __( 'Upload path' ), 'do_settings_text',
    'media', 'uploads',
    array(
         'id' => 'upload_path', // defaults to first argument,
         'name' => 'upload_path', // defaults to first argument, then ['id']
         'class' => 'regular-text code',
         'description' => __( 'Default is <code>wp-content/uploads</code>' ),
);

#24 in reply to: ↑ 23 @mordauk
12 years ago

Replying to nacin:

Rather than overloading add_settings_field()'s $callback argument with a type-like name (as scribu points out), why not just name the actual function there?

add_settings_field( 'upload_path', __( 'Upload path' ), 'do_settings_text',
    'media', 'uploads',
    array(
         'id' => 'upload_path', // defaults to first argument,
         'name' => 'upload_path', // defaults to first argument, then ['id']
         'class' => 'regular-text code',
         'description' => __( 'Default is <code>wp-content/uploads</code>' ),
);

I prefer overloading it instead because that allows the user to just pass "text" or "textarea" as the callback, which makes it simpler. If the callback isn't overloaded and just the function name is passed, then I think the default callback functions should be named something more intuitive, perhaps just "text_field", "textarea_field", etc.

#25 @bpetty
12 years ago

  • Keywords dev-feedback added

This appears to be one implementation (a child) of #18285, which I know a couple devs discussing this patch are aware of, but it hasn't been mentioned in this ticket, so I'm pointing it out now. Take a look there for other ideas on how a new settings API could be
implemented.

Also related: #9296 (in reference to lack of flexible API for custom permalink settings)

#26 @bpetty
12 years ago

  • Cc bpetty added
  • Milestone changed from Awaiting Review to Future Release

#27 @Otto42
11 years ago

  • Cc Otto42 added

#28 @sunnyratilal
11 years ago

  • Cc ratilal.sunny@… added

#29 @cklosows
11 years ago

  • Cc cklosowski@… added

#30 @dougal
11 years ago

This isn't going to make it into 3.5?

Darnit, I was all set to update my plugins.

#31 @dougal
11 years ago

  • Cc dougal@… added

#32 follow-up: @kovshenin
11 years ago

  • Cc kovshenin added

If this does go into core, I think it should be part of #18285 and not global functions.

#33 in reply to: ↑ 32 @mordauk
11 years ago

Replying to kovshenin:

If this does go into core, I think it should be part of #18285 and not global functions.

I would actually like to see it done with both. As it stands, this is a patch that can be implemented at anytime. The entire new Settings API class, however, is still a long ways out.

While it might be a temporary improvement, it would still be hugely helpful for the next year, year and a half while the new class is worked on.

#34 @unknowndomain
11 years ago

  • Keywords settings-3.6 added

#35 @unknowndomain
11 years ago

  • Cc me@… added

#36 @SergeyBiryukov
11 years ago

  • Keywords settings-api added; settings-3.6 removed

#37 @dcowgill
11 years ago

  • Cc dcowgill@… added

#38 @zamoose
11 years ago

  • Cc zamoose@… added

#39 @cfoellmann
11 years ago

  • Cc foellmann@… added

@cfoellmann
11 years ago

hand over args to add_settings_section callback function

#40 @cfoellmann
11 years ago

Added an $args array to the function

add_settings_section( $id, $title, $callback, $page )

which results in

add_settings_section( $id, $title, $callback, $page, $args = array() )

Example functions:

function register_some_settings() {
	add_settings_section( 
		'some_id', // $id
		'Some Title', // $title
		'generate_section', // $callback
		'some_page', // $page
		array(
			"desc" => "some text for the section description"
		)
	);
	
	// add some fields ...
	
	add_settings_section( 
		'some_other_id', // $id
		'Another Title', // $title
		'generate_section', // $callback
		'some_page', // $page
		array(
			"desc" => "A DIFFERENT text for the second section's description"
		)
	);
}

function generate_section( $args ) {
	echo '<p>' . $args['desc'] . '</p>';
}

#41 @cfoellmann
11 years ago

moved the patch to a dedicated ticket since it is not really in the scope of the ticket.
See #25154

#42 @nacin
10 years ago

  • Component changed from General to Plugins

#43 @nacin
10 years ago

  • Component changed from Plugins to Admin APIs
  • Focuses administration added

#44 @nacin
10 years ago

  • Component changed from Admin APIs to Plugins

Sorry for the noise.

#45 @chriscct7
8 years ago

  • Keywords settings-api removed

#46 @swissspidy
7 years ago

  • Milestone Future Release deleted
  • Resolution set to duplicate
  • Status changed from reopened to closed

Duplicate of #39441.

Note: See TracTickets for help on using tickets.