Wordpress Settings API Admin Menus Capabilities Sanitization Form Handling
Definisi singkat
Settings API adalah kumpulan fungsi WordPress untuk mendaftarkan, menampilkan, dan memproses pengaturan di admin dashboard dengan cara yang konsisten. Di praktik plugin/theme work, API ini biasanya dipakai untuk halaman settings yang menyimpan opsi ke wp_options, lengkap dengan section, field, capability check, nonce, dan sanitization callback.
Kalau kamu sedang membangun halaman admin yang isinya form pengaturan, Settings API memberi struktur yang lebih aman dan lebih gampang dirawat dibanding menulis alur submit manual dari nol.
Kapan memakai Settings API
Pakai Settings API kalau kebutuhanmu cocok dengan pola pengaturan situs, misalnya:
- halaman opsi plugin seperti API key, toggle fitur, dan konfigurasi integrasi
- halaman theme options yang sifatnya global
- form admin yang menyimpan data ke options table
- pengaturan yang perlu tampil di dashboard dengan section dan field terstruktur
- data yang disimpan tidak terkait satu post tertentu, melainkan level situs atau plugin
Settings API biasanya pilihan yang sehat kalau kamu butuh:
- register setting dengan sanitization yang jelas
- rendering field yang konsisten
- alur submit form admin yang standar
- capability gating yang eksplisit
- integrasi dengan
options.phptanpa custom processing berlebihan
Jangan pakai Settings API kalau
Jangan dipaksakan kalau kebutuhanmu sebenarnya berbeda:
- data yang disimpan adalah meta per post, user, atau term
- form butuh wizard multi-step yang kompleks
- validasi dan workflow lebih cocok lewat controller/custom endpoint
- UI settings sangat custom dan tidak lagi mengikuti pola form admin WordPress
- kamu perlu transactional save flow yang melibatkan banyak resource sekaligus
Prinsip praktisnya: Settings API bagus untuk site-level configuration. Kalau objeknya bukan setting global, sering kali ada API WordPress lain yang lebih pas.
Alur kerja register menu, page, dan settings
Di admin WordPress, tiga hal ini sering terlihat seperti satu blok, padahal perannya beda:
- menu/page: tempat navigasi dan tampilan UI
- settings: definisi data yang disimpan
- form handling: alur submit ke
options.php, lalu sanitize dan redirect
Urutan umumnya begini:
- hook admin dijalankan
- menu atau submenu dibuat
- halaman settings diregister
- setting, section, dan field diregister
- page render memanggil
settings_fields()dando_settings_sections() - form submit dikirim ke
options.php - WordPress memproses nonce, capability, dan sanitization callback
- hasil valid disimpan
- user di-redirect kembali ke halaman settings dengan status update
Diagram alur
Cara kerja admin menu dan page
Admin menu dibuat dengan hook seperti admin_menu atau network_admin_menu, lalu halaman ditambahkan dengan fungsi seperti add_menu_page() atau add_submenu_page().
add_menu_page()
Dipakai untuk membuat menu level atas di sidebar admin.
Contoh:
add_action('admin_menu', function () {
add_menu_page(
'Plugin Settings',
'Plugin Settings',
'manage_options',
'myplugin-settings',
'myplugin_render_settings_page',
'dashicons-admin-generic'
);
});Parameter pentingnya:
- page title: judul browser/page
- menu title: label di sidebar
- capability: siapa yang boleh melihat halaman
- menu slug: identifier unik halaman
- callback: fungsi render konten halaman
- icon / position: tampilan dan posisi menu
add_submenu_page()
Dipakai kalau halaman settings menjadi turunan menu yang sudah ada.
Contoh:
add_action('admin_menu', function () {
add_submenu_page(
'options-general.php',
'Plugin Settings',
'Plugin Settings',
'manage_options',
'myplugin-settings',
'myplugin_render_settings_page'
);
});Kenapa capability di menu penting
Capability di menu bukan sekadar kosmetik. Itu membatasi siapa yang bisa membuka halaman sejak dari navigasi.
Kalau menu bisa terlihat oleh user yang salah, kamu berisiko:
- membocorkan struktur UI internal
- memunculkan page yang berisi aksi sensitif
- membuka permukaan error atau informasi konfigurasi
Tetap lakukan capability check di callback page dan saat save. Jangan percaya hanya pada visibility menu.
Cara kerja register setting, section, dan field
Settings API punya tiga lapisan utama:
1. register_setting()
Mendaftarkan option name, group, dan aturan sanitization.
Contoh:
add_action('admin_init', function () {
register_setting('myplugin_settings_group', 'myplugin_api_key', [
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'default' => '',
'show_in_rest' => false,
]);
});Yang penting di sini:
- option name: key yang disimpan di database
- group: nama grup form yang dikaitkan dengan submit
- sanitize_callback: fungsi pembersih data sebelum simpan
- default: nilai fallback
Kalau nilai yang disimpan kompleks, sanitize_callback sering perlu custom logic, bukan sekadar helper bawaan.
2. add_settings_section()
Membagi form menjadi blok logis.
Contoh:
add_settings_section(
'myplugin_main_section',
'Pengaturan Utama',
function () {
echo '<p>Atur konfigurasi dasar plugin di sini.</p>';
},
'myplugin-settings'
);Section membantu pembaca karena form admin WordPress cepat jadi padat. Section membuat halaman lebih mudah dipindai.
3. add_settings_field()
Mendaftarkan field individual yang ditampilkan di dalam section.
Contoh:
add_settings_field(
'myplugin_api_key_field',
'API Key',
'myplugin_render_api_key_field',
'myplugin-settings',
'myplugin_main_section'
);Callback field biasanya bertugas menampilkan input, checkbox, select, atau textarea. Nilai saat ini dibaca dari option yang tersimpan.
Contoh struktur render page
Di callback render halaman, pola dasarnya seperti ini:
function myplugin_render_settings_page() {
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions to access this page.'));
}
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<form method="post" action="options.php">
<?php
settings_fields('myplugin_settings_group');
do_settings_sections('myplugin-settings');
submit_button();
?>
</form>
</div>
<?php
}Tiga fungsi penting di dalam form:
settings_fields()do_settings_sections()submit_button()
settings_fields() menghasilkan hidden fields yang berisi nonce dan group yang dibutuhkan options.php.
Cara kerja save flow di options.php
Saat form disubmit ke options.php, WordPress menangani proses save dengan pola standar.
Urutannya
- form dikirim lewat POST
settings_fields()memastikan nonce dan group ikut terkirim- WordPress memvalidasi capability user
- WordPress memanggil sanitize callback yang diregister
- data disimpan ke options table
- WordPress me-redirect kembali ke halaman asal
- status sukses ditandai lewat query arg atau pesan updated
Kenapa action form harus options.php
Kalau kamu memakai Settings API, action="options.php" bukan detail kecil. Itu jalur resmi yang dipakai WordPress untuk memproses option group yang sudah diregister.
Kalau kamu mengganti ke endpoint custom tanpa alasan yang jelas, kamu harus mengurus sendiri:
- nonce handling
- capability check
- sanitization
- redirect
- error handling
- persistence
Itu bisa saja valid, tapi kamu keluar dari pola standar Settings API.
Sanitize callback dan keamanan data
Sanitization adalah lapisan penting sebelum data ditulis ke database. Di WordPress admin, asumsi yang aman adalah: input dari form tetap harus dianggap tidak tepercaya.
Sanitization bukan escaping
Ini jebakan yang sering terjadi:
- sanitization membersihkan data sebelum simpan
- escaping melindungi output saat ditampilkan
Keduanya beda fungsi.
Contoh aturan umum:
- teks sederhana →
sanitize_text_field() - textarea →
sanitize_textarea_field() - URL →
esc_url_raw() - email →
sanitize_email()lalu validasi hasilnya - checkbox → cast ke boolean/int yang eksplisit
- array → sanitasi per elemen, jangan satu fungsi untuk seluruh struktur
Contoh sanitize callback custom
function myplugin_sanitize_settings($input) {
$output = [];
$output['api_key'] = isset($input['api_key'])
? sanitize_text_field($input['api_key'])
: '';
$output['endpoint'] = isset($input['endpoint'])
? esc_url_raw($input['endpoint'])
: '';
$output['enabled'] = !empty($input['enabled']) ? 1 : 0;
return $output;
}Lalu dipakai di register_setting():
register_setting('myplugin_settings_group', 'myplugin_settings', [
'type' => 'array',
'sanitize_callback' => 'myplugin_sanitize_settings',
]);Capability tetap wajib
Sanitization tidak menggantikan authorization. Walaupun data sudah dibersihkan, user yang tidak berhak tetap tidak boleh menyimpan setting sensitif.
Gunakan capability seperti:
manage_optionsuntuk menu admin yang benar-benar sensitif- capability yang lebih spesifik kalau plugin menyediakan model izin sendiri
Kalau fitur itu untuk editor atau role tertentu, jangan langsung pakai manage_options hanya karena paling gampang.
Nonce, CSRF, dan form admin
Settings API secara default bekerja bersama nonce dari settings_fields(). Itu penting untuk mencegah CSRF.
Yang perlu dijaga
- form harus menyertakan
settings_fields() - form harus dikirim via POST
- page harus dicek capability-nya
- field bernilai sensitif tetap disanitasi
Kesalahan umum nonce
- membuat form custom tapi lupa nonce
- menaruh nonce, tapi tidak memverifikasinya di alur custom
- menganggap nonce cukup tanpa capability check
- memakai AJAX save tanpa alur keamanan yang setara
Kalau kamu keluar dari options.php, pastikan alur pengamanan minimal setara: nonce, capability, sanitization, dan logging/error handling bila perlu.
Jebakan umum pada admin UI
1. Menyimpan semua input tanpa struktur
Kalau semua field disimpan ke satu option blob tanpa skema yang jelas, halaman settings jadi sulit dirawat. Lebih baik bentuk datanya jelas sejak awal.
2. Capability hanya dicek di menu
Menu yang tersembunyi bukan berarti aman. Tetap cek capability di callback render dan di jalur save.
3. Mengandalkan escaping saat save
Escaping bukan untuk menyimpan data. Kalau data masuk ke database dalam bentuk yang sudah di-escape, kamu bisa bikin bug saat output berikutnya.
4. Sanitization terlalu agresif
Beberapa field butuh format tertentu. Kalau kamu pakai sanitization yang salah, data valid bisa ikut rusak.
Contoh:
- URL yang valid diperlakukan seperti teks biasa
- HTML yang memang diizinkan dipotong habis
- angka desimal berubah jadi integer tanpa sengaja
5. Field callback terlalu pintar
Callback render field sebaiknya hanya menampilkan UI. Kalau logika save, validasi, atau transform terlalu banyak disebar di callback field, page jadi sulit dipahami.
6. Tidak menamai option group dan page dengan konsisten
Group, page slug, dan option name harus konsisten supaya settings_fields() dan do_settings_sections() tidak meleset.
7. Melupakan escaped output di admin
Admin UI tetap butuh escaping saat render:
esc_html()untuk teksesc_attr()untuk value inputesc_url()untuk URL
Admin bukan alasan untuk mengendurkan escaping.
8. Konflik UI dengan script atau plugin lain
Halaman admin WordPress adalah area bersama. Hindari:
- selector CSS terlalu umum
- id/class generik seperti
.buttontanpa scope - script yang mengubah markup inti tanpa isolasi
Pola implementasi yang sehat
Kalau kamu membangun settings page yang rapi, susun layer-nya seperti ini:
- admin_menu: register menu/page
- admin_init: register setting, section, field
- render callback: tampilkan form
- sanitize callback: bersihkan input
- capability check: lindungi page dan save path
- escaping output: amankan nilai yang ditampilkan
Kalau dipisahkan begini, tiap bagian punya tanggung jawab yang jelas.
Ringkasan cepat
Pakai Settings API kalau kamu membangun pengaturan global plugin/theme dan ingin alur save yang mengikuti pola WordPress.
Ingat urutan intinya:
- register menu/page
- register setting/section/field
- render form dengan
settings_fields()dando_settings_sections() - submit ke
options.php - sanitize sebelum save
- redirect kembali ke page
Kalau yang kamu bangun bukan settings global, pertimbangkan API lain yang lebih sesuai. Settings API itu kuat, tapi paling bagus saat dipakai pada masalah yang memang cocok dengan modelnya.