Сессия PHP не записывается после вывода (echo или print_r на внешний вызов ajax) - PullRequest
12 голосов
/ 12 апреля 2011

У меня возникли серьезные проблемы с отладкой этой конкретной проблемы, и я надеюсь, что кто-то знает, что я делаю неправильно.

У меня есть система Custom CMS, которая использует Paragraphs в качестве строительных блоков, которые обновляются с помощью вызовов Ajax (prototypejs) и функций, которые анализируют фрагменты HTML в заданном порядке, очищают их и сохраняют эти данные в ассоциативных массивах в переменной Session. , Пользователи входят в систему, сессия создана, и я могу без проблем проверить эту сессию на каждой странице, которая мне нужна. Система работает непосредственно на определенных веб-сайтах, поэтому пользователь может видеть свои обновления в режиме реального времени и просматривать сайт, как это делал бы обычный пользователь, но редактировал. Итак, ничего нового здесь. Но вот странная вещь.

Сайт пользователя в режиме редактирования (администратор вошел в систему): путь "/"

После проверки зарегистрированного статуса функция обрабатывает редактируемое содержимое и сохраняет ассоциативный массив в сеансе, а также запускает некоторые объекты javascript для редактирования каждого абзаца. Данные на самом деле сохранены, я могу использовать внешний скрипт, чтобы проверить, есть ли он там после завершения этого php-скрипта. Если я загружаю новую страницу (новый контент), сессия обновляется с новыми данными)

Администратор изменяет абзац с помощью Inplaceeditor, и этот фрагмент HTML отправляется через Ajax в скрипт php, который запускает именованный сеанс, считывает данные текущего сеанса, проверяет, следует ли изменить, добавлять или удалять абзац, и переназначает значения для существующие ключи массива в $_SESSION. если я сделаю var_dump() o print_r для $_SESSION после назначения новых данных, то там. После этого скрипт повторяет обработанный html, и ajax обновляет исходный абзац на вызывающей странице.

Этот скрипт находится в /admin/cms/...etc, что означает как минимум 4 директории внутри корня сайта.

Когда сценарий заканчивается, я проверяю, используя тот же сценарий дампа сеанса, чтобы увидеть, действительно ли данные были записаны / переданы, но нет, $_SESSION имеет только исходные данные с вызывающей страницы. Тот же ID, то же имя сеанса, тот же session_start(), но данные не записываются. Вся эта операция очень быстрая, поэтому, хотя это может быть проблемой со скоростью, сценарии заканчиваются, прежде чем session_write_close сможет выполнить свою работу.

Но если я добавлю новый ключ в массив $_SESSION и добавлю туда некоторые данные, данные будут обновлены и записаны. Если я ничего не выводю в этом скрипте и просто обрабатываю данные и устанавливаю переменные сеанса, он также обновляется и записывается.

Как будто некоторые члены массива $_SESSION заблокированы для обновления.

Что я сделал, чтобы отследить эту ошибку, и что я уверен, что я не делаю неправильно.

  • 1.- register_globals выключены, конечно
  • 2.- session_name() и session_start() присутствуют всегда и в заданном
    порядок. Раньше у меня было несколько
    session_start() - закрыть на той же странице
    использовать несколько именованных сессий, но уточнить проблему это не дольше поэтому.
  • 3.- Я использую session_write_close() после обработки данных сеанса. Также
    пробовал без, позволяя PHP решить когда совершать данные, но не везет.
  • 4.- Я использую только куки для SID.
  • 5.- сеансы хранятся в / tmp, я вижу, как обновляются данные.
  • Я также пытался использовать пользовательское сохранение обработчик на БД, но та же проблема,
    "_write" вызывается только когда нет выходных данных.
  • Я искал php.net, stackoverflow, google и т. Д. По этой теме. Я никогда не спрашиваю без расследования, это мой первый раз за многие годы ... но это настолько нелогично, что это должно быть что-то крошечное, о чем даже не думают.

