Баг при чтении/записи файла

Тема в разделе "PHP", создана пользователем Aizen, 16 апр 2019.

Модераторы: latteo
  1. Aizen

    Aizen Создатель

    Регистр.:
    18 мар 2016
    Сообщения:
    17
    Симпатии:
    4
    Здравствуйте.
    Набросал маленький модуль для подсчета кликов по кнопке. массив со статистикой кодирую в json и записываю в файл.

    Код:
    $button = $_GET['button'];
    
    if( !$button ) exit();
    
    $stats = get_vars("button_stats");
    
    $date = date('Y-m-d');
    
    $count = intval($stats[$date][$button]);
    $count++;
    
    $stats[$date][$button] = $count;
    
    set_vars( "button_stats", $stats );
    Для записи и чтения файла использую функции движка DLE
    Код:
    function set_vars($file, $data) {
       
        $file = totranslit($file, true, false);
       
        if ( is_array($data) OR is_int($data) ) {
           
            file_put_contents (ENGINE_DIR . '/cache/system/' . $file . '.php', json_encode( $data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ), LOCK_EX);
            @chmod( ENGINE_DIR . '/cache/system/' . $file . '.php', 0666 );
           
        }
    }
    
    function get_vars($file) {
        $file = totranslit($file, true, false);
    
        $data = @file_get_contents( ENGINE_DIR . '/cache/system/' . $file . '.php' );
    
        if ( $data !== false ) {
    
            $data = json_decode( $data, true );
            if ( is_array($data) OR is_int($data) ) return $data;
    
        }
    
        return false;   
    }

    В итоге получается что каждые пару часов содержимое файла сбрасывается.
    Предпологаю что проблема в функции записи или чтения с файла. Но не могу понять где именно.
     
  2. borgox

    borgox Создатель

    Регистр.:
    17 янв 2019
    Сообщения:
    15
    Симпатии:
    4
    С DLE не сильно знаком, но в вашей функции есть такое -
    file_put_contents (ENGINE_DIR . '/cache/system/' . $file . '.php', json_encode( $data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ), LOCK_EX);

    Как видите вы кладете информацию в папку cache, есть подозрения что при сбросе кеша вы просто удаляете свой файл, и он обнуляется :)
     
  3. latteo

    latteo Эффективное использование PHP, MySQL

    Moderator
    Регистр.:
    28 фев 2008
    Сообщения:
    1.611
    Симпатии:
    1.539
    При чтении файла нет блокировки, в итоге может возникнуть коллизия.
    Второй момент, с которым сталкивался, чтение делал где-то в начале скрипта, а запись через несколько секунд, после выполнения. В итоге подсчёт был неправильный.

    Вообще для этого дела лучше бд использовать, пусть даже SqlLite, с методами типа update ... set counter += 1.

    Либо разбирайтесь как работают блокировки и как вписать их в свою логику:
    Для себя дёргал вот отсюда функции https://github.com/yiisoft/yii2/blob/master/framework/caching/FileCache.php getValue($key) и setValue($key, $value) удалив ненужную логику работы с кешем.
     
  4. Den1xxx

    Den1xxx

    Moderator
    Регистр.:
    15 янв 2014
    Сообщения:
    280
    Симпатии:
    155
    Проблема скорее всего в том, что 2 скрипта одновременно пытаются писать в 1 файл.
    Подобное решал либо блокировкой записи путем создания временного файла, либо использованием БД.
     
  5. jokids

    jokids Писатель

    Регистр.:
    9 май 2019
    Сообщения:
    3
    Симпатии:
    0
    Просто очищается кэш. Нужно изменить папки для сохранения данных и не использовать папки кэша
     
  6. krast90

    krast90 Создатель

    Регистр.:
    4 апр 2008
    Сообщения:
    11
    Симпатии:
    3
    Делайте запись/чтение значений в папку /engine/data/ и не будет пропадать
     
  7. mSnus

    mSnus Постоялец

    Регистр.:
    4 дек 2015
    Сообщения:
    76
    Симпатии:
    28
    я бы проверял результат json_encode, коварная функция:
    То есть если в неё передали не-UTF8 строку, файл запишется пустой.