Dezvoltare Plugin WordPress - Mesajul Headers Already Sent
Dezvolt pluginuri WordPress. Când îmi activez pluginul, primesc următorul mesaj:
Pluginul a generat 293 caractere de output neașteptat în timpul activării. Dacă observați mesaje de tipul "headers already sent", probleme cu feed-urile de sindicalizare sau alte probleme, încercați să dezactivați sau să ștergeți acest plugin.
Pluginul funcționează foarte bine dar nu știu de ce primesc acest mesaj. Pluginul meu este: http://wordpress.org/extend/plugins/facebook-send-like-button/

Această eroare este de obicei cauzată de spații sau linii goale înainte de tag-ul de deschidere <?php
sau după tag-ul de închidere ?>
.
Consultă această pagină pentru a vedea câteva soluții: Cum rezolv problema cu avertismentul "Headers already sent"?
ACTUALIZARE
După ce am analizat codul plugin-ului tău, am observat că nu ai un tag de închidere PHP. Pe ultima linie, adaugă ?>

Fișierele PHP nu au nevoie de tag-ul de închidere ?>
. De fapt, o modalitate de a garanta că nu vor apărea probleme de tipul Headers already sent
este să nu folosiți deloc tag-ul de închidere.

Aceasta a fost problema mea. Aveam o grămadă de linii goale după tag-ul de închidere ?>
.