Самое странное, что когда я просто обрабатываю данные без вывода, $_SESSION обновляется нормально. Но если впоследствии я изменю этот сценарий, добавив вывод и попробовав снова, вместо того, чтобы просто иметь новое (последнее) значение, я получу исходное значение, то, которое было создано вызывающей страницей на первом месте, иногда после воспроизведения нескольких раз! PHP не может кэшировать значения между скриптами или? У меня нет глобальных переменных.

Я гдействительно невежественный Эта система работала безупречно на PHP4.3, так как я использую 5.3.3 для двух месяцев мои пользователи, где калибровка данных, где перепутаны, так что я проверил и да, есть серьезные проблемы. Сегодня я обновил (5.3.6) и не могу зафиксировать значения этого сеанса.

Код скрипта, вызываемый через Ajax:

<?
session_cache_limiter('nocache'); 
session_name("CMS_ses");
session_start();
include('../htmLawed/htmLawed.php');
include("utils_cms.php");
include("../../../php/utils_array.php");

$value=$_POST['value'];
$editorId=$_POST['editorId'];
$clase=$_POST['clase'];
$editorId=str_replace("pre","",$editorId);
$value=html_entity_decode(stripslashes($value),ENT_QUOTES);
if (strlen(trim($value))==0)
    {
    die();
    }
$value="<div id=\"$editorId\"  class=\"$clase\">$value</div>";

$newXHTML=$value;
$retorno=CMS_nuevoBloque($newXHTML,$editorId);
$_SESSION['data']['CMSeditores']=$retorno[1];   
$_SESSION['data']['CMScont']=$retorno[2];   
session_write_close();

print_r($retorno[0]); //Offending part...without everything works
?>

тут действительно ничего странного .... код главной страницы еще проще, никаких странных директив php и т. Д.

Вот заголовок страницы звонящего

include 'php/db.php';
$len=$_GET['len'];
$sec=$_GET['sec'];
$cont=$_GET['cont'];
$admfin=$_GET['admfin'];
$fecha=$_GET['fecha'];
$token=$_GET['token'];
$cur=$_GET['cur'];

$PHP_SELF=$_SERVER['PHP_SELF'];
session_cache_limiter('nocache');
session_name("CMS_ses");
session_start();

$passvar='';
unset($adm);
if ((!empty($_SESSION['cms_logged'])) and (!isset($admfin)) )
    {
    $nivelpermisos=$_SESSION['cms_logged_group'];
    $useractual=$_SESSION['cms_logged'];
    $adm=1;

    }
elseif (empty($_SESSION['cms_logged']))
    {
    unset($useractual);
    }
    //.........rest of the code  

ОБНОВЛЕНИЕ: Я провел ночные тесты и обнаружил что-то, чего не понимаю. ПОМОГИТЕ, пожалуйста: Это касается не только сессий, но и Mysql Querys. Тот же код, но вместо того, чтобы пытаться записать в массив $_SESSION, я сделал простое обновление таблицы Innodb, используя session_id. Когда я вывожу некоторый код, обновление действительно выполняется (я могу вывести строку запроса и без mysql_error() или уведомления), но при проверке базы данных строка не обновляется. Выпуск выходных данных, если скрипт и Query действительно зафиксированы. Общим является то, что сеансы запускаются и выводится.

Я перезапустил Apache и т. Д. (Кто знает), но не повезло. Тогда я сделал что-то действительно глупое, потому что это вещь на стороне сервера. Я изменил свой браузер на Firefox (используя сафари) и все работает! Хорошо, перепроверьте, вернитесь в сафари, ничего не работает. Оба бегут бок о бок, одна и та же проблема. PHP на стороне сервера, как разные браузеры могут обрабатывать код по-разному, может ли браузер сказать откат apache, запрос не обработан или вызвать один и тот же скрипт дважды без уведомления (проверено, что консоль разработчика safaris и скрипт вызывается только один раз)? Может ли safari переслать данные молча, потому что он «думает», что ajax провалился? Я проверил заголовки, используя Firebug и инструменты разработчика Safaris, ничего странного, но всякий раз, когда я делаю Ajax-вызов с safari, страница вызывающего абонента перезагружает данные (соединение Aka с сервером ...).

