WordPress: метабокс с безопасным сохранением (OOP, nonce, права)
Класс метабокса для CPT с проверкой nonce, автосохранения и прав пользователя. get_post_meta, update_post_meta, add_meta_box по документации.
Как использовать
- Подключите класс в теме или плагине и вызовите ProjectRepoMetaBox::init() на add_action('init', ..., 20) (после регистрации CPT).
- Ключ мета с подчёркиванием (_repo_url) скрыт из блока «Произвольные поля» в редакторе.
Метабокс для поля «URL репозитория» у CPT project с проверкой nonce, пропуском автосохранения и проверкой прав. Соответствует документации add_meta_box и примерам на wp-kama.ru.
<?php
declare(strict_types=1);
/**
* Метабокс «Репозиторий» для post type project.
* Nonce + проверка прав при сохранении. PHP 8.1+.
*/
final class ProjectRepoMetaBox
{
private const POST_TYPE = 'project';
private const META_KEY = '_repo_url';
private const NONCE_ACTION = 'project_repo_save';
private const NONCE_NAME = 'project_repo_nonce';
private const INPUT_NAME = 'project_repo_url';
public static function init(): void
{
$self = new self();
add_action('add_meta_boxes', [$self, 'addMetaBox']);
add_action('save_post_' . self::POST_TYPE, [$self, 'save'], 10, 1);
}
public function addMetaBox(string $postType): void
{
if ($postType !== self::POST_TYPE) {
return;
}
add_meta_box(
'project_repo',
'Репозиторий',
[$this, 'render'],
self::POST_TYPE,
'normal',
'default'
);
}
/** @param \WP_Post $post */
public function render($post): void
{
wp_nonce_field(self::NONCE_ACTION, self::NONCE_NAME);
$value = get_post_meta((int) $post->ID, self::META_KEY, true);
$value = is_string($value) ? $value : '';
?>
<p>
<label for="<?php echo esc_attr(self::INPUT_NAME); ?>">URL репозитория</label><br>
<input type="url"
id="<?php echo esc_attr(self::INPUT_NAME); ?>"
name="<?php echo esc_attr(self::INPUT_NAME); ?>"
value="<?php echo esc_attr($value); ?>"
style="width:100%; max-width:32em;"
/>
</p>
<?php
}
public function save(int $postId): void
{
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
$nonce = $_POST[self::NONCE_NAME] ?? '';
if (!is_string($nonce) || !wp_verify_nonce($nonce, self::NONCE_ACTION)) {
return;
}
if (!current_user_can('edit_post', $postId)) {
return;
}
$raw = $_POST[self::INPUT_NAME] ?? '';
if (!is_string($raw)) {
return;
}
$url = esc_url_raw(trim($raw));
update_post_meta($postId, self::META_KEY, $url);
}
}
// После регистрации CPT (например в плагине):
ProjectRepoMetaBox::init();
Usage:
Вызовите ProjectRepoMetaBox::init() после того, как зарегистрирован тип project (например, в том же плагине на init с приоритетом 20). В шаблоне значение читайте через сниппет «Post meta helper (OOP)» или get_post_meta($postId, '_repo_url', true).
Notes:
- Ключ
_repo_urlс подчёркиванием не показывается в блоке «Произвольные поля» (get_post_meta). - Сохранение привязано к
save_post_{post_type}— срабатывает только для записей типаproject.