Неизвестное свойство (w)

Я получаю эту ошибку на моем сервере, размещенном на nginx:

 Fatal error: TimeElapsedString(): Unknown property (w) in /var/www/script/system/framework.engine.php on line 51 

TimeElapsedString:

function TimeElapsedString($datetime, $full = false)
{
    date_default_timezone_set('UTC');

    $now = new DateTime;
    $ago = new DateTime($datetime);
    $diff = $now->diff($ago);

    $diff->w = floor($diff->d / 7); // LINE 51
    $diff->d -= $diff->w * 7;

    $string = array
    (
        'y' => 'year',
        'm' => 'month',
        'w' => 'week',
        'd' => 'day',
        'h' => 'hour',
        'i' => 'minute',
        's' => 'second',
    );

    foreach ($string as $k => &$v)
    {
        if ($diff->$k)
        {
            $v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
        }
        else
        {
            unset($string[$k]);
        }
    }

    if (!$full) $string = array_slice($string, 0, 1);
    return $string ? implode(', ', $string) . ' ago' : 'just now';
}

Все, что работает отлично на локальном хосте (wamp) версия php на размещенном сервере - 5.3.3, поэтому я действительно вижу эту проблему. также я использовал эту функцию на другом сервере nginx, а также без проблем.

функция из этого ответа: Преобразование временной метки в прошлое в PHP, например, 1 день назад, 2 дня назад...

Ответ 1

Как сказал @Tularis, это потому, что вы не можете назначать новые свойства внутренним объектам PHP в PHP 5.3. Это связано с тем, что метод DateTime diff() возвращает объект, а новые свойства объекта не могут быть созданы "на лету".

object(DateInterval)#8 (8) {
  ["y"]=>
  int(0)
  ["m"]=>
  int(6)
  ["d"]=>
  int(11)
  ["h"]=>
  int(9)
  ["i"]=>
  int(45)
  ["s"]=>
  int(10)
  ["invert"]=>
  int(1)
  ["days"]=>
  int(195)
}

Чтобы исправить это, я преобразовал $now->diff($then) в массив,

array(8) {
  ["y"]=>
  int(0)
  ["m"]=>
  int(6)
  ["d"]=>
  int(11)
  ["h"]=>
  int(9)
  ["i"]=>
  int(45)
  ["s"]=>
  int(10)
  ["invert"]=>
  int(1)
  ["days"]=>
  int(195)
}

и сделать код отражением изменений, используя $diff как массив, а не объект,

// Find how much time has elapsed since now()
// from: /info/27883/converting-timestamp-to-time-ago-in-php-eg-1-day-ago-2-days-ago/204360#204360
//
function timeElapsedSinceNow( $datetime, $full = false )
{
    $now = new DateTime;
    $then = new DateTime( $datetime );
    $diff = (array) $now->diff( $then );

    $diff['w']  = floor( $diff['d'] / 7 );
    $diff['d'] -= $diff['w'] * 7;

    $string = array(
        'y' => 'year',
        'm' => 'month',
        'w' => 'week',
        'd' => 'day',
        'h' => 'hour',
        'i' => 'minute',
        's' => 'second',
    );

    foreach( $string as $k => & $v )
    {
        if ( $diff[$k] )
        {
            $v = $diff[$k] . ' ' . $v .( $diff[$k] > 1 ? 's' : '' );
        }
        else
        {
            unset( $string[$k] );
        }
    }

    if ( ! $full ) $string = array_slice( $string, 0, 1 );
    return $string ? implode( ', ', $string ) . ' ago' : 'just now';
}

Кстати, я считаю, что исходный вопрос OP исходит из этого поста, где его проблема осталась без ответа: fooobar.com/info/27883/...