{"id":20874,"date":"2026-10-14T18:52:00","date_gmt":"2026-10-14T16:52:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?p=20874"},"modified":"2026-10-09T22:41:08","modified_gmt":"2026-10-09T20:41:08","slug":"strony-ustawien-settings-api-register-setting","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/","title":{"rendered":"Strony ustawie\u0144 wtyczki z Settings API i register_setting"},"content":{"rendered":"<p>Prawie ka\u017cda wtyczka potrzebuje strony, na kt\u00f3rej administrator mo\u017ce zmieni\u0107 kilka warto\u015bci. Zaskakuj\u0105co wiele wtyczek wci\u0105\u017c buduje j\u0105 r\u0119cznie: w\u0142asna obs\u0142uga \u017c\u0105dania POST, sprawdzenie uprawnie\u0144 w jednym miejscu, zapomniany Nonce w innym i kilkana\u015bcie osobnych wierszy w <code>wp_options<\/code>. WordPress od wersji 2.7 udost\u0119pnia do tego Settings API. Interfejs ten wy\u015bwietla formularz w znanym uk\u0142adzie panelu administracyjnego i wysy\u0142a dane do <code>wp-admin\/options.php<\/code>, gdzie rdze\u0144 sprawdza Nonce i uprawnienia, oczyszcza dane oraz je zapisuje. Od WordPressa 4.7 funkcja <code>register_setting()<\/code> opisuje ponadto same dane: typ, warto\u015b\u0107 domy\u015bln\u0105, callback oczyszczaj\u0105cy oraz, dzi\u0119ki <code>show_in_rest<\/code>, widoczno\u015b\u0107 w punkcie ko\u0144cowym REST <code>\/wp\/v2\/settings<\/code>.<\/p>\n<p>W tym artykule powstaje ma\u0142a, ale kompletna wtyczka \u201eLW Settings Demo\u201d: pasek komunikatu, kt\u00f3rego trzy ustawienia s\u0105 zebrane w jednej opcji, strona w menu \u201eUstawienia\u201d, callback oczyszczaj\u0105cy obs\u0142uguj\u0105cy zar\u00f3wno formularz, jak i REST API, oraz kr\u00f3tki skrypt, kt\u00f3ry t\u0119 sam\u0105 opcj\u0119 odczytuje i zapisuje przez <code>apiFetch<\/code>. Po drodze da si\u0119 prze\u015bledzi\u0107 drog\u0119 pojedynczego pola formularza od elementu wej\u015bciowego a\u017c do wiersza w <code>wp_options<\/code> i zobaczy\u0107, w kt\u00f3rym miejscu \u015bcie\u017cka REST biegnie inaczej. Kod \u017ar\u00f3d\u0142owy rdzenia przeczytano 29.09.2026; wed\u0142ug sprawdzenia wersji na WordPress.org aktualne wydanie to 7.1.2, a przyk\u0142ad wymaga co najmniej WordPressa 6.6.<\/p>\n<h2>Cztery zadania, cztery grupy funkcji<\/h2>\n<p>Settings API dzieli stron\u0119 ustawie\u0144 na wyra\u017anie rozdzielone zadania. Ka\u017cda grupa funkcji nale\u017cy do w\u0142asnego hooka. Pomieszanie ich to najcz\u0119stszy pow\u00f3d, dla kt\u00f3rego strona wy\u015bwietla si\u0119 poprawnie, ale niczego nie zapisuje.<\/p>\n<table>\n<thead>\n<tr>\n<th>Funkcja<\/th>\n<th>Hook<\/th>\n<th>Zadanie<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>add_options_page()<\/code><\/td>\n<td><code>admin_menu<\/code><\/td>\n<td>Pozycja w menu \u201eUstawienia\u201d, Capability decyduj\u0105ca o wy\u015bwietleniu pozycji<\/td>\n<\/tr>\n<tr>\n<td><code>register_setting()<\/code><\/td>\n<td><code>init<\/code> (wyja\u015bnienie ni\u017cej)<\/td>\n<td>Dopisuje opcj\u0119 do listy dozwolonych opcji grupy, do\u0142\u0105cza callback oczyszczaj\u0105cy, warto\u015b\u0107 domy\u015bln\u0105 i schemat REST<\/td>\n<\/tr>\n<tr>\n<td><code>add_settings_section()<\/code>, <code>add_settings_field()<\/code><\/td>\n<td><code>admin_init<\/code><\/td>\n<td>Uk\u0142ad: nag\u0142\u00f3wki, etykiety, callbacki wypisuj\u0105ce elementy formularza<\/td>\n<\/tr>\n<tr>\n<td><code>settings_fields()<\/code>, <code>do_settings_sections()<\/code><\/td>\n<td>Callback strony<\/td>\n<td>Ukryte pola z Nonce, a potem wszystkie sekcje i pola strony<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><code>add_options_page()<\/code> to cienka nak\u0142adka: wywo\u0142uje <code>add_submenu_page()<\/code> z <code>options-general.php<\/code> jako stron\u0105 nadrz\u0119dn\u0105. Przekazana tu Capability rozstrzyga o tym, czy pozycja pojawi si\u0119 w menu; u\u017cytkownik bez niej dostaje te\u017c status 403 przy bezpo\u015brednim otwarciu adresu strony. Docblock funkcji wprost zaznacza, \u017ce callback strony musi sam jeszcze raz sprawdzi\u0107 uprawnienia, dlatego funkcja renderuj\u0105ca w przyk\u0142adzie zaczyna si\u0119 od <code>current_user_can( 'manage_options' )<\/code>. Przy zapisie nast\u0119puje trzecia, osobna kontrola w <code>options.php<\/code>, co pokazuje sekcja o \u015bcie\u017cce zapisu.<\/p>\n<p>Formularz i zapis \u0142\u0105czy grupa opcji. <code>register_setting( 'lwsd_notice_bar', 'lwsd_settings', \u2026 )<\/code> przypisuje opcj\u0119 <code>lwsd_settings<\/code> do grupy <code>lwsd_notice_bar<\/code>, a <code>settings_fields( 'lwsd_notice_bar' )<\/code> wysy\u0142a w\u0142a\u015bnie t\u0119 nazw\u0119 grupy w ukrytym polu <code>option_page<\/code>. Identyfikator strony u\u017cywany przez <code>add_settings_section()<\/code> i <code>do_settings_sections()<\/code> to osobna nazwa; w przyk\u0142adzie pokrywa si\u0119 ze slugiem menu <code>lwsd-notice-bar<\/code>.<\/p>\n<h2>Jedna opcja zamiast kilkunastu<\/h2>\n<p>Plugin Handbook zaleca przechowywanie powi\u0105zanych warto\u015bci jako tablicy w jednej opcji, bo odczyt i zapis odbywaj\u0105 si\u0119 wtedy w jednej transakcji bazy danych, a nie w wielu. Kod <code>options.php<\/code> dostarcza drugiego, mniej oczywistego argumentu. Przy zapisie plik przechodzi przez <strong>wszystkie<\/strong> opcje zarejestrowane w przes\u0142anej grupie i dla ka\u017cdej wywo\u0142uje <code>update_option()<\/code>. Je\u015bli w danych POST brakuje pola, przekazywana jest warto\u015b\u0107 <code>null<\/code>. Dwa formularze w tej samej grupie nadpisuj\u0105 wi\u0119c nawzajem swoje warto\u015bci. Jedna opcja tablicowa na formularz usuwa t\u0119 pu\u0142apk\u0119, a callback oczyszczaj\u0105cy widzi wszystkie warto\u015bci jednocze\u015bnie. Dzi\u0119ki temu da si\u0119 sformu\u0142owa\u0107 regu\u0142y obejmuj\u0105ce kilka p\u00f3l, na przyk\u0142ad \u201ebrak aktywnego paska bez tre\u015bci komunikatu\u201d.<\/p>\n<p>Cen\u0105 jest serializacja: tablica trafia do jednego wiersza jako zserializowany ci\u0105g znak\u00f3w, a pojedynczych kluczy nie da si\u0119 filtrowa\u0107 w SQL. Przy warto\u015bciach konfiguracyjnych rzadko ma to znaczenie. Dla danych, kt\u00f3re trzeba przeszukiwa\u0107, alternatywy omawia <a href=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/tworzenie-stron-internetowych\/baza-danych-wordpressa-ograniczenia-wydajnosci-wp_postmeta-i-budowa\/\">artyku\u0142 o granicach wydajno\u015bci <code>wp_postmeta<\/code> i w\u0142asnych tabelach<\/a>.<\/p>\n<h3>\u015awiadome ustawienie autoload<\/h3>\n<p>WordPress 6.6 przebudowa\u0142 kolumn\u0119 autoload. Parametr <code>$autoload<\/code> funkcji <code>add_option()<\/code> ma od tej wersji domy\u015blnie warto\u015b\u0107 <code>null<\/code>. W kolumnie zapisywane s\u0105 <code>on<\/code> i <code>off<\/code> dla jawnych decyzji, <code>auto<\/code>, gdy nikt nie zdecydowa\u0142, oraz <code>auto-on<\/code> lub <code>auto-off<\/code>, gdy decyzj\u0119 dynamicznie podj\u0105\u0142 filtr. Stare warto\u015bci <code>yes<\/code> i <code>no<\/code> s\u0105 od 6.7 oznaczone jako przestarza\u0142e. Opcje wi\u0119ksze ni\u017c 150 000 bajt\u00f3w domy\u015blnie nie s\u0105 \u0142adowane automatycznie (filtr <code>wp_max_autoloaded_option_size<\/code>). Wed\u0142ug <code>wp_autoload_values_to_autoload()<\/code> warto\u015b\u0107 <code>auto<\/code> jest obecnie nadal \u0142adowana, jednak notatka deweloperska do 6.6 zastrzega, \u017ce ta domy\u015blna regu\u0142a mo\u017ce si\u0119 w przysz\u0142ych wersjach zmieni\u0107.<\/p>\n<p>Dla Settings API ma to znaczenie, poniewa\u017c <code>options.php<\/code> wywo\u0142uje <code>update_option()<\/code> bez argumentu autoload. Je\u015bli opcja jeszcze nie istnieje, <code>update_option()<\/code> wywo\u0142uje <code>add_option()<\/code>, a wiersz powstaje z warto\u015bci\u0105 <code>auto<\/code>. Aby jawnie ustawi\u0107 autoload, nale\u017cy utworzy\u0107 opcj\u0119 samodzielnie. Przyk\u0142ad robi to przy aktywacji za pomoc\u0105 <code>add_option( \u2026, true )<\/code>, poniewa\u017c pasek komunikatu jest odczytywany przy ka\u017cdym \u017c\u0105daniu frontendu.<\/p>\n<p>P\u00f3\u017aniejsze wywo\u0142ania <code>update_option()<\/code> bez argumentu autoload zachowuj\u0105 jawne <code>on<\/code> lub <code>off<\/code>; ponownie oceniane s\u0105 tylko warianty <code>auto<\/code>. Opcja potrzebna tylko na jednej stronie panelu dosta\u0142aby natomiast <code>false<\/code>.<\/p>\n<p>P\u00f3\u017aniej mo\u017cna zmieni\u0107 autoload za pomoc\u0105 <code>wp_set_option_autoload()<\/code> (od 6.4), bez zmiany zapisanej warto\u015bci opcji. Natomiast <code>update_option()<\/code> przyjmuje now\u0105 warto\u015b\u0107 autoload tylko wtedy, gdy zmienia si\u0119 r\u00f3wnie\u017c tre\u015b\u0107 opcji. Znaczenie poszczeg\u00f3lnych warto\u015bci kolumny w praktyce om\u00f3wi <span class=\"lw-artikel-geplant\">osobny, zaplanowany artyku\u0142 o autoload<\/span>.<\/p>\n<h2>Kompletna wtyczka<\/h2>\n<p>Plik g\u0142\u00f3wny zawiera wszystko: rejestracj\u0119, stron\u0119, pola, callback oczyszczaj\u0105cy, wyj\u015bcie na frontendzie i aktywacj\u0119. Prefiks <code>lwsd_<\/code> obowi\u0105zuje konsekwentnie dla funkcji, sta\u0142ych, opcji i identyfikator\u00f3w HTML.<\/p>\n<pre><code>&lt;?php\n\/**\n * Plugin Name:       LW Settings Demo\n * Description:       Notice bar with a settings page built on the Settings API, also available via \/wp\/v2\/settings.\n * Version:           1.0.0\n * Requires at least: 6.6\n * Requires PHP:      7.4\n * Author:            Lukas Wojcik\n * License:           GPL-2.0-or-later\n * License URI:       https:\/\/www.gnu.org\/licenses\/gpl-2.0.html\n * Text Domain:       lw-settings-demo\n *\n * @package LW_Settings_Demo\n *\/\n\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n\nconst LWSD_OPTION = 'lwsd_settings';   \/\/ Row in wp_options.\nconst LWSD_GROUP  = 'lwsd_notice_bar'; \/\/ Option group, sent as option_page.\nconst LWSD_PAGE   = 'lwsd-notice-bar'; \/\/ Menu slug and settings page ID.\n\n\/**\n * Default values of the bundled option.\n *\n * @return array\n *\/\nfunction lwsd_default_settings() {\n\treturn array(\n\t\t'enabled'  =&gt; false,\n\t\t'message'  =&gt; '',\n\t\t'position' =&gt; 'bottom',\n\t);\n}\n\n\/**\n * Returns the stored settings merged with the defaults.\n *\n * @return array\n *\/\nfunction lwsd_get_settings() {\n\t$settings = get_option( LWSD_OPTION );\n\n\tif ( ! is_array( $settings ) ) {\n\t\t$settings = array();\n\t}\n\n\treturn wp_parse_args( $settings, lwsd_default_settings() );\n}\n\n\/**\n * Registers the option on init, so admin screens and REST requests both know it.\n *\/\nfunction lwsd_register_setting() {\n\tregister_setting(\n\t\tLWSD_GROUP,\n\t\tLWSD_OPTION,\n\t\tarray(\n\t\t\t'type'              =&gt; 'object',\n\t\t\t'label'             =&gt; __( 'Notice bar', 'lw-settings-demo' ),\n\t\t\t'description'       =&gt; __( 'Visibility, text and position of the notice bar.', 'lw-settings-demo' ),\n\t\t\t'sanitize_callback' =&gt; 'lwsd_sanitize_settings',\n\t\t\t'default'           =&gt; lwsd_default_settings(),\n\t\t\t'show_in_rest'      =&gt; array(\n\t\t\t\t'schema' =&gt; array(\n\t\t\t\t\t'type'       =&gt; 'object',\n\t\t\t\t\t'properties' =&gt; array(\n\t\t\t\t\t\t'enabled'  =&gt; array(\n\t\t\t\t\t\t\t'type' =&gt; 'boolean',\n\t\t\t\t\t\t),\n\t\t\t\t\t\t'message'  =&gt; array(\n\t\t\t\t\t\t\t'type'      =&gt; 'string',\n\t\t\t\t\t\t\t'maxLength' =&gt; 200,\n\t\t\t\t\t\t),\n\t\t\t\t\t\t'position' =&gt; array(\n\t\t\t\t\t\t\t'type' =&gt; 'string',\n\t\t\t\t\t\t\t'enum' =&gt; array( 'top', 'bottom' ),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t)\n\t);\n}\nadd_action( 'init', 'lwsd_register_setting' );\n\n\/**\n * Sanitizes the whole settings array.\n *\n * Runs for options.php and for REST writes, because both end in update_option().\n * Must be idempotent: on the first save of a missing option it runs twice.\n *\n * @param mixed $input Raw value.\n * @return array\n *\/\nfunction lwsd_sanitize_settings( $input ) {\n\t$defaults = lwsd_default_settings();\n\n\tif ( ! is_array( $input ) ) {\n\t\treturn $defaults;\n\t}\n\n\t$message  = isset( $input['message'] ) ? sanitize_text_field( $input['message'] ) : '';\n\t$position = isset( $input['position'] ) ? sanitize_key( $input['position'] ) : '';\n\n\t$output = array(\n\t\t'enabled'  =&gt; ! empty( $input['enabled'] ),\n\t\t'message'  =&gt; mb_substr( $message, 0, 200 ),\n\t\t'position' =&gt; in_array( $position, array( 'top', 'bottom' ), true ) ? $position : $defaults['position'],\n\t);\n\n\tif ( $output['enabled'] &amp;&amp; '' === $output['message'] ) {\n\t\t$output['enabled'] = false;\n\n\t\t\/\/ add_settings_error() lives in wp-admin\/includes\/template.php,\n\t\t\/\/ which a REST request does not load.\n\t\tif ( function_exists( 'add_settings_error' ) ) {\n\t\t\tadd_settings_error(\n\t\t\t\tLWSD_OPTION,\n\t\t\t\t'lwsd_empty_message',\n\t\t\t\t__( 'The notice bar stays off until a message is entered.', 'lw-settings-demo' ),\n\t\t\t\t'warning'\n\t\t\t);\n\t\t}\n\t}\n\n\treturn $output;\n}\n\n\/**\n * Adds the page below Settings and loads its script only there.\n *\/\nfunction lwsd_add_settings_page() {\n\t$hook_suffix = add_options_page(\n\t\t__( 'Notice bar', 'lw-settings-demo' ),\n\t\t__( 'Notice bar', 'lw-settings-demo' ),\n\t\t'manage_options',\n\t\tLWSD_PAGE,\n\t\t'lwsd_render_settings_page'\n\t);\n\n\tif ( $hook_suffix ) {\n\t\tadd_action( 'load-' . $hook_suffix, 'lwsd_load_settings_page' );\n\t}\n}\nadd_action( 'admin_menu', 'lwsd_add_settings_page' );\n\n\/**\n * Runs only when the settings page is requested.\n *\/\nfunction lwsd_load_settings_page() {\n\tadd_action( 'admin_enqueue_scripts', 'lwsd_enqueue_admin_script' );\n}\n\n\/**\n * Enqueues the REST demo script.\n *\/\nfunction lwsd_enqueue_admin_script() {\n\twp_enqueue_script(\n\t\t'lwsd-settings-rest',\n\t\tplugins_url( 'js\/settings-rest.js', __FILE__ ),\n\t\tarray( 'wp-api-fetch', 'wp-i18n' ),\n\t\t'1.0.0',\n\t\tarray( 'in_footer' =&gt; true )\n\t);\n\twp_set_script_translations( 'lwsd-settings-rest', 'lw-settings-demo' );\n}\n\n\/**\n * Declares section and fields. Only needed on admin screens.\n *\/\nfunction lwsd_register_fields() {\n\tadd_settings_section(\n\t\t'lwsd_section_main',\n\t\t__( 'Display', 'lw-settings-demo' ),\n\t\t'lwsd_render_section',\n\t\tLWSD_PAGE\n\t);\n\n\tadd_settings_field(\n\t\t'lwsd_enabled',\n\t\t__( 'Show notice bar', 'lw-settings-demo' ),\n\t\t'lwsd_render_enabled_field',\n\t\tLWSD_PAGE,\n\t\t'lwsd_section_main',\n\t\tarray( 'label_for' =&gt; 'lwsd_enabled' )\n\t);\n\n\tadd_settings_field(\n\t\t'lwsd_message',\n\t\t__( 'Message', 'lw-settings-demo' ),\n\t\t'lwsd_render_message_field',\n\t\tLWSD_PAGE,\n\t\t'lwsd_section_main',\n\t\tarray( 'label_for' =&gt; 'lwsd_message' )\n\t);\n\n\tadd_settings_field(\n\t\t'lwsd_position',\n\t\t__( 'Position', 'lw-settings-demo' ),\n\t\t'lwsd_render_position_field',\n\t\tLWSD_PAGE,\n\t\t'lwsd_section_main',\n\t\tarray( 'label_for' =&gt; 'lwsd_position' )\n\t);\n}\nadd_action( 'admin_init', 'lwsd_register_fields' );\n\n\/**\n * Section intro.\n *\/\nfunction lwsd_render_section() {\n\techo '&lt;p&gt;' . esc_html__( 'All three values are stored together in one option.', 'lw-settings-demo' ) . '&lt;\/p&gt;';\n}\n\n\/**\n * Checkbox field.\n *\/\nfunction lwsd_render_enabled_field() {\n\t$settings = lwsd_get_settings();\n\n\tprintf(\n\t\t'&lt;input type=\"checkbox\" id=\"lwsd_enabled\" name=\"%1$s[enabled]\" value=\"1\" %2$s \/&gt;',\n\t\tesc_attr( LWSD_OPTION ),\n\t\tchecked( $settings['enabled'], true, false )\n\t);\n}\n\n\/**\n * Text field.\n *\/\nfunction lwsd_render_message_field() {\n\t$settings = lwsd_get_settings();\n\n\tprintf(\n\t\t'&lt;input type=\"text\" class=\"regular-text\" id=\"lwsd_message\" name=\"%1$s[message]\" value=\"%2$s\" maxlength=\"200\" \/&gt;',\n\t\tesc_attr( LWSD_OPTION ),\n\t\tesc_attr( $settings['message'] )\n\t);\n}\n\n\/**\n * Select field.\n *\/\nfunction lwsd_render_position_field() {\n\t$settings = lwsd_get_settings();\n\t$choices  = array(\n\t\t'top'    =&gt; __( 'Top of the page', 'lw-settings-demo' ),\n\t\t'bottom' =&gt; __( 'Bottom of the page', 'lw-settings-demo' ),\n\t);\n\n\tprintf( '&lt;select id=\"lwsd_position\" name=\"%s[position]\"&gt;', esc_attr( LWSD_OPTION ) );\n\n\tforeach ( $choices as $value =&gt; $label ) {\n\t\tprintf(\n\t\t\t'&lt;option value=\"%1$s\" %2$s&gt;%3$s&lt;\/option&gt;',\n\t\t\tesc_attr( $value ),\n\t\t\tselected( $settings['position'], $value, false ),\n\t\t\tesc_html( $label )\n\t\t);\n\t}\n\n\techo '&lt;\/select&gt;';\n}\n\n\/**\n * Settings page. The form posts to options.php, not to this page.\n *\/\nfunction lwsd_render_settings_page() {\n\tif ( ! current_user_can( 'manage_options' ) ) {\n\t\treturn;\n\t}\n\t?&gt;\n\t&lt;div class=\"wrap\"&gt;\n\t\t&lt;h1&gt;&lt;?php echo esc_html( get_admin_page_title() ); ?&gt;&lt;\/h1&gt;\n\t\t&lt;form action=\"options.php\" method=\"post\"&gt;\n\t\t\t&lt;?php\n\t\t\tsettings_fields( LWSD_GROUP );\n\t\t\tdo_settings_sections( LWSD_PAGE );\n\t\t\tsubmit_button();\n\t\t\t?&gt;\n\t\t&lt;\/form&gt;\n\t\t&lt;p&gt;\n\t\t\t&lt;button type=\"button\" class=\"button\" id=\"lwsd-rest-toggle\"&gt;&lt;?php esc_html_e( 'Toggle via REST API', 'lw-settings-demo' ); ?&gt;&lt;\/button&gt;\n\t\t\t&lt;span id=\"lwsd-rest-status\" aria-live=\"polite\"&gt;&lt;\/span&gt;\n\t\t&lt;\/p&gt;\n\t&lt;\/div&gt;\n\t&lt;?php\n}\n\n\/**\n * Prints the notice bar on the front end.\n *\n * @param string $position Where the calling hook prints: top or bottom.\n *\/\nfunction lwsd_print_notice( $position ) {\n\t$settings = lwsd_get_settings();\n\n\tif ( ! $settings['enabled'] || $position !== $settings['position'] || '' === $settings['message'] ) {\n\t\treturn;\n\t}\n\n\tprintf(\n\t\t'&lt;div class=\"lwsd-notice lwsd-notice-%1$s\" role=\"status\"&gt;%2$s&lt;\/div&gt;',\n\t\tesc_attr( $position ),\n\t\tesc_html( $settings['message'] )\n\t);\n}\n\n\/**\n * Top position, needs a theme that calls wp_body_open().\n *\/\nfunction lwsd_print_top_notice() {\n\tlwsd_print_notice( 'top' );\n}\nadd_action( 'wp_body_open', 'lwsd_print_top_notice' );\n\n\/**\n * Bottom position.\n *\/\nfunction lwsd_print_bottom_notice() {\n\tlwsd_print_notice( 'bottom' );\n}\nadd_action( 'wp_footer', 'lwsd_print_bottom_notice' );\n\n\/**\n * Creates the option with an explicit autoload value.\n *\/\nfunction lwsd_activate() {\n\t\/\/ Read on every front-end request, so autoload it on purpose.\n\tadd_option( LWSD_OPTION, lwsd_default_settings(), '', true );\n}\nregister_activation_hook( __FILE__, 'lwsd_activate' );<\/code><\/pre>\n<h3>Dlaczego register_setting dzia\u0142a na hooku init<\/h3>\n<p>Przyk\u0142ad w Plugin Handbook rejestruje ustawienia na hooku <code>admin_init<\/code>. Ten hook jest wywo\u0142ywany w <code>wp-admin\/admin.php<\/code>, a \u017c\u0105danie REST do <code>\/wp-json\/<\/code> nigdy nie \u0142aduje tego pliku. Ustawienie zarejestrowane tylko tam dzia\u0142a w formularzu, ale nie pojawia si\u0119 w <code>\/wp\/v2\/settings<\/code>. Rdze\u0144 rejestruje w\u0142asne ustawienia na <code>rest_api_init<\/code>, a przyk\u0142ad z WordPress Developer Blog dla stron ustawie\u0144 opartych na React korzysta z <code>init<\/code>. Wtyczka idzie t\u0105 drug\u0105 drog\u0105: <code>init<\/code> obejmuje <code>options.php<\/code>, stron\u0119 ustawie\u0144, \u017c\u0105dania REST oraz frontend, gdzie dodatkowo dzia\u0142a zarejestrowana warto\u015b\u0107 domy\u015blna. Sekcje i pola to natomiast czysty uk\u0142ad panelu i zostaj\u0105 na <code>admin_init<\/code>.<\/p>\n<h3>Jeden callback oczyszczaj\u0105cy dla dw\u00f3ch \u015bcie\u017cek<\/h3>\n<p><code>register_setting()<\/code> podpina callback pod filtr <code>sanitize_option_lwsd_settings<\/code>. Filtr ten stosuje <code>sanitize_option()<\/code>, kt\u00f3r\u0105 <code>update_option()<\/code> wywo\u0142uje przy ka\u017cdym zapisie, niezale\u017cnie od tego, czy warto\u015b\u0107 pochodzi z <code>options.php<\/code>, czy z REST API. Ma to dwie konsekwencje.<\/p>\n<p>Po pierwsze, <code>add_settings_error()<\/code> jest zdefiniowana w <code>wp-admin\/includes\/template.php<\/code>, pliku, kt\u00f3rego zwyk\u0142e \u017c\u0105danie REST nie \u0142aduje. Sprawdzenie przez <code>function_exists()<\/code> pozwala wi\u0119c ustali\u0107, czy funkcja jest dost\u0119pna przed jej wywo\u0142aniem. Po drugie, callback musi by\u0107 idempotentny: ponowne zastosowanie go do w\u0142asnego wyniku musi da\u0107 ten sam wynik. Gdy opcji brakuje, <code>update_option()<\/code> oczyszcza warto\u015b\u0107 raz, a <code>add_option()<\/code> drugi raz. Utworzenie wiersza przy aktywacji zapobiega temu podw\u00f3jnemu przebiegowi w normalnej pracy, ale callback nie powinien na tym polega\u0107.<\/p>\n<h3>Bez wywo\u0142ania settings_errors() na stronie<\/h3>\n<p>Dla stron w menu \u201eUstawienia\u201d plik <code>admin-header.php<\/code> do\u0142\u0105cza <code>options-head.php<\/code>, a ten sam wywo\u0142uje <code>settings_errors()<\/code>. Dodatkowe wywo\u0142anie w callbacku strony wypisa\u0142oby ka\u017cdy komunikat dwukrotnie. Przyk\u0142ad z Handbooka u\u017cywa strony menu najwy\u017cszego poziomu i dlatego wywo\u0142uje <code>settings_errors()<\/code> samodzielnie. Jeszcze jeden szczeg\u00f3\u0142 z <code>options.php<\/code>: komunikat o zapisaniu ustawie\u0144 dodawany jest tylko wtedy, gdy nie zarejestrowano \u017cadnego innego. Ostrze\u017cenie z callbacku oczyszczaj\u0105cego zast\u0119puje go, cho\u0107 pozosta\u0142e warto\u015bci zosta\u0142y zapisane.<\/p>\n<h2>Co dzieje si\u0119 przy zapisie<\/h2>\n<p>Formularz wysy\u0142a dane do <code>options.php<\/code>, a nie do strony ustawie\u0144. Poni\u017csze kroki pochodz\u0105 bezpo\u015brednio z kodu rdzenia i dotycz\u0105 ka\u017cdej strony zbudowanej na Settings API.<\/p>\n<figure class=\"lw-diagram\">\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/diagrams\/wp-settings-api-pl.png?v=20260930\" width=\"1120\" height=\"580\" alt=\"Od pola formularza do wp_options: \u015bcie\u017cka zapisu w Settings API\"><figcaption>options.php sprawdza Capability, Nonce i list\u0119 dozwolonych; REST do\u0142\u0105cza przy update_option(), gdzie dzia\u0142a callback<\/figcaption><\/figure>\n<ol>\n<li><code>settings_fields()<\/code> wypisuje cztery ukryte pola: <code>option_page<\/code> z nazw\u0105 grupy, <code>action<\/code> z warto\u015bci\u0105 <code>update<\/code>, Nonce <code>_wpnonce<\/code> dla akcji <code>lwsd_notice_bar-options<\/code> oraz <code>_wp_http_referer<\/code> z adresem, na kt\u00f3ry <code>options.php<\/code> przekierowuje po zapisie.<\/li>\n<li><code>options.php<\/code> ustala wymagan\u0105 Capability: <code>manage_options<\/code>, z mo\u017cliwo\u015bci\u0105 zmiany przez filtr <code>option_page_capability_{$option_page}<\/code>. Bez niej \u017c\u0105danie ko\u0144czy si\u0119 statusem 403.<\/li>\n<li><code>check_admin_referer( $option_page . '-options' )<\/code> weryfikuje Nonce.<\/li>\n<li>Grupa musi znajdowa\u0107 si\u0119 na li\u015bcie dozwolonych, kt\u00f3r\u0105 wype\u0142nia <code>register_setting()<\/code>, a rozszerza filtr <code>allowed_options<\/code>. W przeciwnym razie <code>wp_die()<\/code> przerywa \u017c\u0105danie.<\/li>\n<li>Dla ka\u017cdej zarejestrowanej opcji warto\u015b\u0107 jest odczytywana z <code>$_POST<\/code>, przycinana, je\u015bli jest skalarna, przepuszczana przez <code>wp_unslash()<\/code> i przekazywana do <code>update_option()<\/code>.<\/li>\n<li><code>update_option()<\/code> uruchamia <code>sanitize_option()<\/code>, a wi\u0119c callback, potem filtry <code>pre_update_option<\/code>. Je\u015bli warto\u015b\u0107 si\u0119 nie zmieni\u0142a, nic nie jest zapisywane; w przeciwnym razie zserializowana warto\u015b\u0107 trafia do wiersza.<\/li>\n<li>Zebrane komunikaty trafiaj\u0105 na 30 sekund do transientu <code>settings_errors<\/code>, po czym nast\u0119puje przekierowanie z <code>settings-updated=true<\/code>. Po przekierowaniu <code>settings_errors()<\/code> odczytuje transient i wy\u015bwietla komunikaty.<\/li>\n<\/ol>\n<p>Krok drugi ma praktyczn\u0105 konsekwencj\u0119. Wtyczka, kt\u00f3ra pokazuje swoj\u0105 pozycj\u0119 menu redaktorom z uprawnieniem <code>edit_pages<\/code>, nie zapisze ustawie\u0144, dop\u00f3ki filtr <code>option_page_capability_lwsd_notice_bar<\/code> nadal wymaga <code>manage_options<\/code>. Wy\u015bwietlanie menu, callback strony i zapis musz\u0105 wymaga\u0107 tego samego uprawnienia. Dlaczego sam Nonce nigdy nie zast\u0119puje sprawdzenia uprawnie\u0144, wyja\u015bnia szczeg\u00f3\u0142owo <a href=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/sanityzacja-escaping-nonce-capability-wtyczki\/\">osobny artyku\u0142 tej serii o sanitizacji, escapowaniu, Nonce i Capabilities<\/a>.<\/p>\n<h2>register_setting a punkt ko\u0144cowy \/wp\/v2\/settings<\/h2>\n<p>Zarejestrowane ustawienia domy\u015blnie nie pojawiaj\u0105 si\u0119 w REST API. Dla typ\u00f3w skalarnych wystarczy <code>show_in_rest<\/code> z warto\u015bci\u0105 <code>true<\/code>. Przy <code>array<\/code> i <code>object<\/code> opcja potrzebuje schematu w <code>show_in_rest.schema<\/code>: dla tablic bez <code>items<\/code> rdze\u0144 zg\u0142asza komunikat <code>_doing_it_wrong<\/code> (od 5.4), a dla obiekt\u00f3w <code>properties<\/code> okre\u015blaj\u0105, jakie klucze istniej\u0105. Kontroler buduje ostateczny schemat z <code>type<\/code>, <code>label<\/code> (jako <code>title<\/code>), <code>description<\/code> i <code>default<\/code>, a nast\u0119pnie nak\u0142ada na niego schemat z <code>show_in_rest<\/code>. Akceptowane s\u0105 wy\u0142\u0105cznie typy <code>number<\/code>, <code>integer<\/code>, <code>string<\/code>, <code>boolean<\/code>, <code>array<\/code> i <code>object<\/code>; pozosta\u0142e ustawienia s\u0105 po cichu pomijane.<\/p>\n<p>Kontroler w <code>class-wp-rest-settings-controller.php<\/code> odpowiada na kilka pyta\u0144, kt\u00f3re strony referencyjne pozostawiaj\u0105 otwarte:<\/p>\n<ul>\n<li><strong>Uprawnienia:<\/strong> zar\u00f3wno odczyt, jak i zapis wymagaj\u0105 <code>manage_options<\/code>. Punkt ko\u0144cowy nie nadaje si\u0119 wi\u0119c do przekazywania ustawie\u0144 anonimowym odwiedzaj\u0105cym; do tego potrzebna jest osobna trasa z w\u0142asnym <code>permission_callback<\/code>.<\/li>\n<li><strong>Nazwa:<\/strong> klucz w odpowiedzi odpowiada nazwie opcji, chyba \u017ce <code>show_in_rest<\/code> ustawia inne <code>name<\/code>.<\/li>\n<li><strong>\u015acis\u0142e obiekty:<\/strong> kontroler rekurencyjnie dodaje <code>additionalProperties: false<\/code> do ka\u017cdego obiektu bez w\u0142asnej regu\u0142y. Nieznane klucze w \u017c\u0105daniu s\u0105 odrzucane. Je\u015bli zapisana warto\u015b\u0107 zawiera klucze nieznane schematowi, na przyk\u0142ad pozosta\u0142e po starszej wersji wtyczki, GET zwraca <code>null<\/code> dla ca\u0142ego ustawienia.<\/li>\n<li><strong>Zast\u0105pienie zamiast scalenia:<\/strong> POST przekazuje wys\u0142any obiekt bez zmian do <code>update_option()<\/code>. Brakuj\u0105ce w\u0142a\u015bciwo\u015bci nie s\u0105 zachowywane; w przyk\u0142adzie callback oczyszczaj\u0105cy uzupe\u0142nia je warto\u015bciami domy\u015blnymi, a <code>enabled<\/code> po cichu zmienia si\u0119 na <code>false<\/code>.<\/li>\n<li><strong>null usuwa:<\/strong> warto\u015b\u0107 <code>null<\/code> wywo\u0142uje <code>delete_option()<\/code>, chyba \u017ce zapisana warto\u015b\u0107 jest nieprawid\u0142owa; wtedy kontroler odmawia z kodem <code>rest_invalid_stored_value<\/code> i statusem 500.<\/li>\n<li><strong>Odpowied\u017a:<\/strong> po aktualizacji kontroler ponownie wywo\u0142uje <code>get_item()<\/code>. Odpowied\u017a pokazuje zatem warto\u015b\u0107 po oczyszczeniu, a nie wys\u0142an\u0105.<\/li>\n<\/ul>\n<h2>Odczyt i zapis przez apiFetch<\/h2>\n<p>Skrypt znajduje si\u0119 w <code>js\/settings-rest.js<\/code> i jest \u0142adowany wy\u0142\u0105cznie na stronie ustawie\u0144: wtyczka podpina <code>admin_enqueue_scripts<\/code> dopiero w hooku <code>load-{$hook_suffix}<\/code>, kt\u00f3rego sufiks zwraca <code>add_options_page()<\/code>. Do uwierzytelnienia wystarcza zale\u017cno\u015b\u0107 <code>wp-api-fetch<\/code>. Rdze\u0144 rejestruje dla tego uchwytu dwa skrypty inline, jeden z bazowym adresem REST API i jeden z middleware dla Nonce. \u017b\u0105danie niesie wi\u0119c bez dodatkowego kodu Nonce <code>wp_rest<\/code> pasuj\u0105cy do ciasteczka logowania.<\/p>\n<pre><code>\/* global wp *\/\n( function () {\n\t'use strict';\n\n\tconst { __ } = wp.i18n;\n\tconst button = document.getElementById( 'lwsd-rest-toggle' );\n\tconst status = document.getElementById( 'lwsd-rest-status' );\n\n\tif ( ! button || ! status ) {\n\t\treturn;\n\t}\n\n\tbutton.addEventListener( 'click', async () =&gt; {\n\t\tbutton.disabled = true;\n\n\t\ttry {\n\t\t\t\/\/ GET returns every setting registered with show_in_rest, keyed by name.\n\t\t\tconst settings = await wp.apiFetch( { path: '\/wp\/v2\/settings' } );\n\t\t\tconst current = settings.lwsd_settings;\n\n\t\t\tif ( ! current ) {\n\t\t\t\t\/\/ null: the stored value does not match the registered schema.\n\t\t\t\tstatus.textContent = __( 'Stored value does not match the schema.', 'lw-settings-demo' );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t\/\/ The endpoint replaces the whole object, so send every property.\n\t\t\tconst saved = await wp.apiFetch( {\n\t\t\t\tpath: '\/wp\/v2\/settings',\n\t\t\t\tmethod: 'POST',\n\t\t\t\tdata: {\n\t\t\t\t\tlwsd_settings: { ...current, enabled: ! current.enabled },\n\t\t\t\t},\n\t\t\t} );\n\n\t\t\t\/\/ The response already contains the sanitized value.\n\t\t\tstatus.textContent = saved.lwsd_settings.enabled\n\t\t\t\t? __( 'Notice bar is on.', 'lw-settings-demo' )\n\t\t\t\t: __( 'Notice bar is off.', 'lw-settings-demo' );\n\t\t} catch ( error ) {\n\t\t\tstatus.textContent = error.message || __( 'Request failed.', 'lw-settings-demo' );\n\t\t} finally {\n\t\t\tbutton.disabled = false;\n\t\t}\n\t} );\n} )();<\/code><\/pre>\n<p>Przycisk odczytuje ca\u0142y obiekt ustawie\u0144, odwraca <code>enabled<\/code> i odsy\u0142a obiekt w komplecie. Odpowied\u017a ilustruje punkt z poprzedniej sekcji: przy pustym polu komunikatu callback oczyszczaj\u0105cy z powrotem wy\u0142\u0105cza pasek, a wiersz statusu informuje o wy\u0142\u0105czonym pasku. Formularz powy\u017cej nie od\u015bwie\u017ca si\u0119 sam i pokazuje nowy stan dopiero po prze\u0142adowaniu strony.<\/p>\n<p>Ten sam wzorzec przenosi si\u0119 na stron\u0119 ustawie\u0144 zbudowan\u0105 w React. WordPress Developer Blog pokazuje stron\u0119 opart\u0105 na <code>@wordpress\/components<\/code>, kt\u00f3ra wczytuje opcj\u0119 przez <code>apiFetch( { path: '\/wp\/v2\/settings' } )<\/code> i zapisuje j\u0105 \u017c\u0105daniem POST, z rejestracj\u0105 na <code>init<\/code> i schematem. Strona PHP pozostaje taka sama: <code>register_setting()<\/code> ze schematem i callbackiem oczyszczaj\u0105cym jest nadal jedynym miejscem, w kt\u00f3rym zdefiniowano typ, warto\u015b\u0107 domy\u015bln\u0105 i oczyszczanie. Odpada jedynie renderowanie formularza i <code>options.php<\/code>.<\/p>\n<h2>Ograniczenia i otwarte kwestie<\/h2>\n<ul>\n<li>Kod sprawdzono wzgl\u0119dem kodu \u017ar\u00f3d\u0142owego rdzenia (ga\u0142\u0105\u017a 7.1 i trunk) i uruchomiono na testowej instalacji WordPressa 7.1.2 z PHP 8.4: aktywacja tworzy opcj\u0119 z autoload <code>on<\/code>, a pierwszy zapis przez formularz po usuni\u0119ciu opcji \u2013 z <code>auto<\/code>. Zapis przez formularz i przez <code>\/wp\/v2\/settings<\/code> nie zostawi\u0142 wpis\u00f3w w logu debugowania, a Plugin Check 2.1.0 zg\u0142osi\u0142 jedynie brak pliku <code>readme.txt<\/code>.<\/li>\n<li>Spos\u00f3b traktowania <code>auto<\/code> w przysz\u0142ych wersjach pozostaje otwarty; notatka deweloperska do 6.6 wprost zostawia miejsce na zmian\u0119.<\/li>\n<li>Wtyczka nie usuwa swojej opcji przy odinstalowaniu. To zadanie dla <code>uninstall.php<\/code>, tematu <a href=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/cykl-zycia-wtyczki-odinstalowanie\/\">osobnego artyku\u0142u tej serii o cyklu \u017cycia wtyczki<\/a>.<\/li>\n<li>G\u00f3rna pozycja wymaga, by Theme wywo\u0142ywa\u0142 <code>wp_body_open()<\/code>; w przeciwnym razie dzia\u0142a tylko dolna.<\/li>\n<li>Ustawie\u0144 sieciowych w Multisite ani <code>register_setting()<\/code> w po\u0142\u0105czeniu ze stronami panelu sieci nie badano.<\/li>\n<li>W ga\u0142\u0119zi trunk (7.2 alfa) <code>settings_errors()<\/code> przestawiono na <code>wp_admin_notice()<\/code>. Ta wersja nie zosta\u0142a wydana, wi\u0119c artyku\u0142 opisuje zachowanie wersji 7.1.<\/li>\n<\/ul>\n<div class=\"lw-faq\">\n<h2>Pytania i odpowiedzi<\/h2>\n<h3>Czy register_setting() na hooku admin_init wystarcza, gdy ustawienie jest potrzebne tylko w formularzu?<\/h3>\n<p>Dla formularza tak: <code>options.php<\/code> przechodzi przez <code>wp-admin\/admin.php<\/code>, gdzie wywo\u0142ywany jest <code>admin_init<\/code>. Gdy jednak ustawienie ma pojawi\u0107 si\u0119 w <code>\/wp\/v2\/settings<\/code>, b\u0119dzie go brakowa\u0142o, poniewa\u017c \u017c\u0105danie REST nie uruchamia <code>admin_init<\/code>. R\u00f3wnie\u017c zarejestrowana warto\u015b\u0107 domy\u015blna dla <code>get_option()<\/code> dzia\u0142a na frontendzie tylko wtedy, gdy rejestracja odbywa si\u0119 tak\u017ce tam. <code>init<\/code> obejmuje wszystkie trzy przypadki.<\/p>\n<h3>Dlaczego GET \/wp\/v2\/settings nagle zwraca null dla opcji typu array lub object?<\/h3>\n<p>Kontroler sprawdza zapisan\u0105 warto\u015b\u0107 wzgl\u0119dem schematu i przy b\u0142\u0119dzie zwraca <code>null<\/code>. Najcz\u0119stsz\u0105 przyczyn\u0105 s\u0105 klucze nieznane schematowi, na przyk\u0142ad ze starszej wersji wtyczki: obiekty bez w\u0142asnej regu\u0142y automatycznie otrzymuj\u0105 <code>additionalProperties: false<\/code>. Rozwi\u0105zaniem jest migracja zapisanej warto\u015bci albo rozszerzony schemat. W tym stanie \u017c\u0105danie POST z <code>null<\/code> zostaje odrzucone z kodem <code>rest_invalid_stored_value<\/code>.<\/p>\n<h3>Czy przez \/wp\/v2\/settings da si\u0119 zmieni\u0107 tylko jeden klucz obiektu?<\/h3>\n<p>Nie. Kontroler przekazuje wys\u0142any obiekt bez zmian do <code>update_option()<\/code> i tym samym zast\u0119puje ca\u0142\u0105 warto\u015b\u0107. Klient musi najpierw odczyta\u0107 obiekt, zmieni\u0107 klucz i odes\u0142a\u0107 obiekt w komplecie. Prawdziwe cz\u0119\u015bciowe aktualizacje wymagaj\u0105 w\u0142asnej trasy z <code>permission_callback<\/code>.<\/p>\n<h3>Czy Nonce z settings_fields() wystarcza do ochrony strony ustawie\u0144?<\/h3>\n<p>Nie. Nonce WordPressa pomaga chroni\u0107 przed CSRF. Jest ograniczony czasowo i powi\u0105zany z akcj\u0105 oraz sesj\u0105 u\u017cytkownika, ale nie dowodzi, \u017ce \u017c\u0105danie pochodzi z w\u0142asnego formularza, ani nie zast\u0119puje uwierzytelniania lub sprawdzania uprawnie\u0144. Uprawnienia <code>options.php<\/code> sprawdza osobno, przez <code>manage_options<\/code> lub warto\u015b\u0107 zwr\u00f3con\u0105 przez filtr <code>option_page_capability_{$option_page}<\/code>. Wtyczka, kt\u00f3ra obni\u017ca wymagane uprawnienie swojej pozycji menu, musi dostosowa\u0107 r\u00f3wnie\u017c ten filtr, inaczej zapis si\u0119 nie powiedzie.<\/p>\n<\/div>\n<div class=\"lw-quellen\">\n<h2>\u0179r\u00f3d\u0142a<\/h2>\n<ul>\n<li><a href=\"https:\/\/developer.wordpress.org\/plugins\/settings\/settings-api\/\" target=\"_blank\" rel=\"noopener noreferrer\">Plugin Handbook: Settings API<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/plugins\/settings\/using-settings-api\/\" target=\"_blank\" rel=\"noopener noreferrer\">Plugin Handbook: Using Settings API<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/plugins\/settings\/custom-settings-page\/\" target=\"_blank\" rel=\"noopener noreferrer\">Plugin Handbook: Custom Settings Page<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/plugins\/settings\/options-api\/\" target=\"_blank\" rel=\"noopener noreferrer\">Plugin Handbook: Options API<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/register_setting\/\" target=\"_blank\" rel=\"noopener noreferrer\">Code Reference: register_setting()<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/settings_fields\/\" target=\"_blank\" rel=\"noopener noreferrer\">Code Reference: settings_fields()<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/add_option\/\" target=\"_blank\" rel=\"noopener noreferrer\">Code Reference: add_option()<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_set_option_autoload\/\" target=\"_blank\" rel=\"noopener noreferrer\">Code Reference: wp_set_option_autoload()<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/rest-api\/reference\/settings\/\" target=\"_blank\" rel=\"noopener noreferrer\">REST API Handbook: Settings<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/packages\/packages-api-fetch\/\" target=\"_blank\" rel=\"noopener noreferrer\">Block Editor Handbook: @wordpress\/api-fetch<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/news\/2024\/03\/how-to-use-wordpress-react-components-for-plugin-pages\/\" target=\"_blank\" rel=\"noopener noreferrer\">WordPress Developer Blog: How to use WordPress React components for plugin pages<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/make.wordpress.org\/core\/2016\/10\/26\/registering-your-settings-in-wordpress-4-7\/\" target=\"_blank\" rel=\"noopener noreferrer\">Make WordPress Core: Registering your settings in WordPress 4.7<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/make.wordpress.org\/core\/2023\/10\/17\/new-option-functions-in-6-4\/\" target=\"_blank\" rel=\"noopener noreferrer\">Make WordPress Core: New option functions in 6.4<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/make.wordpress.org\/core\/2024\/06\/18\/options-api-disabling-autoload-for-large-options\/\" target=\"_blank\" rel=\"noopener noreferrer\">Make WordPress Core: Options API: Disabling autoload for large options<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/wordpress-develop\/blob\/7.1\/src\/wp-admin\/options.php\" target=\"_blank\" rel=\"noopener noreferrer\">wordpress-develop: wp-admin\/options.php (branch 7.1)<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/wordpress-develop\/blob\/7.1\/src\/wp-admin\/options-head.php\" target=\"_blank\" rel=\"noopener noreferrer\">wordpress-develop: wp-admin\/options-head.php (branch 7.1)<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/wordpress-develop\/blob\/7.1\/src\/wp-includes\/option.php\" target=\"_blank\" rel=\"noopener noreferrer\">wordpress-develop: wp-includes\/option.php (branch 7.1)<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/wordpress-develop\/blob\/7.1\/src\/wp-includes\/rest-api\/endpoints\/class-wp-rest-settings-controller.php\" target=\"_blank\" rel=\"noopener noreferrer\">wordpress-develop: class-wp-rest-settings-controller.php (branch 7.1)<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/wordpress-develop\/blob\/7.1\/src\/wp-admin\/includes\/plugin.php\" target=\"_blank\" rel=\"noopener noreferrer\">wordpress-develop: wp-admin\/includes\/plugin.php (branch 7.1)<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/wordpress-develop\/blob\/7.1\/src\/wp-admin\/includes\/template.php\" target=\"_blank\" rel=\"noopener noreferrer\">wordpress-develop: wp-admin\/includes\/template.php (branch 7.1)<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/wordpress-develop\/blob\/7.1\/src\/wp-includes\/script-loader.php\" target=\"_blank\" rel=\"noopener noreferrer\">wordpress-develop: wp-includes\/script-loader.php (branch 7.1)<\/a>, dost\u0119p 29.09.2026<\/li>\n<li><a href=\"https:\/\/api.wordpress.org\/core\/version-check\/1.7\/\" target=\"_blank\" rel=\"noopener noreferrer\">WordPress.org version check API (current release)<\/a>, dost\u0119p 29.09.2026<\/li>\n<\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Kompletna wtyczka z jedn\u0105 zbiorcz\u0105 opcj\u0105, stron\u0105 w menu \u201eUstawienia\u201d i dost\u0119pem przez \/wp\/v2\/settings, a do tego droga ka\u017cdego pola formularza przez options.php.<\/p>\n","protected":false},"author":1,"featured_media":20927,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[92646],"tags":[92280,92051,92238,92286],"class_list":["post-20874","post","type-post","status-publish","format-standard","hentry","category-tutorials-pl-wordpress-plugins-tricks-pl","tag-php-pl","tag-rest-api-pl","tag-tutorial-pl","tag-wordpress-pl"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Strony ustawie\u0144 wtyczki z Settings API i register_setting | Lukas Wojcik<\/title>\n<meta name=\"description\" content=\"Settings API krok po kroku: register_setting ze schematem, jedna zbiorcza opcja, \u015bwiadomy autoload, kontrole w options.php i apiFetch na \/wp\/v2\/settings.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Strony ustawie\u0144 wtyczki z Settings API i register_setting | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"Settings API krok po kroku: register_setting ze schematem, jedna zbiorcza opcja, \u015bwiadomy autoload, kontrole w options.php i apiFetch na \/wp\/v2\/settings.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-14T16:52:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20874-strony-ustawien-settings-api-register-setting.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Lukas Wojcik\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lukas Wojcik\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/\"},\"author\":{\"name\":\"Lukas Wojcik\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"Strony ustawie\u0144 wtyczki z Settings API i register_setting\",\"datePublished\":\"2026-10-14T16:52:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/\"},\"wordCount\":2392,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/fi-20874-strony-ustawien-settings-api-register-setting.png\",\"keywords\":[\"PHP\",\"REST API\",\"Tutorial\",\"WordPress\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/\",\"name\":\"Strony ustawie\u0144 wtyczki z Settings API i register_setting | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/fi-20874-strony-ustawien-settings-api-register-setting.png\",\"datePublished\":\"2026-10-14T16:52:00+00:00\",\"description\":\"Settings API krok po kroku: register_setting ze schematem, jedna zbiorcza opcja, \u015bwiadomy autoload, kontrole w options.php i apiFetch na \\\/wp\\\/v2\\\/settings.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/fi-20874-strony-ustawien-settings-api-register-setting.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/fi-20874-strony-ustawien-settings-api-register-setting.png\",\"width\":1200,\"height\":630,\"caption\":\"Strony ustawie\u0144 wtyczki z Settings API i register_setting\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/wordpress-plugins-tricks-pl\\\/tutorials-pl-wordpress-plugins-tricks-pl\\\/strony-ustawien-settings-api-register-setting\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Strony ustawie\u0144 wtyczki z Settings API i register_setting\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Strony ustawie\u0144 wtyczki z Settings API i register_setting | Lukas Wojcik","description":"Settings API krok po kroku: register_setting ze schematem, jedna zbiorcza opcja, \u015bwiadomy autoload, kontrole w options.php i apiFetch na \/wp\/v2\/settings.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/","og_locale":"en_US","og_type":"article","og_title":"Strony ustawie\u0144 wtyczki z Settings API i register_setting | Lukas Wojcik","og_description":"Settings API krok po kroku: register_setting ze schematem, jedna zbiorcza opcja, \u015bwiadomy autoload, kontrole w options.php i apiFetch na \/wp\/v2\/settings.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-10-14T16:52:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20874-strony-ustawien-settings-api-register-setting.png","type":"image\/png"}],"author":"Lukas Wojcik","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Lukas Wojcik","Est. reading time":"20 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/"},"author":{"name":"Lukas Wojcik","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"Strony ustawie\u0144 wtyczki z Settings API i register_setting","datePublished":"2026-10-14T16:52:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/"},"wordCount":2392,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20874-strony-ustawien-settings-api-register-setting.png","keywords":["PHP","REST API","Tutorial","WordPress"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/","url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/","name":"Strony ustawie\u0144 wtyczki z Settings API i register_setting | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20874-strony-ustawien-settings-api-register-setting.png","datePublished":"2026-10-14T16:52:00+00:00","description":"Settings API krok po kroku: register_setting ze schematem, jedna zbiorcza opcja, \u015bwiadomy autoload, kontrole w options.php i apiFetch na \/wp\/v2\/settings.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20874-strony-ustawien-settings-api-register-setting.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20874-strony-ustawien-settings-api-register-setting.png","width":1200,"height":630,"caption":"Strony ustawie\u0144 wtyczki z Settings API i register_setting"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/wordpress-plugins-tricks-pl\/tutorials-pl-wordpress-plugins-tricks-pl\/strony-ustawien-settings-api-register-setting\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Strony ustawie\u0144 wtyczki z Settings API i register_setting"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/20874","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=20874"}],"version-history":[{"count":1,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/20874\/revisions"}],"predecessor-version":[{"id":21779,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/20874\/revisions\/21779"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/20927"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=20874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=20874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=20874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}