Я действительно ничего не понимаю.

Ответы [ 6 ]

1 голос
/ 09 августа 2011

Спасибо за вашу помощь. Я делал все в правильном порядке, но данные сессии все еще не записывались. Имена сессий там, где это необходимо, потому что иногда мы тестируем множество сайтов в одном домене, используя одну и ту же пользовательскую CMS. Итак, наконец, после большого количества испытаний и безуспешно, я обнаружил, что глобальные регистры были активны на этом сервере (мы никогда не использовали его, код был написан с учетом этой опции, разумеется), но это портит сессии !. Отключение сделало огромное изменение. Нет больше проблем. Я также сделал пользовательский обработчик сеансов в БД, чтобы я мог отслеживать проблемы более централизованно. Вывод: никогда не используйте глобальные регистры + именованные сеансы, сложные данные в сеансах. Во всяком случае, я дам этому вопросу больше времени и больше тестов. Ajax-вызовы также иногда бывают слишком быстрыми, мне пришлось поместить команду сна, чтобы запись данных сеанса была действительно завершена. Спасибо

1 голос
/ 02 августа 2011

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

Возможно, это решит (или поможет вам решить) вашу проблему.

http://php.net/manual/en/function.register-shutdown-function.php

0 голосов
/ 04 августа 2011

Вопрос: Вы вызываете session_start () первым делом ... до ЛЮБОГО вывода в браузер и до назначения каких-либо переменных?

Звучит глупо, но попробуйте.

Такжепочему вы используете имена сеансов?Это на самом деле не нужно, если у вас не много переменных сеанса с одним и тем же именем, предназначенных для разных целей, и если это так, то вам нужно сначала это исправить!

0 голосов
/ 04 августа 2011

Есть ли причина, по которой вы устанавливаете имя сеанса дважды?В прошлом у меня были проблемы, когда я устанавливал сеанс без имени, затем другой фрагмент сценария (не мой) называл сессию.Даже в конце скрипта мне удалось распечатать переменную сеанса, но как только я перешел на новую страницу, мой сеанс был забыт.Только когда я скопировал имя, включенное во 2-й сценарий, в мой сеансовый вызов, он был решен.

Убедитесь, что не используются другие имена сеансов;Кроме того, может быть, попробуйте только назвать сеанс один раз, при первом вызове сеанса?

0 голосов
/ 31 июля 2011

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

удалить сеансовые куки перед обновлением страницы в целях тестирования:)

Убедитесь, что вы не назначаете никакие массивы с ключом, содержащим символ канала (|). Это предотвратит сериализацию и сохранение данных сеанса.

Do session_regenerate_id (true); во многих случаях session_write_close не имеет значения без session_regenerate_id. или просто сделайте session_start () после session_write_close (), если вы полагаетесь на SID; и в вашем случае я думаю, что это вызывает проблемы у вас, поскольку вы каждый раз заканчиваете текущий сеанс, а не запускаете его для следующей страницы. надеюсь, вы поняли мою точку зрения. Далее, чтобы убедиться, что данные действительно сбрасываются в браузер, используйте ob_end_flush ();

Я не мог понять связь между

$_SESSION['data']['CMSeditores']=$retorno[1];   
$_SESSION['data']['CMScont']=$retorno[2];   

и

$nivelpermisos=$_SESSION['cms_logged_group'];
    $useractual=$_SESSION['cms_logged'];

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

Надеюсь, это вам поможет .:)

0 голосов
/ 29 июля 2011

У меня была похожая проблема, но она возникла несколько лет назад. IE манипулирует заголовком по-своему, и это вызывает странные ошибки в php, которые вы можете найти в архивах php.net.

@ Diego Pino Navarro, см. на этой странице справки , найдите Safari и проблемы с php.

Я также обнаружил, «Safari» забыл «регистрационную информацию http-аутентификации» .

...