Разработка плагина WordPress - Сообщение о Headers Already Sent
При разработке плагинов WordPress я получаю следующее сообщение при активации:
Плагин сгенерировал 293 символа неожиданного вывода во время активации. Если вы заметили сообщения "headers already sent", проблемы с лентами синдикации или другие проблемы, попробуйте деактивировать или удалить этот плагин.
Плагин работает очень хорошо, но я не понимаю, почему появляется это сообщение. Мой плагин: http://wordpress.org/extend/plugins/facebook-send-like-button/

Обычно это вызвано пробелами или переносами строк перед открывающим тегом <?php
или после закрывающего тега ?>
.
Ознакомьтесь с этой страницей, чтобы увидеть возможные решения: Как решить проблему с предупреждением "Headers already sent"?
ОБНОВЛЕНИЕ
После анализа кода вашего плагина я заметил, что у вас отсутствует закрывающий тег PHP. На последней строке добавьте ?>

PHP-файлам не требуется закрывающий тег ?>
. Более того, один из способов гарантировать отсутствие проблем с Headers already sent
— просто не использовать закрывающий тег.

Вот в чём была моя проблема. У меня было несколько пустых строк после закрывающего тега ?>
.

Не рекомендуется использовать закрывающий PHP-тег. Это плохая практика, которая приводит к проблемам, описанным в вопросе, и противоречит стандартам кодирования WordPress Core (см. https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#remove-trailing-spaces).

Скорее всего, вы получаете ошибку PHP, которая генерирует вывод до отправки заголовков. Если у вас включен E_NOTICE
, вызов $_POST['foo']
может вызвать ошибку "Notice: undefined variable", если переменная не определена.
Лучшая практика: никогда не делайте предположений о переменных GET, POST, COOKIE и REQUEST. Всегда проверяйте их сначала с помощью isset()
или empty()
.
if ( isset( $_POST['foo'] ) ) {
$foo = (string) $_POST['foo'];
// при необходимости добавьте дополнительные проверки здесь
}

В начале функции активации добавьте ob_start();
, а в конце - trigger_error(ob_get_contents(),E_USER_ERROR);
.
Затем попробуйте активировать ваш плагин, и вы увидите, что на самом деле представляют собой 'сгенерировано 293 символа неожиданного вывода'. После этого отладка станет проще (либо удалите символы новой строки, либо исправьте ошибки).

Я знаю, что это старый вопрос, и на него уже есть принятый ответ. Есть множество ответов, которые рассматривают, какими могут быть потенциальные проблемы с активацией. Однако ни один из них не затрагивает главный вопрос: КАК правильно отлаживать проблемы с активацией плагинов.
Если вы занимаетесь разработкой плагинов для WordPress, лучше использовать правильные инструменты. Один из таких — Debug Bar. Это плагин, который помогает отлаживать проблемы в WordPress. Если вы разрабатываете плагины, он должен быть в вашем арсенале.
У Debug Bar есть несколько дополнений — своего рода плагины для плагина. Одно из них — Debug Bar Plugin Activation, которое показывает PHP-ошибки, возникающие при активации плагина. Как только вы узнаете, какая именно PHP-ошибка приводит к отправке заголовков, вы поймете, где искать решение. Поверьте, знание конкретной ошибки сэкономит вам уйму времени вместо того, чтобы гадать, что могло пойти не так.

Я не уверен на 100%, но почти уверен, что проблема именно в этом.
Вам нужно использовать корректную callback-функцию в качестве второго аргумента в register_activation_hook()
:
register_activation_hook(__FILE__,'twl_tablo_olustur');
Насколько я могу судить, функция twl_tablo_olustur()
нигде не определена. Это точно объясняет неожиданный вывод (ошибка PHP из-за попытки вызвать несуществующую функцию) и почему во всех остальных случаях всё работает нормально.

Я часто получаю такие сообщения, когда вывожу отладочные сообщения плагинов или тем, особенно если вывод происходит до вызова wp_header.
Если вы выводите любые символы, то, насколько я понимаю (возможно, ошибаюсь), происходит неявное объявление заголовков, поэтому когда происходит обычный вызов header(), вы получаете ошибку, так как не может быть двух объявлений заголовков.
Вы можете использовать ob_start() для буферизации вывода, что должно устранить ошибку — ознакомьтесь с комментариями здесь: http://php.net/manual/en/function.header.php

Рассматривая последнюю версию плагина (381724), проблема заключается в слишком большом количестве пробелов.
Каждый раз, когда вам нужно создать такую структуру:
function blabla(){
<= табуляция
что-то...
}
в вашем коде используйте TAB, а не пробелы.
Вот ваш код, где я заменил все пробелы на табуляции, и при активации не получаю никаких сообщений:
<?php
/*
Plugin Name: Facebook Send Button By Teknoblogo.com
Plugin URI: http://www.teknoblogo.com/facebook-gonder-butonu-eklenti
Description: Добавляет кнопки "Отправить" и "Нравится" от Facebook к вашим записям! Автор: <a href="http://www.teknoblogo.com">teknoblogo.com</a>
Version: 1.3
Author: Eray Alakese
Author URI: http://www.teknoblogo.com
License: GPL2
*/
wp_register_script('fgb_script', "http://connect.facebook.net/en_US/all.js#xfbml=1");
wp_enqueue_script('fgb_script');
function fgb_ayarlari_yap()
{
add_option('fgb_yer', 'u');
add_option('fgb_buton', 'snl');
add_option('fgb_manual', 'hayir');
}
register_activation_hook( __FILE__, 'fgb_ayarlari_yap' );
function fgb_ayarlari_sil()
{
delete_option('fgb_yer');
delete_option('fgb_buton');
delete_option('fgb_manual');
}
register_deactivation_hook( __FILE__, 'fgb_ayarlari_sil' );
function fgb_ekle($content)
{
$fgb_yer = get_option('fgb_yer');
$fgb_buton_opt = get_option('fgb_buton');
$fgb_manual = get_option('fgb_manual');
$fgb_perma = rawurlencode(get_permalink());
$fgb_send_button = "<fb:send href=\"$fgb_perma\" font=\"\"></fb:send>";
$fgb_like_button = "<fb:like href=\"$fgb_perma\" send=\"false\" width=\"450\" show_faces=\"true\" font=\"\"></fb:like>";
$fgb_snl_button = "<fb:like href=\"$fgb_perma\" send=\"true\" width=\"450\" show_faces=\"true\" font=\"\"></fb:like>";
if($fgb_buton_opt == "send")
{
$fgb_buton = $fgb_send_button;
}
elseif($fgb_buton_opt == "like")
{
$fgb_buton = $fgb_like_button;
}
elseif($fgb_buton_opt == "snl")
{
$fgb_buton = $fgb_snl_button;
}
else
{
echo "Тип кнопки не определен!";
}
if ($fgb_manual=="hayir"){
if ($fgb_yer == "u")
{
$content = $fgb_buton."<br />".$content;
}
elseif ($fgb_yer == "a")
{
$content = $content."<br />".$fgb_buton;
}
return $content;
}
elseif($fgb_manual=="evet"){
echo $fgb_buton;
}
}
if (get_option('fgb_manual')=="hayir"){ add_filter( "the_content", "fgb_ekle" ); }
add_action('admin_menu', 'fgb_admin_menu');
function fgb_admin_menu() {
add_options_page('Facebook Send Button', 'Facebook Send Button', 'manage_options', 'fgb', 'fgb_admin_options');
}
function fgb_admin_options() {
if (!current_user_can('manage_options')) {
wp_die( __('У вас недостаточно прав для доступа к этой странице.') );
}
echo '<div class="wrap">';
?>
<h2>Facebook Send & Like Button</h2>
<?
if($_POST["fgb_gonder"])
{
echo "<h3>сохранено</h3>";
update_option('fgb_yer', $_POST["fgb_yer"]);
update_option('fgb_buton', $_POST["fgb_buton"]);
update_option('fgb_manual', $_POST["fgb_manual"]);
$fgb_admin_yer = get_option('fgb_yer');
$fgb_admin_buton = get_option('fgb_buton');
$fgb_admin_manual = get_option('fgb_manual');
}
?>
<form action="<?php echo $_SERVER['REQUEST_URI']; ?>" method="POST">
Показать кнопки Facebook <select name="fgb_yer">
<option value="u" <?php if($fgb_admin_yer == "u"){echo "SELECTED";}?>>перед содержимым</option>
<option value="a" <?php if($fgb_admin_yer == "a"){echo "SELECTED";}?>>после содержимого</option>
</select> и я хочу <select name="fgb_buton">
<option value="snl" <?php if($fgb_admin_buton=="snl"){echo "SELECTED";}?>>кнопки "Отправить" и "Нравится" вместе</option>
<option value="send" <?php if($fgb_admin_buton=="send"){echo "SELECTED";}?>>только кнопку "Отправить"</option>
<option value="like" <?php if($fgb_admin_buton=="like"){echo "SELECTED";}?>>только кнопку "Нравится"</option>
</select> . <br />
<input type="radio" value="hayir" name="fgb_manual" <?php if($fgb_admin_manual=="hayir"){echo "CHECKED";}?> /> разместить кнопки автоматически <br />
<input type="radio" value="evet" name="fgb_manual" <?php if($fgb_admin_manual=="evet"){echo "CHECKED";}?> /> я размещу их вручную <br />
<input type="submit" class="button-primary" name="fgb_gonder" value="<?php _e('Сохранить изменения') ?>" />
</form>
<br />Если вы используете <strong>ручное размещение</strong>, вам нужно добавить этот код в вашу тему:
<strong><?php if(function_exists('fgb_ekle')) { fgb_ekle(); }?></strong>
<hr />
<em>Если вам нравится этот плагин, пожалуйста, <a href="http://wordpress.org/extend/plugins/facebook-send-like-button/">оцените его</a>.
Автор: <a href="http://www.teknoblogo.com">Eray Alakese</a>
Вы можете <a href="mailto:info@teknoblogo.com">написать мне</a> по поводу ошибок, спасибо.</em>
<?php
echo '</div>';
}

Это не должно иметь к этому никакого отношения. Пробелы и табуляции внутри ваших функций допустимы и не вызывают эту ошибку.

внутри функции вы правы, но если функция выводит что-то напрямую, например: function blabla(){?> <input> <?php code... ?> вывод чего-то <?php code.. }
, то это уже другой случай.

Вы удаляете закрывающий тег PHP (?>) в конце каждого файла. Также удаляете все пробелы после закрывающего тега PHP (?>).
При активации плагина просто проверяете, существует ли таблица или нет.
Я устранил проблему с помощью следующего кода:
if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
$sql = "CREATE TABLE {$table_name}(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(250),
email VARCHAR(250),
PRIMARY KEY (id)
);";
dbDelta($sql);
}