Nu recomandăm folosirea tag-ului de închidere PHP. Este o practică proastă care duce la probleme de tipul celor din OP și contravine standardelor de codare WordPress Core (vezi https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#remove-trailing-spaces)

Presupun că primești o eroare PHP, care generează output înainte ca antetele să fie trimise. Dacă ai E_NOTICE
activat, apelarea $_POST['foo']
poate genera o "Notificare: variabilă nedefinită" dacă acea variabilă nu este setată.
Practică recomandată: nu presupune niciodată nimic despre variabilele GET, POST, COOKIE și REQUEST. Verifică întotdeauna mai întâi folosind isset()
sau empty()
.
if ( isset( $_POST['foo'] ) ) {
$foo = (string) $_POST['foo'];
// aplică mai multe operații de curățare aici dacă este necesar
}

La începutul funcției tale de activare pune un ob_start();
și la final pune un trigger_error(ob_get_contents(),E_USER_ERROR);
Apoi încearcă să activezi pluginul tău și vei putea vedea ce reprezintă de fapt 'generated 293 characters of unexpected output'. De aici încolo depanarea va fi mai ușoară (fie prin eliminarea caracterelor de linie nouă, fie prin rezolvarea unor erori).

Știu că aceasta este o întrebare veche și are deja un răspuns acceptat. Există multe răspunsuri care acoperă ce ar putea fi problema de activare. Cu toate acestea, niciunul dintre răspunsuri nu abordează cu adevărat problema de bază a modului în care să depanezi problemele legate de activarea plugin-urilor.
Dacă intenționezi să dezvolți plugin-uri pentru WordPress, ar trebui să folosești instrumentele potrivite pentru această sarcină. Unul dintre acestea este Debug Bar. Acesta este un plugin care te ajută să depanezi problemele în WordPress. Dacă ești un dezvoltator de plugin-uri, ar trebui să fie în toolbox-ul tău.
Debug Bar are o serie de suplimente - plugin-uri pentru plugin, dacă vrei. Unul dintre acestea este Debug Bar Plugin Activation, care îți va afișa eroarea PHP generată la activarea plugin-ului. Odată ce știi care este eroarea PHP care determină trimiterea headerelor, atunci știi unde trebuie să te uiți pentru a o corecta. Crede-mă, a ști care este eroarea poate să-ți economisească o tonă de timp în loc să încerci să ghicești care ar putea fi eroarea.

Nu sunt sigur că asta este problema, dar sunt destul de convins că da.
Trebuie să folosești un callback valid ca al doilea argument în register_activation_hook()
:
register_activation_hook(__FILE__,'twl_tablo_olustur');
Din câte pot vedea, nu ai definit funcția twl_tablo_olustur()
nicăieri. Acest lucru ar explica cu siguranță ieșirea neașteptată (eroare PHP generată din încercarea de a apela o funcție inexistentă) și ar explica de ce funcționează corect în toate celelalte circumstanțe.

Am tendința să primesc aceste mesaje des când afișez mesaje de depanare pentru plugin-uri/teme, mai ales când afișez conținut înainte ca wp_header să fie apelat.
Dacă afișezi orice caractere, atunci cred (ar putea fi greșit aici) că există o declarație implicită de header, așa că atunci când apelul normal header() apare, primești eroarea pentru că nu poți avea 2 declarații de header.
Poți folosi ob_start() pentru a bufferiza output-ul, ceea ce ar trebui să elimine eroarea - verifică comentariile de aici: http://php.net/manual/en/function.header.php

Analizând ultima revizie a plugin-ului (381724), problema este Prea multe spații
de fiecare dată când doriți să creați această structură:
function blabla(){
<= spațiu
ceva...
}
în codul vostru folosiți TAB și nu spații.
Iată codul vostru unde am înlocuit toate spațiile cu tab-uri și nu primesc niciun mesaj la activare:
<?php
/*
Plugin Name: Facebook Send Button By Teknoblogo.com
Plugin URI: http://www.teknoblogo.com/facebook-gonder-butonu-eklenti
Description: Adaugă butoanele Facebook Send și Like la articolele tale! Autor: <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 "Tipul butonului nu a putut fi obținut!";
}
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( __('Nu aveți permisiuni suficiente pentru a accesa această pagină.') );
}
echo '<div class="wrap">';
?>
<h2>Facebook Send & Like Button</h2>
<?
if($_POST["fgb_gonder"])
{
echo "<h3>salvat</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">
Afișează butoanele Facebook <select name="fgb_yer">
<option value="u" <?php if($fgb_admin_yer == "u"){echo "SELECTED";}?>>înainte de conținut</option>
<option value="a" <?php if($fgb_admin_yer == "a"){echo "SELECTED";}?>>după conținut</option>
</select> și vreau <select name="fgb_buton">
<option value="snl" <?php if($fgb_admin_buton=="snl"){echo "SELECTED";}?>>butoanele send și like împreună</option>
<option value="send" <?php if($fgb_admin_buton=="send"){echo "SELECTED";}?>>doar butonul send</option>
<option value="like" <?php if($fgb_admin_buton=="like"){echo "SELECTED";}?>>doar butonul like</option>
</select> . <br />
<input type="radio" value="hayir" name="fgb_manual" <?php if($fgb_admin_manual=="hayir"){echo "CHECKED";}?> /> adaugă butoane pentru mine, AUTOMAT <br />
<input type="radio" value="evet" name="fgb_manual" <?php if($fgb_admin_manual=="evet"){echo "CHECKED";}?> /> le pot adăuga eu, MANUAL <br />
<input type="submit" class="button-primary" name="fgb_gonder" value="<?php _e('Salvează modificările') ?>" />
</form>
<br />Dacă folosiți <strong>inserare manuală</strong> , trebuie să adăugați acest cod în tema voastră:
<strong><?php if(function_exists('fgb_ekle')) { fgb_ekle(); }?></strong>
<hr />
<em>Dacă vă place acest plugin, vă rugăm să <a href="http://wordpress.org/extend/plugins/facebook-send-like-button/">votați</a>.
Autor: <a href="http://www.teknoblogo.com">Eray Alakese</a>
Puteți să îmi <a href="mailto:info@teknoblogo.com">trimiteți un email</a> pentru bug-uri, mulțumesc.</em>
<?php
echo '</div>';
}

Asta nu ar trebui să aibă nicio legătură. Spațiile și taburile din interiorul funcțiilor sunt acceptabile și nu produc această eroare.

în interiorul unei funcții ai dreptate, dar dacă funcția afișează ceva direct, de exemplu: function blabla(){?> <input> <?php code... ?> afișează ceva <?php code.. }
atunci situația este diferită.

@MatthewMuro: dacă lași spațiu în interiorul unei funcții e în regulă, dar dacă lași orice spațiu alb/salt de linie după tag-urile de închidere PHP ?>
atunci vei primi eroarea header already send
deoarece acele spații albe în plus vor fi afișate când motorul PHP le parsează.

Eliminați tag-ul de închidere PHP (?>
) de la sfârșitul fiecărui fișier și, de asemenea, eliminați toate spațiile goale după tag-ul de închidere PHP (?>
).
Când activați plugin-ul, verificați dacă tabela există deja sau nu.
Am rezolvat problema cu următorul cod:
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);
}
