- 赤色のリンクは、まだ日本語Codexに存在しないページ・画像です。英語版と併せてご覧ください。(詳細)
「設定ページの作成」の版間の差分
Takahashi Fumiki (トーク | 投稿記録) (en:Creating_Options_Pages2009/2/20 Ronnie268) |
細 (→はじめに: 表記ゆれ) |
||
(4人の利用者による、間の7版が非表示) | |||
1行目: | 1行目: | ||
+ | <span style="color:red">この記事は、 [[Version 2.7]] で導入された [[Settings API]] に合わせて更新されています。2.7 より古いバージョンの場合は [http://wpdocs.sourceforge.jp/wiki/index.php?title=%E8%A8%AD%E5%AE%9A%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AE%E4%BD%9C%E6%88%90&oldid=2797 履歴] をごらんください。</span> | ||
+ | |||
== はじめに == | == はじめに == | ||
− | + | WordPressにカスタムの設定画面を作ることは比較的簡単です。 | |
− | メニューアイテムと新しいページを作るには、まず[[Adding Administration Menus|管理メニューの追加]]を見てください。 | + | メニューアイテムと新しいページを作るには、まず[[Adding Administration Menus | 管理メニューの追加]]を見てください。 |
この構造に従う限りは、WordPressがあなたの代わりに作成、更新、保存、リダイレクトといった設定を行ってくれます。パーミッションをチェックし、裏側で起きているすべてを魔法のように執り行うのです。 | この構造に従う限りは、WordPressがあなたの代わりに作成、更新、保存、リダイレクトといった設定を行ってくれます。パーミッションをチェックし、裏側で起きているすべてを魔法のように執り行うのです。 | ||
− | + | WordPress 2.7 でいくつかの関数が追加されました。WordPress 2.7 時点では、これらの関数を使うかどうかは任意選択ですが、将来必須になるでしょう。WordPress MU 2.7 では必須です。詳細は [[Migrating Plugins and Themes to 2.7]] と [[Settings API]] をごらんください。 | |
− | + | この記事は、設定ページのマークアップのみを説明しています。設定ページの追懐については、[[Administration Menus | 管理メニュー]]をごらんください。 | |
− | + | == コードの保存先 == | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | == | + | オプションページのコードは、プラグインの PHP ファイル (テーマの場合は functions.php) 内に置くか、options.php のようなファイルを作成し、php の include 関数 - http://php.net/manual/en/function.include.php を使うことができます。 |
+ | |||
+ | == ページの開始 == | ||
+ | |||
+ | 既存の WordPress オプションページの見た目に合わせたい場合、以下のように開始します。 | ||
+ | <div class="wrap"> | ||
+ | <h2>Your Plugin Page Title</h2> | ||
+ | |||
+ | == Form タグ == | ||
ページを作ったら、HTMLフォームを作る必要があります。このコードを使ってください: | ページを作ったら、HTMLフォームを作る必要があります。このコードを使ってください: | ||
− | |||
− | |||
− | |||
− | == | + | <form method="post" action="options.php"> |
− | |||
− | + | === settings_fields 関数 === | |
− | + | ||
− | + | ||
− | + | setting fields が、オプションページの設定を上手く処理してくれます。 | |
− | + | 開始 form タグの後、以下の関数を追加します。 | |
− | + | settings_fields( 'myoption-group' ); | |
− | < | + | ここで <tt>myoption-group</tt> は [[関数リファレンス/register_setting|register_setting]] 関数で使用した名前と同じにします。 |
− | + | ||
− | </ | + | |
− | + | Version 2.7 以前では、'''nonce magic''', '''action field''', そして '''page_options field''' が必須でしたが、この関数が面倒みてくれます。 | |
− | + | === do_settings_fields 関数 === | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | settings_fields() を呼び出した後、以下の関数を追加します。 | |
− | + | do_settings_sections( 'myoption-group' ); | |
− | + | ||
− | + | ||
− | + | この関数は、フォームのマークアップ自体を面倒みてくれます。 | |
− | + | == 終了タグ == | |
+ | |||
+ | それでは、その他の設定を入力して、formタグを閉じましょう。WordPressのデフォルトである"設定を更新"ボタンを使うこともできます。 | ||
+ | |||
+ | <?php submit_button(); ?> | ||
+ | </form> | ||
+ | </div> | ||
+ | |||
+ | [[関数リファレンス/submit_button|submit_button]] 関数でボタンを作成することができます。 | ||
+ | |||
+ | テキストを翻訳対応にするためには、_e()関数を使うようにしてください。詳しくは [[Localizing WordPress | WordPress の翻訳]]を参照してください。 | ||
+ | |||
+ | === Register Settings === | ||
+ | |||
+ | [[関数リファレンス/register setting|register_setting]] 関数と [[関数リファレンス/unregister setting|unregister_setting]] 関数は、フォームが保存できるオプションのホワイトリストにオプションを追加/削除します。セキュリティのために、各オプションの値をチェックするコールバック関数を指定できます。 | ||
+ | |||
+ | register_setting 関数は [[Plugin API/Action Reference#Administrative Actions|admin_init]] アクションフックで呼び出されるべきです。このフックは他の管理ページよりも先に呼び出され、このフォームを受け取る <tt>options.php</tt> よりも先に呼び出されます。 | ||
+ | |||
+ | あなたのプラグインには、新しいメニューを追加する add_action セクションがあるかもしれません。This line will be in the same section to add an action to admin_init. | ||
<pre> | <pre> | ||
− | + | if ( is_admin() ){ // admin actions | |
+ | add_action( 'admin_menu', 'add_mymenu' ); | ||
+ | add_action( 'admin_init', 'register_mysettings' ); | ||
+ | } else { | ||
+ | // non-admin enqueues, actions, and filters | ||
+ | } | ||
</pre> | </pre> | ||
− | + | それから各オプションを登録する関数を作成します。 | |
− | |||
<pre> | <pre> | ||
− | + | function register_mysettings() { // whitelist options | |
+ | register_setting( 'myoption-group', 'new_option_name' ); | ||
+ | register_setting( 'myoption-group', 'some_other_option' ); | ||
+ | register_setting( 'myoption-group', 'option_etc' ); | ||
+ | } | ||
</pre> | </pre> | ||
− | + | <tt>myoption-group</tt> の名前はなんでも良いですが、上述の settings_fields 関数で使用する名前と同じにしてください。 | |
− | + | === すべてを纏める === | |
+ | 注意: 例のいくつかは(とくに do_settings は) 古い書き方かもしれません。 [http://ottopress.com/2009/wordpress-settings-api-tutorial/ View Otto's tutorial here for better examples of workable code]. ほかにも [http://planetozh.com/blog/about/ ozh] による [http://planetozh.com/blog/2009/05/handling-plugins-options-in-wordpress-28-with-register_setting/ article] があります。 | ||
− | + | オプションページにアイコンを追加するには以下のコード [3.4.2 以降で使用可能] を用いてください。アイコンはテーマフォルダの "images" フォルダ内にあります。 | |
− | + | ||
− | + | ||
− | + | <pre><?php add_menu_page('BAW Plugin Settings', 'BAW Settings', 'administrator', __FILE__, 'baw_settings_page', get_stylesheet_directory_uri('stylesheet_directory')."/images/media-button-other.gif"); ?></pre> | |
− | + | Settings API を使用してプラグインのオプションを作成/保存する例です。 | |
<pre> | <pre> | ||
− | < | + | <?php |
− | + | // create custom plugin settings menu | |
− | + | add_action('admin_menu', 'baw_create_menu'); | |
+ | |||
+ | function baw_create_menu() { | ||
+ | |||
+ | //create new top-level menu | ||
+ | add_menu_page('BAW Plugin Settings', 'BAW Settings', 'administrator', __FILE__, 'baw_settings_page',plugins_url('/images/icon.png', __FILE__)); | ||
+ | |||
+ | //call register settings function | ||
+ | add_action( 'admin_init', 'register_mysettings' ); | ||
+ | } | ||
+ | |||
+ | |||
+ | function register_mysettings() { | ||
+ | //register our settings | ||
+ | register_setting( 'baw-settings-group', 'new_option_name' ); | ||
+ | register_setting( 'baw-settings-group', 'some_other_option' ); | ||
+ | register_setting( 'baw-settings-group', 'option_etc' ); | ||
+ | } | ||
+ | |||
+ | function baw_settings_page() { | ||
+ | ?> | ||
+ | <div class="wrap"> | ||
+ | <h2>Your Plugin Name</h2> | ||
+ | |||
+ | <form method="post" action="options.php"> | ||
+ | <?php settings_fields( 'baw-settings-group' ); ?> | ||
+ | <?php do_settings_sections( 'baw-settings-group' ); ?> | ||
+ | <table class="form-table"> | ||
+ | <tr valign="top"> | ||
+ | <th scope="row">New Option Name</th> | ||
+ | <td><input type="text" name="new_option_name" value="<?php echo esc_attr( get_option('new_option_name') ); ?>" /></td> | ||
+ | </tr> | ||
+ | |||
+ | <tr valign="top"> | ||
+ | <th scope="row">Some Other Option</th> | ||
+ | <td><input type="text" name="some_other_option" value="<?php echo esc_attr( get_option('some_other_option') ); ?>" /></td> | ||
+ | </tr> | ||
+ | |||
+ | <tr valign="top"> | ||
+ | <th scope="row">Options, Etc.</th> | ||
+ | <td><input type="text" name="option_etc" value="<?php echo esc_attr( get_option('option_etc') ); ?>" /></td> | ||
+ | </tr> | ||
+ | </table> | ||
+ | |||
+ | <?php submit_button(); ?> | ||
+ | |||
</form> | </form> | ||
</div> | </div> | ||
+ | <?php } ?> | ||
</pre> | </pre> | ||
− | + | ==== 例 #2 ==== | |
− | + | この例は WP 3.5.1 で動作します。より簡単なコードです。 [http://ottopress.com/2009/wordpress-settings-api-tutorial/ Otto's tutorial] を新しくしたものです。 | |
− | + | ||
<pre> | <pre> | ||
− | < | + | <?php |
− | + | class MySettingsPage | |
+ | { | ||
+ | /** | ||
+ | * Holds the values to be used in the fields callbacks | ||
+ | */ | ||
+ | private $options; | ||
− | + | /** | |
− | + | * Start up | |
+ | */ | ||
+ | public function __construct() | ||
+ | { | ||
+ | add_action( 'admin_menu', array( $this, 'add_plugin_page' ) ); | ||
+ | add_action( 'admin_init', array( $this, 'page_init' ) ); | ||
+ | } | ||
− | + | /** | |
+ | * Add options page | ||
+ | */ | ||
+ | public function add_plugin_page() | ||
+ | { | ||
+ | // This page will be under "Settings" | ||
+ | add_options_page( | ||
+ | 'Settings Admin', | ||
+ | 'My Settings', | ||
+ | 'manage_options', | ||
+ | 'my-setting-admin', | ||
+ | array( $this, 'create_admin_page' ) | ||
+ | ); | ||
+ | } | ||
− | + | /** | |
− | + | * Options page callback | |
− | + | */ | |
− | + | public function create_admin_page() | |
− | + | { | |
− | + | // Set class property | |
− | + | $this->options = get_option( 'my_option_name' ); | |
− | + | ?> | |
− | + | <div class="wrap"> | |
+ | <?php screen_icon(); ?> | ||
+ | <h2>My Settings</h2> | ||
+ | <form method="post" action="options.php"> | ||
+ | <?php | ||
+ | // This prints out all hidden setting fields | ||
+ | settings_fields( 'my_option_group' ); | ||
+ | do_settings_sections( 'my-setting-admin' ); | ||
+ | submit_button(); | ||
+ | ?> | ||
+ | </form> | ||
+ | </div> | ||
+ | <?php | ||
+ | } | ||
− | + | /** | |
− | + | * Register and add settings | |
− | + | */ | |
− | + | public function page_init() | |
− | + | { | |
− | + | register_setting( | |
+ | 'my_option_group', // Option group | ||
+ | 'my_option_name', // Option name | ||
+ | array( $this, 'sanitize' ) // Sanitize | ||
+ | ); | ||
− | + | add_settings_section( | |
− | + | 'setting_section_id', // ID | |
+ | 'My Custom Settings', // Title | ||
+ | array( $this, 'print_section_info' ), // Callback | ||
+ | 'my-setting-admin' // Page | ||
+ | ); | ||
− | + | add_settings_field( | |
− | + | 'id_number', // ID | |
− | + | 'ID Number', // Title | |
+ | array( $this, 'id_number_callback' ), // Callback | ||
+ | 'my-setting-admin', // Page | ||
+ | 'setting_section_id' // Section | ||
+ | ); | ||
− | </ | + | add_settings_field( |
− | </ | + | 'title', |
+ | 'Title', | ||
+ | array( $this, 'title_callback' ), | ||
+ | 'my-setting-admin', | ||
+ | 'setting_section_id' | ||
+ | ); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Sanitize each setting field as needed | ||
+ | * | ||
+ | * @param array $input Contains all settings fields as array keys | ||
+ | */ | ||
+ | public function sanitize( $input ) | ||
+ | { | ||
+ | $new_input = array(); | ||
+ | if( isset( $input['id_number'] ) ) | ||
+ | $new_input['id_number'] = absint( $input['id_number'] ); | ||
+ | |||
+ | if( isset( $input['title'] ) ) | ||
+ | $new_input['title'] = sanitize_text_field( $input['title'] ); | ||
+ | |||
+ | return $new_input; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Print the Section text | ||
+ | */ | ||
+ | public function print_section_info() | ||
+ | { | ||
+ | print 'Enter your settings below:'; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Get the settings option array and print one of its values | ||
+ | */ | ||
+ | public function id_number_callback() | ||
+ | { | ||
+ | printf( | ||
+ | '<input type="text" id="id_number" name="my_option_name[id_number]" value="%s" />', | ||
+ | isset( $this->options['id_number'] ) ? esc_attr( $this->options['id_number']) : '' | ||
+ | ); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Get the settings option array and print one of its values | ||
+ | */ | ||
+ | public function title_callback() | ||
+ | { | ||
+ | printf( | ||
+ | '<input type="text" id="title" name="my_option_name[title]" value="%s" />', | ||
+ | isset( $this->options['title'] ) ? esc_attr( $this->options['title']) : '' | ||
+ | ); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if( is_admin() ) | ||
+ | $my_settings_page = new MySettingsPage(); | ||
</pre> | </pre> | ||
+ | 以下のようなページを作成します。 | ||
+ | |||
+ | [[Image:creating-options-pages-ex-2b.png]] | ||
+ | |||
+ | ==== 落とし穴 ==== | ||
+ | ''register_setting()'' 関数の第二引数の「設定」名は、データベースで更新されるオプション名と同じでなけれななりません。 | ||
+ | <br /> | ||
+ | たとえば '''add_option( 'foo_bar', 'isfoo' )''' を使う場合、'''register_setting()''' 関数の第二引数は'''foo_bar''' でなければなりません。そうしないと、WordPress はどのオプションを更新してよいのか分からなくなります。 | ||
+ | |||
+ | To show the menu in '''Multisite''' screen, it would be a matter of doing:<br /> | ||
+ | <tt>add_action( is_multisite() ? 'network_admin_menu' : 'admin_menu', 'callback_function' );</tt><br /> | ||
+ | But the form save action leads to a 404 page: <tt>/wp-admin/network/options.php</tt>.<br /> | ||
+ | To solve it, use the solution in [http://wordpress.stackexchange.com/a/72503 this WordPress Answers post], or alternatively the one in [http://code.hyperspatial.com/1250/save-plugin-options-multisite-3-1/ this blog post]. | ||
+ | {{原文|Creating_Options_Pages|145513}}<!-- 08:03, 11 August 2014 Ounziw 版 --> | ||
[[Category:プラグイン]] | [[Category:プラグイン]] | ||
[[Category:WordPress の開発]] | [[Category:WordPress の開発]] | ||
[[Category:上級トピック]] | [[Category:上級トピック]] |
2015年8月15日 (土) 17:45時点における最新版
この記事は、 Version 2.7 で導入された Settings API に合わせて更新されています。2.7 より古いバージョンの場合は 履歴 をごらんください。
目次
はじめに
WordPressにカスタムの設定画面を作ることは比較的簡単です。
メニューアイテムと新しいページを作るには、まず 管理メニューの追加を見てください。
この構造に従う限りは、WordPressがあなたの代わりに作成、更新、保存、リダイレクトといった設定を行ってくれます。パーミッションをチェックし、裏側で起きているすべてを魔法のように執り行うのです。
WordPress 2.7 でいくつかの関数が追加されました。WordPress 2.7 時点では、これらの関数を使うかどうかは任意選択ですが、将来必須になるでしょう。WordPress MU 2.7 では必須です。詳細は Migrating Plugins and Themes to 2.7 と Settings API をごらんください。
この記事は、設定ページのマークアップのみを説明しています。設定ページの追懐については、 管理メニューをごらんください。
コードの保存先
オプションページのコードは、プラグインの PHP ファイル (テーマの場合は functions.php) 内に置くか、options.php のようなファイルを作成し、php の include 関数 - http://php.net/manual/en/function.include.php を使うことができます。
ページの開始
既存の WordPress オプションページの見た目に合わせたい場合、以下のように開始します。
<div class="wrap"> <h2>Your Plugin Page Title</h2>
Form タグ
ページを作ったら、HTMLフォームを作る必要があります。このコードを使ってください:
<form method="post" action="options.php">
settings_fields 関数
setting fields が、オプションページの設定を上手く処理してくれます。
開始 form タグの後、以下の関数を追加します。
settings_fields( 'myoption-group' );
ここで myoption-group は register_setting 関数で使用した名前と同じにします。
Version 2.7 以前では、nonce magic, action field, そして page_options field が必須でしたが、この関数が面倒みてくれます。
do_settings_fields 関数
settings_fields() を呼び出した後、以下の関数を追加します。
do_settings_sections( 'myoption-group' );
この関数は、フォームのマークアップ自体を面倒みてくれます。
終了タグ
それでは、その他の設定を入力して、formタグを閉じましょう。WordPressのデフォルトである"設定を更新"ボタンを使うこともできます。
<?php submit_button(); ?> </form> </div>
submit_button 関数でボタンを作成することができます。
テキストを翻訳対応にするためには、_e()関数を使うようにしてください。詳しくは WordPress の翻訳を参照してください。
Register Settings
register_setting 関数と unregister_setting 関数は、フォームが保存できるオプションのホワイトリストにオプションを追加/削除します。セキュリティのために、各オプションの値をチェックするコールバック関数を指定できます。
register_setting 関数は admin_init アクションフックで呼び出されるべきです。このフックは他の管理ページよりも先に呼び出され、このフォームを受け取る options.php よりも先に呼び出されます。
あなたのプラグインには、新しいメニューを追加する add_action セクションがあるかもしれません。This line will be in the same section to add an action to admin_init.
if ( is_admin() ){ // admin actions add_action( 'admin_menu', 'add_mymenu' ); add_action( 'admin_init', 'register_mysettings' ); } else { // non-admin enqueues, actions, and filters }
それから各オプションを登録する関数を作成します。
function register_mysettings() { // whitelist options register_setting( 'myoption-group', 'new_option_name' ); register_setting( 'myoption-group', 'some_other_option' ); register_setting( 'myoption-group', 'option_etc' ); }
myoption-group の名前はなんでも良いですが、上述の settings_fields 関数で使用する名前と同じにしてください。
すべてを纏める
注意: 例のいくつかは(とくに do_settings は) 古い書き方かもしれません。 View Otto's tutorial here for better examples of workable code. ほかにも ozh による article があります。
オプションページにアイコンを追加するには以下のコード [3.4.2 以降で使用可能] を用いてください。アイコンはテーマフォルダの "images" フォルダ内にあります。
<?php add_menu_page('BAW Plugin Settings', 'BAW Settings', 'administrator', __FILE__, 'baw_settings_page', get_stylesheet_directory_uri('stylesheet_directory')."/images/media-button-other.gif"); ?>
Settings API を使用してプラグインのオプションを作成/保存する例です。
<?php // create custom plugin settings menu add_action('admin_menu', 'baw_create_menu'); function baw_create_menu() { //create new top-level menu add_menu_page('BAW Plugin Settings', 'BAW Settings', 'administrator', __FILE__, 'baw_settings_page',plugins_url('/images/icon.png', __FILE__)); //call register settings function add_action( 'admin_init', 'register_mysettings' ); } function register_mysettings() { //register our settings register_setting( 'baw-settings-group', 'new_option_name' ); register_setting( 'baw-settings-group', 'some_other_option' ); register_setting( 'baw-settings-group', 'option_etc' ); } function baw_settings_page() { ?> <div class="wrap"> <h2>Your Plugin Name</h2> <form method="post" action="options.php"> <?php settings_fields( 'baw-settings-group' ); ?> <?php do_settings_sections( 'baw-settings-group' ); ?> <table class="form-table"> <tr valign="top"> <th scope="row">New Option Name</th> <td><input type="text" name="new_option_name" value="<?php echo esc_attr( get_option('new_option_name') ); ?>" /></td> </tr> <tr valign="top"> <th scope="row">Some Other Option</th> <td><input type="text" name="some_other_option" value="<?php echo esc_attr( get_option('some_other_option') ); ?>" /></td> </tr> <tr valign="top"> <th scope="row">Options, Etc.</th> <td><input type="text" name="option_etc" value="<?php echo esc_attr( get_option('option_etc') ); ?>" /></td> </tr> </table> <?php submit_button(); ?> </form> </div> <?php } ?>
例 #2
この例は WP 3.5.1 で動作します。より簡単なコードです。 Otto's tutorial を新しくしたものです。
<?php class MySettingsPage { /** * Holds the values to be used in the fields callbacks */ private $options; /** * Start up */ public function __construct() { add_action( 'admin_menu', array( $this, 'add_plugin_page' ) ); add_action( 'admin_init', array( $this, 'page_init' ) ); } /** * Add options page */ public function add_plugin_page() { // This page will be under "Settings" add_options_page( 'Settings Admin', 'My Settings', 'manage_options', 'my-setting-admin', array( $this, 'create_admin_page' ) ); } /** * Options page callback */ public function create_admin_page() { // Set class property $this->options = get_option( 'my_option_name' ); ?> <div class="wrap"> <?php screen_icon(); ?> <h2>My Settings</h2> <form method="post" action="options.php"> <?php // This prints out all hidden setting fields settings_fields( 'my_option_group' ); do_settings_sections( 'my-setting-admin' ); submit_button(); ?> </form> </div> <?php } /** * Register and add settings */ public function page_init() { register_setting( 'my_option_group', // Option group 'my_option_name', // Option name array( $this, 'sanitize' ) // Sanitize ); add_settings_section( 'setting_section_id', // ID 'My Custom Settings', // Title array( $this, 'print_section_info' ), // Callback 'my-setting-admin' // Page ); add_settings_field( 'id_number', // ID 'ID Number', // Title array( $this, 'id_number_callback' ), // Callback 'my-setting-admin', // Page 'setting_section_id' // Section ); add_settings_field( 'title', 'Title', array( $this, 'title_callback' ), 'my-setting-admin', 'setting_section_id' ); } /** * Sanitize each setting field as needed * * @param array $input Contains all settings fields as array keys */ public function sanitize( $input ) { $new_input = array(); if( isset( $input['id_number'] ) ) $new_input['id_number'] = absint( $input['id_number'] ); if( isset( $input['title'] ) ) $new_input['title'] = sanitize_text_field( $input['title'] ); return $new_input; } /** * Print the Section text */ public function print_section_info() { print 'Enter your settings below:'; } /** * Get the settings option array and print one of its values */ public function id_number_callback() { printf( '<input type="text" id="id_number" name="my_option_name[id_number]" value="%s" />', isset( $this->options['id_number'] ) ? esc_attr( $this->options['id_number']) : '' ); } /** * Get the settings option array and print one of its values */ public function title_callback() { printf( '<input type="text" id="title" name="my_option_name[title]" value="%s" />', isset( $this->options['title'] ) ? esc_attr( $this->options['title']) : '' ); } } if( is_admin() ) $my_settings_page = new MySettingsPage();
以下のようなページを作成します。
落とし穴
register_setting() 関数の第二引数の「設定」名は、データベースで更新されるオプション名と同じでなけれななりません。
たとえば add_option( 'foo_bar', 'isfoo' ) を使う場合、register_setting() 関数の第二引数はfoo_bar でなければなりません。そうしないと、WordPress はどのオプションを更新してよいのか分からなくなります。
To show the menu in Multisite screen, it would be a matter of doing:
add_action( is_multisite() ? 'network_admin_menu' : 'admin_menu', 'callback_function' );
But the form save action leads to a 404 page: /wp-admin/network/options.php.
To solve it, use the solution in this WordPress Answers post, or alternatively the one in this blog post.