Я использую Laravel 5 (чтобы быть конкретным, версия laravel/framework "v5.0.27" ), с драйвером session = 'file'.
Я разрабатываю 64-разрядную машину Windows 7.
Я заметил, что иногда (раз в неделю или около того) я неожиданно и случайно выхожу из системы. Иногда это происходит даже сразу после входа в систему. Я добавил сообщения журнала в мой логический код, но код журнала не был запущен. Laravel вел себя так, как будто он полностью потерял файл сеанса.
Еще одна серьезная проблема заключалась в том, что иногда после отладки сессий (с использованием xdebug и Netbeans) Laravel начал проигрывать и другие файлы - настройки .env, некоторые файлы JS debugbar и т.д. В журнале ошибок были такие сообщения, как:
[2015-07-08 13:05:31] local.ERROR: exception 'ErrorException' with message 'mcrypt_encrypt(): Key of size 7 not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported' in D:\myproject\vendor\laravel\framework\src\Illuminate\Encryption\Encrypter.php:81
[2015-07-08 13:05:31] local.ERROR: exception 'PDOException' with message 'SQLSTATE[HY000] [1044] Access denied for user ''@'localhost' to database 'forge'' in D:\myproject\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:47
Это ясно говорит о том, что файл .env не был прочитан Laravel, поэтому он использует настройки по умолчанию:
'database' => env('DB_DATABASE', 'forge'),
'key' => env('APP_KEY', 'somekey'),
Потеря файлов происходила редко, может быть, раз в месяц или около того, и это всегда происходило после сеансов отладки. Мне всегда приходилось перезапускать Apache, чтобы он снова работал.
Чтобы стресс-тест системы и достоверность воспроизведения вопросов, я использовал быстрый взлом в моем контроллере Angular:
setInterval(function(){
$scope.getGridPagedDataAsync();
}, 500);
Это просто базовый запрос данных от Angular к Laravel.
И это все - теперь я могу воспроизвести проигрывание сессии и потерять .env через 3 минуты или меньше.
Я разработал AJAX-интенсивные веб-приложения ранее на том же ПК с тем же Apache + PHP, но без Laravel, без .env, и я раньше не замечал таких проблем.
Во время отладки через код я узнал, что Laravel не использует встроенные сессии PHP вообще, но реализовал свой собственный сеанс на основе файлов. Очевидно, что он не обеспечивает такую же надежность, как и PHP-сессии по умолчанию, и я не уверен, почему.
Конечно, в реальных сценариях мое приложение не будет таким интенсивным AJAX, но в моих опытах в некоторых случаях достаточно всего двух одновременных запросов AJAX, чтобы потерять сеанс.
Я видел некоторые связанные отчеты об ошибках в Laravel для различных вопросов сессии. Однако я еще ничего не видел о dot-env, но, похоже, он страдает от той же проблемы.
Я предполагаю, что Laravel не использует блокировки файлов и ожидания, поэтому, если файл по какой-либо причине не может быть прочитан (возможно, заблокирован каким-то параллельным процессом или Apache), то Laravel просто отказывается и возвращает все, что может.
Есть ли хорошее решение для этого? Может быть, это специфично для Windows, и проблемы исчезнут на машине Linux?
Любопытно, почему разработчики Laravel (или Symfony) еще не исправили свой файл сеансовых файлов. Я знаю, что блокировка/ожидание замедлит его, но было бы здорово хотя бы иметь возможность включить "надежные сеансы".
Тем временем я попытаюсь выполнить код Laravel и посмотреть, смогу ли я придумать какое-нибудь "быстрое и амбициозное" исправление, но было бы гораздо лучше иметь какое-то надежное и "лучшее" решение.
Обновление о .env
Проблема не связана с блокировкой файлов. Я нашел отчет об ошибке Laravel для проблемы .env, который привел меня к связанному отчету для проекта Dotenv, который, в свою очередь, говорит, что это основная проблема PHP. Меня беспокоит то, что дотенвские разработчики говорят, что Дотенв никогда не предназначался для производства, но Ларавель, похоже, полагается на Дотенва.
В https://github.com/laravel/framework/pull/8187 похоже решение, которое должно работать в одном направлении, но некоторые комментаторы говорят, что в их случае проблема была противоположной. Кто-то, называемый crynobone, дал умный фрагмент кода, чтобы попробовать:
$value = array_get($_ENV, $key, getenv($key));
Появилось другое предложение использовать "makeMutable()" как для Dotenv, так и для Laravel Githubs, но комментаторы сообщают, что это может нарушить тесты.
Итак, я попробовал crynobone, но для меня это не сработало. Во время отладки я узнал, что в случае, когда что-то ломается для одновременных запросов, ключ $не может быть найден ни в getenv(), ни в $_ENV, ни даже в $_SERVER. Единственное, что сработало (quick & dirty experminet), заключалось в том, чтобы добавить:
static:: $cached [$ name] = $value;
в класс Dotenv, а затем в helpers.php env(), я вижу, что:
Dotenv::$cached[$key]
всегда хорош, даже когда $_ENV и getenv оба ничего не дают.
Хотя Dotenv не предназначался для производства, я не хочу менять рабочий процесс развертывания и конфигурации.
Далее мне придется исследовать проблемы сессии...
Добавление
Связанные отчеты об ошибках Laravel (некоторые даже из версии 4. и, похоже, не исправлены): https://github.com/laravel/framework/issues/4576
https://github.com/laravel/framework/issues/5416
https://github.com/laravel/framework/issues/8172
и старую статью, которая проливает свет на то, что происходит (по крайней мере, с проблемами сеанса): http://thwartedefforts.org/2006/11/11/race-conditions-with-ajax-and-php-sessions/