Редактирование записей через форму на фронтенде
У меня есть пользовательский тип записи со стандартными мета-боксами и некоторыми произвольными полями. Как можно реализовать редактирование записи через форму на фронтенде?

Вот базовые решения для обновления записи/страницы. Я добавил быстрый пример работы с пользовательскими метаполями. Это довольно просто, но укажет вам направление для редактирования записей на фронтенде без использования плагинов. Решение не супергибкое, но вы можете добавить в него все, что вам необходимо.
Добавьте этот код в ваш цикл:
<form id="post" class="post-edit front-end-form" method="post" enctype="multipart/form-data">
<input type="hidden" name="post_id" value="<?php the_ID(); ?>" />
<?php wp_nonce_field( 'update_post_'. get_the_ID(), 'update_post_nonce' ); ?>
<p><label for="post_title">Заголовок</label>
<input type="text" id="post_title" name="post_title" value="<?php echo $post->post_title; ?>" /></p>
<p><?php wp_editor( $post->post_content, 'postcontent' ); ?></p>
<p><label for="post_title">Тест</label>
<?php $value = get_post_meta(get_the_ID(), 'edit_test', true); ?>
<input type="text" id="edit_test" name="edit_test" value="<?php echo $value; ?>" /></p>
<p><label for="post_title">Тест 2</label>
<?php $value = get_post_meta(get_the_ID(), 'edit_test2', true); ?>
<input type="text" id="edit_test2" name="edit_test2" value="<?php echo $value; ?>" /></p>
<input type="submit" id="submit" value="Обновить" />
</form>
Затем добавьте этот код в начало страницы для обработки формы:
if ( 'POST' == $_SERVER['REQUEST_METHOD'] && ! empty($_POST['post_id']) && ! empty($_POST['post_title']) && isset($_POST['update_post_nonce']) && isset($_POST['postcontent']) )
{
$post_id = $_POST['post_id'];
$post_type = get_post_type($post_id);
$capability = ( 'page' == $post_type ) ? 'edit_page' : 'edit_post';
if ( current_user_can($capability, $post_id) && wp_verify_nonce( $_POST['update_post_nonce'], 'update_post_'. $post_id ) )
{
$post = array(
'ID' => esc_sql($post_id),
'post_content' => esc_sql($_POST['postcontent']),
'post_title' => esc_sql($_POST['post_title'])
);
wp_update_post($post);
if ( isset($_POST['edit_test']) ) update_post_meta($post_id, 'edit_test', esc_sql($_POST['edit_test']) );
if ( isset($_POST['edit_test2']) ) update_post_meta($post_id, 'edit_test2', esc_sql($_POST['edit_test2']) );
}
else
{
wp_die("У вас нет прав для этого действия");
}
}

Я добавил esc_sql(). Мне просто пришло в голову, что данные, отправляемые из публичной (или полупубличной) формы, нужно экранировать.

