• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Cron/deferred problem: Cannot modify header information - headers already sent

Teapot

Well-known member
#1
I'm having some trouble with a cron job that is working, but produces an error in the error log every time it runs. For the life of me, I can't work out why:

Code:
ErrorException: Cannot modify header information - headers already sent by (output started at /home/pcharms/public_html/library/CreativeCorner/Model/Works.php:1) - deferred.php:21

array(3) {
  ["url"] => string(34) "http://pokecharms.com/deferred.php"
  ["_GET"] => array(0) {
  }
  ["_POST"] => array(4) {
    ["_xfRequestUri"] => string(106) "/admin.php?cron/CCorner_UpdateViews/run&_xfToken=1%2C1385546511%2Cb5031f692efcb2484c1938be253b33308cbe40f1"
    ["_xfNoRedirect"] => string(1) "1"
    ["_xfToken"] => string(8) "********"
    ["_xfResponseType"] => string(4) "json"
  }
}
The code that's run by this cron is this:

CreativeCorner_CronEntry_Views
Code:
<?php
class CreativeCorner_CronEntry_Views
{
    public static function runViewUpdate()
    {
        XenForo_Model::create('CreativeCorner_Model_Works')->updateWorkViews();
    }
}
CreativeCorner_Model_Works
Code:
<?php
class CreativeCorner_Model_Works extends XenForo_Model
{

// [unrelated/unexecuted code removed...]

    public function updateWorkViews()
    {
        $db = $this->_getDb();

        $db->query('
            UPDATE cc_work
            INNER JOIN (
                SELECT work_id, COUNT(*) AS total
                FROM cc_work_view
                GROUP BY work_id
            ) AS new_count ON (new_count.work_id = cc_work.work_id)
            SET cc_work.view_count = cc_work.view_count + new_count.total
        ');

        $db->query('TRUNCATE TABLE cc_work_view');
    }

// [...]

}
Anyone have any ideas as to what could be causing this issue?

As always, thanks very much for your time. :)
 

Teapot

Well-known member
#3
I actually fixed it in the end - it's a massive PHP quirk. There was some whitespace before the opening <?php in the model, which PHP was trying to output before setting the headers in deferred.php - because it was outputting whitespace, it was outputting headers, hence the error. Anyway, I removed the offending whitespace and the problem went away.

Thanks for your help @tyteen4a03. :)
 

shawn

Well-known member
#4
What else could be causing this? I have the same problem. Couple of cleanup scripts based loosely on this tutorial to move old/deleted/etc threads. They worked fine under 1.1x, but now under 1.2, the header lines in deferred.php (26-29ish?) trip the cannot-modify-header php error and they fault out. PITA to troubleshoot, too, since manually running the scripts doesn't pipe them through deferred.php.
 

tyteen4a03

Well-known member
#5
What else could be causing this? I have the same problem. Couple of cleanup scripts based loosely on this tutorial to move old/deleted/etc threads. They worked fine under 1.1x, but now under 1.2, the header lines in deferred.php (26-29ish?) trip the cannot-modify-header php error and they fault out. PITA to troubleshoot, too, since manually running the scripts doesn't pipe them through deferred.php.
Code please?
 

shawn

Well-known member
#6
PHP:
<?php
class RSC_MoveThreadCron_CronEntry
{
    public static function runMoveOldThreads()
    {
        $options = XenForo_Application::get('options');

        $threadModel = XenForo_Model::create('XenForo_Model_Thread');
        $nodes = XenForo_Model::create('XenForo_Model_Node')->getViewableNodeList();
       
        $sourceNodes = array();
       
        if (empty($options->xefModeratedForums[0]))
        {
            return;
        }
        else
        {
            $sourceNodes = $options->xefModeratedForums;
        }

        $fetchOptions = array(
            'join' => XenForo_Model_Thread::FETCH_FORUM | XenForo_Model_Thread::FETCH_USER,
            'order' => 'last_post_date',
            'orderDirection' => 'desc',
        );

        $conditions = array(
                'last_post_date' => array('<', XenForo_Application::$time - 86400 * $options->xefExpirationInterval),
                'node_id'    => $sourceNodes,
                'sticky'    => $options->xefStickyThread,
        );
           
        $threads = $threadModel->getThreads($conditions, $fetchOptions);

        if ($threads)
        {
            foreach ($threads as $thread)
            {
                $dw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread');
                $dw->setExistingData($thread);
                $dw->set('node_id', $options->xefRecycleForum);
                $dw->save();
            }
        }
       
    }
    public static function runMoveDeletedThreads()
    {
        $options = XenForo_Application::get('options');

    if ($options->xefDeletedThread === '1')
    {
        if (empty($options->xefModeratedForums[0]))
        {
        return;
        }
        else
        {
        $sourceNodes = array($options->xefModeratedForums);
        }

        $db = XenForo_Application::getDb();
       
         $threads = $db->fetchAll('
                SELECT thread_id
                FROM xf_thread
                WHERE discussion_state = \'deleted\'
                AND node_id IN (' . $db->quote($sourceNodes) . ')
        '); 
       
            if ($threads)
        {
             foreach ($threads AS $thread)
             {
                    $dw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread');
                    $dw->setExistingData($thread);
                    $dw->set('node_id', $options->xefRecycleForum);
                    $dw->save();
                }           
            } 
    }
    }
}
 

shawn

Well-known member
#8
Hm, nothing obvious. I'll let somebody else pass by :p

(Being a PITA: The database fetching and writing bit is probably more suited to be in a Model)
Right, and the thing that gets me is that the script isn't creating any headers -- it's really a bug related to the new(er) deferred.php way of processing cron jobs.... which, unfortunately, I don't know much about.
 

Teapot

Well-known member
#9
It's a PHP quirk, basically. I ended up using an automated CLI-based cleaner of some sort, whose name I unfortunately forget, and it fixed the whitespace issue for me.
 

shawn

Well-known member
#10
It's a PHP quirk, basically. I ended up using an automated CLI-based cleaner of some sort, whose name I unfortunately forget, and it fixed the whitespace issue for me.
No, white space will cause the error, but that's not the problem in my case. I have a <?php at the very beginning of the script and no closing tags.