Кэширование PHP без вмешательства в права доступа к файлам (также, Как эмулировать переменные ASP-приложения в PHP)

Я пытаюсь реализовать какое-то кэширование в PHP-скрипте, который будет использоваться многими клиентами / сайтами, которые будут развернуты довольно нетехническими пользователями с использованием различных веб-хостов. Из-за нетехнического характера пользователей, я бы хотел не просить их настраивать права доступа к файлам. Кэширование должно происходить между сеансами, поэтому использование переменных сеанса запрещено. Если бы я кодировал это в ASP, я бы использовал переменные приложения, но они не существуют в PHP (насколько мне известно)

У кого-нибудь есть какие-либо предложения о том, как этого добиться?

Вот некоторые возможности, которые я рассмотрел, любые комментарии по ним будут полезны:

  • Кэширование с помощью файлов в системных временных папках - я мог бы использовать sys_get_temp_dir() (или какую-нибудь аналогичную функцию на PHP4), чтобы помочь найти такую ​​папку. Недостатком здесь является то, что он, вероятно, не будет работать на хостах, использующих ограничение openbase_dir
  • На каком-то веб-сайте, на котором я смотрел, упоминалось, что PHP заставляет все пользовательские сеансы использовать одно и то же состояние сеанса, заставляя переменные сеанса действовать как переменные сеанса. Конечно, я не могу найти этот пост сейчас... В любом случае это кажется страшным. (Я обновлю этот вопрос ссылкой на этот пост, как только найду его снова)
  • Использовать стороннее хранилище данных, такое как Amazon Simple Storage Service - похоже, излишне
  • Кэшируйте данные на сервере, которым я управляю, и заставляйте клиента загружать оттуда новые данные при каждом попадании.

Еще раз, любые комментарии по этим идеям или любые новые будут оценены.

ОБНОВЛЕНИЕ: я пытался использовать session_id() для использования общего состояния сеанса, но это не работает. Каждый сеанс поддерживает свой собственный "GlobalCache", есть идеи почему?:

// This code doesn't work, but the similar code in my answer does!

function test() {
    if (!$_SESSION['session_count']) $_SESSION['session_count'] = 0;
    $_SESSION['session_count']++;


    $count = get_cache( 'count' );

    print "pre application count: $count<br>";

    if ( !$count )
        $count = 0;

    $count++;

    print "session_id: " . session_id() . "<br>";
    print "post application count: $count<br>";
    print "session_count: " . $_SESSION['session_count'] . "<br>";

    set_cache('count', $count);
}


function set_cache( $name, $value ) {
    $old_session = session_id();
    print "old_session (set): $old_session<br>";

    session_id("GlobalCache");
    print "new_session (set): " . session_id() .  "<br>";

    $_SESSION[$name] = $value;
    session_id( $old_session );
}

function get_cache( $name ) {
    $old_session = session_id();
    print "old_session (get): $old_session<br>";

    session_id("GlobalCache");
    print "new_session (get): " . session_id() .  "<br>";

    $value = $_SESSION[$name];
    session_id( $old_session );
    return $value;
}

session_start();
test();

ОБНОВЛЕНИЕ: некоторые предложили использовать memcached, который для некоторых является отличным решением, но, поскольку у меня нет контроля над средой конечного сервера, это не вариант. Идея состоит в том, чтобы иметь сценарий, с помощью которого люди могли бы просто подключиться по FTP к учетной записи общего хостинга, которая работает из коробки.

ОБНОВЛЕНИЕ: кто-то предложил создать мою собственную папку кэша со сценарием, но разве мне не нужно было создавать такую ​​папку внутри папки, у которой уже были разрешения на запись?

ОБНОВЛЕНИЕ, РЕШЕНИЕ НАЙДЕНО: В итоге я выяснил проблемы в моем глобальном сценарии сеанса и опубликовал свой собственный ответ на этот счет. Спасибо всем за помощь.

6 ответов

Решение

Хорошо, я понял, как это сделать, эмулируя переменные приложения в стиле ASP, используя общее / глобальное состояние сеанса. Два ключевых изменения из моего нерабочего кода в соответствующем обновлении:

  1. Чтобы переключить состояние сеанса, мы должны завершить текущий сеанс, переключиться на новый, а затем запустить его. Я инкапсулировал этот процесс в switch_session()

  2. Так как мы меняем идентификаторы сеансов, мы должны буферизовать вывод страницы с помощью ob_start()/ob_end_flush(), чтобы cookie сеанса не отправлялись слишком рано.

Далее следует полный рабочий код (тоже вычищен!). Это можно легко проверить, загрузив страницу в IE и окне Firefox, и перезагрузив каждый раз несколько раз, чтобы увидеть рост счетчиков:

<?php
function test() {

    // Do a regular session count
    print "session_id: " . session_id() . "<br>";
    if (!$_SESSION['session_count']) $_SESSION['session_count'] = 0;
    $_SESSION['session_count']++;
    print "session count: " . $_SESSION['session_count'] . "<br>";


    // Do an application count
    $count = get_cache( 'count' );
    if ( !$count ) $count = 0;
    $count++;
    print "application count: $count<br>";
    set_cache('count', $count);
}


function set_cache( $name, $value ) {
    $old_session = switch_session("GlobalCache");
    $_SESSION[$name] = $value;
    switch_session( $old_session );
}

function get_cache( $name ) {
    $old_session = switch_session("GlobalCache");
    $value = $_SESSION[$name];
    switch_session( $old_session );
    return $value;
}

function switch_session( $session_id ) {

    // switch the session and return the original
    $old_id = session_id();

    session_write_close();
    session_id($session_id);
    session_start();
    return $old_id;
}

ob_start();
session_start();
test();
ob_end_flush();
?>

Используйте вашу собственную директорию кеша в директории вашего приложения. При этом вам не придется бороться с различными настройками сервера и / или PHP и получать лучшую переносимость.

Вы можете использовать сеансы с фиксированным ключом сеанса.

http://de.php.net/manual/en/function.session-id.php:

session_id ([id]) используется для получения или установки сессии id для текущей сессии. Если указан идентификатор, он заменит текущий идентификатор сессии. session_id() должен быть вызван перед session_start() для этой цели.

Я голосую за "Кэширование данных на сервере, которым я управляю, и чтобы клиент загружал оттуда новые данные при каждом обращении".

Все остальные пути ведут к определенному безумию.

Проверьте memcached для php- он работает очень хорошо.

http://www.php.net/memcache

Я использовал обновленную функцию автора как способ кэширования простого результата запроса к базе данных, так как ожидал высокой нагрузки. Я также сохранил временную метку, чтобы я мог определить, как часто страница будет обновлять результат базы данных, а не просто принимать кэшированное значение.

Я могу вам сказать, что эта функция кэширования имела намного худшую производительность, чем прямая обработка базы данных при каждом запросе. Я на самом деле убил сервер. Как только я переключился на простой запрос к базе данных, сервер заработал на полной скорости, и довольно большая нагрузка даже не была замечена.

Другие вопросы по тегам