Я использую Advanced Custom Fields для множественного редактирования записей через фронтенд с помощью метабоксов. ACF позволяет создавать продвинутые поля для метабоксов и автоматически добавляет их в панель редактирования записей в админке.
Но также есть фронтенд-функционал.
Этот метод полностью бесплатный. Платить нужно только если вы хотите использовать более сложные типы полей в виде аддонов, например repeater, flexible или gallery. Которые отлично работают в данном случае.
Первый недостаток - отсутствие полей для заголовка и содержимого записи... но это легко исправить, добавив следующий код в functions.php:
/**
* Отключаем стили админки во фронтенде при использовании ACF форм
*
* ACF подключает стили админки при загрузке заголовка, что часто вызывает проблемы с фронтенд-формами и не нужно для наших целей
*/
add_action( 'wp_print_styles', 'custom_acf_deregister_styles', 100 );
function custom_acf_deregister_styles()
{
if (! is_admin() )
{
wp_deregister_style( 'wp-admin' );
}
}
/**
* Сохраняем поле ACF как post_content / post_title для фронтенд-публикации
*/
add_action( 'acf/save_post', 'custom_acf_save_post' );
function custom_acf_save_post( $post_id )
{
if (! is_admin() && 'acf' != get_post_type( $post_id ) ) // Не выполняем при добавлении/обновлении полей/групп полей в админке
{
$post_title = get_post_meta( $post_id, 'form_post_title', true );
$post_content = get_post_meta( $post_id, 'form_post_content', true );
$post = get_post($post_id);
if ( ($post_title && $post_title != $post->post_title) || ($post_content && $post_content != $post->post_content) )
{
$post_data = array(
'ID' => $post_id,
);
if ( $post_content ) $post_data['post_content'] = $post_content;
if ( $post_title ) $post_data['post_title'] = $post_title;
remove_action( 'acf/save_post', 'custom_acf_save_post' );
wp_update_post( $post_data );
add_action( 'acf/save_post', 'custom_acf_save_post' );
}
}
}
/**
* Загружаем существующий post_title
*/
add_filter( 'acf/load_value/name=form_post_title', 'custom_acf_load_value_form_post_title', 10, 3 );
function custom_acf_load_value_form_post_title( $value, $post_id, $field )
{
$value = get_the_title($post_id);
return $value;
}
/**
* Загружаем существующий post_content
*/
add_filter( 'acf/load_value/name=form_post_content', 'custom_acf_load_value_form_post_content', 10, 3 );
function custom_acf_load_value_form_post_content( $value, $post_id, $field )
{
$post = get_post($post_id);
$value = $post->post_content;
return $value;
}
/**
* Установка аддонов (Добавляем две группы полей для редактирования заголовка и содержимого)
*
* Следующий код включит все 4 премиальных аддона в вашу тему.
* Пожалуйста, не пытайтесь включить несуществующий файл - это вызовет ошибку.
*
* Все поля должны быть включены во время действия 'acf/register_fields'.
* Другие типы аддонов (например, страница опций) могут быть включены вне этого действия.
*
* Код предполагает наличие папки 'add-ons' в вашей теме.
*
* ВАЖНО
* Аддоны могут быть включены в премиальную тему согласно условиям лицензии.
* Однако они НЕ должны включаться в премиальные/бесплатные плагины.
* Подробнее: http://www.advancedcustomfields.com/terms-conditions/
*/
// Поля
add_action('acf/register_fields', 'my_register_fields');
/**
* Регистрация групп полей
*
* Функция register_field_group принимает 1 массив с данными для регистрации группы полей
* Вы можете редактировать массив по своему усмотрению, но это может вызвать ошибки, если массив несовместим с ACF
*/
if(function_exists("register_field_group"))
{
register_field_group(array (
'id' => 'acf_form-post-title',
'title' => 'Заголовок записи формы',
'fields' => array (
array (
'key' => 'field_25',
'label' => 'Заголовок',
'name' => 'form_post_title',
'type' => 'text',
'default_value' => '',
'formatting' => 'html',
),
),
'location' => array (
array (
array (
'param' => 'post_type',
'operator' => '==',
'value' => 'course',
'order_no' => 0,
'group_no' => 0,
),
),
),
'options' => array (
'position' => 'normal',
'layout' => 'no_box',
'hide_on_screen' => array (
),
),
'menu_order' => -2,
));
register_field_group(array (
'id' => 'acf_form-post-content',
'title' => 'Содержимое записи формы',
'fields' => array (
array (
'key' => 'field_13',
'label' => 'Содержимое',
'name' => 'form_post_content',
'type' => 'wysiwyg',
'default_value' => '',
'toolbar' => 'full',
'media_upload' => 'yes',
),
),
'location' => array (
array (
array (
'param' => 'post_type',
'operator' => '==',
'value' => 'course',
'order_no' => 0,
'group_no' => 0,
),
),
),
'options' => array (
'position' => 'normal',
'layout' => 'no_box',
'hide_on_screen' => array (
),
),
'menu_order' => -1,
));
}
Этот код добавит поддержку полей заголовка и содержимого, которые можно использовать во фронтенд-формах следующим образом:
// Добавляем перед get_header()
// Подключает стили/скрипты, а также обрабатывает форму, что очень важно
acf_form_head();
get_header();
// Где 51 - ID группы полей ACF (метабоксов), которые мы хотим добавить
acf_form( array(
'field_groups' => array('acf_form-post-title', 'acf_form-post-content', 51)
) );
Я использую этот метод в большинстве своих проектов. Обычно я создаю базовую запись через Gravity Forms, а затем управляю всем через ACF как во фронтенде, так и в админке. Главное преимущество - единое место управления для обоих случаев. Стоит отметить, что ACF можно использовать и для создания записей. Я пока не пробовал, но планирую опробовать в следующем проекте, чтобы иметь полный доступ к метаполям при создании.
Лично для меня ACF - единственный плагин, без которого я не могу обойтись, а Gravity Forms занимает второе место.

