0

So I'm getting the dreaded

Warning: Cannot modify header information - headers already sent

error message when trying to redirect to a success page on my Wordpress plugin.

The issue is, I'm using wp_safe_redirect as instructed in the Codex like this:

wp_safe_redirect(admin_url("admin.php?page=bv_before_after&msg=4"));
exit;

But what's frustrating, is the files that seem to be having the issue, are both Wordpress core files:

(output started at /var/www/html/wp-includes/formatting.php:4586) in /var/www/html/wp-includes/pluggable.php on line 1228

Lots of tutorials talk about OB_flush(), but there are two sides of every thing I've found so far. There doesn't seem to be anything that seems to explain what's happening in my situation, and why.

I don't think it's a whitespace issue in my plugin file, as I've removed all of that. I'm not too good on creating WP plugins, this is my first or second probably. Any ideas as to what I can do?

EXCERPT: This is a portion from the start of the file, to the end of the function that includes the first redirect

<?php
/*
Plugin Name: BellaVou Before & After Manager
Description: Admin interface for managing Before & After photo sets.
Version: 1.0
Author: Lee Collings
*/
function registration_scripts() {
    wp_register_style('style', plugins_url('style.css', __FILE__));
    wp_enqueue_style('fontAwesome','https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css');
    wp_enqueue_style('style');
}
add_action( 'admin_enqueue_scripts', 'registration_scripts' );
add_action('admin_menu','bv_before_after_menu');
function bv_before_after_menu() {
    add_menu_page( 'BV Before & Afters', 'BV Before & Afters', 'manage_options', 'bv_before_after', 'test_init' );
}
function test_init(){
    global $wpdb;
    $msg = isset($_GET['msg']) ? $_GET['msg'] : '';
    $dateFormat = 'd/M/y';
    // Edit URL param
    $editID = isset($_GET['edit']) ? $_GET['edit'] : '';
    $addItem = isset($_GET['add']) ? $_GET['add'] : '';
    // SQL call if editID present
    if ($editID != '') {
        $editItem = $wpdb->get_row("SELECT * FROM wp_before_after WHERE ID = $editID");
    }else{
        $editItem = null;
    }
    // Delete Item
    if(isset($_POST['deleteItem'])) {
        $result = $wpdb->delete( 'wp_before_after', array( 'ID' => $editID ) );
        if($result) {
            wp_safe_redirect(admin_url("admin.php?page=bv_before_after&msg=4"));
            exit;
        } else {
            $msg = array('danger','The entry could not be deleted');
            echo '<div class="notice notice-'.$msg[0].'"><p>'.$msg[1].'</p></div>';
        }
    }
Lee
  • 4,187
  • 6
  • 25
  • 71
  • 2
    you cannot safely rely on that message since wordpress uses actions and filters to allow for code to be injected into those locations, php will hit an error and make it seem like that file is the problem, when actually it's some other plugin somewhere running an action - you're best using a [backtrace](http://php.net/manual/en/function.debug-backtrace.php) to find the actual problem location – naththedeveloper Mar 23 '16 at 15:06
  • I have several `wp_safe_redirect`s in the PHP File, depending on what action is performed. And I'm using `exit;` before that's what the Codex instructs..? – Lee Mar 23 '16 at 15:07
  • Please show more of your code. If there is *any* output before the redirect, it wont work. – rnevius Mar 23 '16 at 15:08
  • Possible duplicate of [How to fix "Headers already sent" error in PHP](http://stackoverflow.com/questions/8028957/how-to-fix-headers-already-sent-error-in-php) – rnevius Mar 23 '16 at 15:08
  • It's not a duplicate, as this question has more specifics that are related to Wordpress, and understanding why it's happening (I already know it's because no output can be sent). So far essentially I've proven that no one can really answer my question... – Lee Mar 23 '16 at 15:13
  • It is a duplicate. This has nothing to do with WordPress core files, as @naththedeveloper mentioned. Without seeing more of your code (specifically, what happens before the redirect), we can't help you debug this. – rnevius Mar 23 '16 at 15:15
  • Will the above code help? Without wanting to give too much away, it's from the very beginning of the file, to the end of the function that includes the first `wp_safe_redirect` – Lee Mar 23 '16 at 15:16
  • `bv_before_after_menu()`, it's just above it – Lee Mar 23 '16 at 15:18
  • 1
    `add_menu_page()` is too late to use `wp_safe_redirect()` (because there has already been output by WP in the Admin). You'll need to add the `isset($_POST['deleteItem'])` logic to an earlier hook (ideally, `init` or similar) – rnevius Mar 23 '16 at 15:21
  • Not sure if this question will help you: http://stackoverflow.com/questions/11419028/redirect-from-add-menu-page – rnevius Mar 23 '16 at 15:22
  • So could I just move the test_init function above the add_menu_page one? – Lee Mar 23 '16 at 15:23
  • Probably not, because it's still being run during the `admin_menu` action hook (at which point there has already been output by WP elsewhere in the Admin) – rnevius Mar 23 '16 at 15:26
  • Sorry I don't understand. How can I use an earlier hook, if moving the order of the code won't matter? The earlier hook will have the same effect surely? Can you explain your comment about `add_menu_page`. Which order should I ideally be putting my functions then? – Lee Mar 23 '16 at 15:27
  • Also, I don't know if it's worth adding, but it's strange how this is only happening on the live production site. My local devlopment with all errors and warnings turned on, doesn't have any problem at all, and happily performs the redirect, and shows the wordpress notice at the top. Could this suggest that it's not the code, but the server config? – Lee Mar 23 '16 at 15:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/107154/discussion-between-lee-and-rnevius). – Lee Mar 23 '16 at 16:15
  • @rnevius Hey, are you able to continue to assist me with this? I Could really do some explanation of what you were suggesting. Are you in a way saying maybe I should move the test_init to a different PHP File, away from the admin_menu hook? Will that work? – Lee Mar 24 '16 at 10:51

0 Answers0