Спасибо за подсказку, но я искал решение без использования плагинов

Это возможно сделать. Просто тема довольно сложная. У меня есть решение под названием "Catapost", которое позволяет добавлять метабоксы к записям, а затем создавать формы на фронтенде для редактирования заголовка/содержания записи вместе с метабоксами. Это ПОХОЖЕ на плагин, но он включён в тему, поэтому может распространяться вместе с темами. Это то, что вам нужно?

Ну... Гибкое решение довольно сложное... Если вам нужно просто редактировать обычную запись... Это может быть не так сложно.

Я добавил очень простое решение в другом ответе, где показано, как сделать это без плагина. Оно не очень гибкое, но хорошо подходит для разового использования.

Если вы хотите отредактировать существующую запись, попробуйте мой плагин Фронт-енд Редактор.
Если вы хотите создать новые записи, попробуйте один из этих вариантов:

Спасибо, Scribu. Твой плагин потрясающий, но он не подходит для моих нужд. Я пытаюсь редактировать существующую запись с помощью формы. Я задавал похожий вопрос о редактировании профиля пользователя через форму на фронтенде и получил такой ответ: http://wordpress.stackexchange.com/questions/9775/how-to-edit-a-user-profile-on-the-front-end Это сработало идеально для меня. Если есть подобное решение для редактирования записей, я буду очень благодарен.

@nickfancis.me используй комментарии для таких вещей - для этого они и существуют!

Самый простой способ — использовать что-то вроде Ninja Forms со следующим платным расширением:
http://wpninjas.com/downloads/front-end-posting/
Также вы можете реализовать это самостоятельно. По сути, вам нужно создать форму и использовать функцию wp_insert_post()
для создания полноценной записи.
Пример формы:
<form action="" id="primaryPostForm" method="POST">
<fieldset>
<label for="postTitle"><?php _e('Заголовок записи:', 'framework') ?></label>
<input type="text" name="postTitle" id="postTitle" class="required" />
</fieldset>
<fieldset>
<label for="postContent"><?php _e('Содержание записи:', 'framework') ?></label>
<textarea name="postContent" id="postContent" rows="8" cols="30" class="required"></textarea>
</fieldset>
<fieldset>
<input type="hidden" name="submitted" id="submitted" value="true" />
<button type="submit"><?php _e('Добавить запись', 'framework') ?></button>
</fieldset>
А затем при отправке формы обработать данные примерно так:
if ( isset( $_POST['submitted'] ) && isset( $_POST['post_nonce_field'] ) && wp_verify_nonce( $_POST['post_nonce_field'], 'post_nonce' ) ) {
if ( trim( $_POST['postTitle'] ) === '' ) {
$postTitleError = 'Пожалуйста, введите заголовок.';
$hasError = true;
}
$post_information = array(
'post_title' => wp_strip_all_tags( $_POST['postTitle'] ),
'post_content' => $_POST['postContent'],
'post_type' => 'post',
'post_status' => 'pending'
);
wp_insert_post( $post_information );
}
Полный код и руководство доступны по ссылке: http://wp.tutsplus.com/tutorials/creative-coding/posting-via-the-front-end-inserting/
