2011-04-11 13 views
12

Mam poważne problemy z debugowaniem tego konkretnego problemu i mam nadzieję, że ktoś ma pojęcie, co robię źle.Sesja PHP nie została napisana po wyjściu (echo lub print_r na zewnętrznej wywołanie ajax)

Mam działający system Custom CMS, który używa akapitów jako klocków, które są aktualizowane przy użyciu wywołań Ajax (prototypejs) i funkcji, które parsują fragmenty HTML w podanej kolejności, czyszczą je i zapisują te dane w tablicach asocjacyjnych w sesji zmienna. Użytkownicy logują się, sesja jest tworzona i mogę sprawdzić tę sesję bez problemu na każdej stronie, której potrzebuję. System działa bezpośrednio na ostatecznych stronach internetowych, dzięki czemu użytkownik może zobaczyć swoje aktualizacje w czasie rzeczywistym i przeglądać witrynę tak, jak zrobiłby to normalny użytkownik, ale edytował. Nic nowego tutaj. Ale tutaj jest ta dziwna rzecz. site

użytkownika końcowego na tryb edycji (user Administrator zalogowany): ścieżka „/”

Po zalogowaniu status zweryfikowany, funkcja przetwarza edycji treści i zapisuje tablicę asocjacyjną do sesji, zaczyna także niektóre obiekty javascript do edycji każdego akapitu. Dane są zapisywane, mogę użyć zewnętrznego skryptu, aby sprawdzić, czy jest tam po zakończeniu tego skryptu php. Jeśli załaduję nową stronę (nowa treść), sesja zostanie zaktualizowana o nowe dane)

Użytkownik administracyjny modyfikuje akapit przy użyciu Inplaceeditora i ten fragment HTML jest wysyłany przez Ajax do skryptu php, który uruchamia sesję nazwaną, odczytuje dane sesji obecnej, sprawdza, czy akapit powinien zostać zmodyfikowany, dołączony lub usunięty i ponownie przypisuje wartości do istniejących kluczy tablicy w $_SESSION. jeśli zrobię var_dump() o print_r do $_SESSION po przypisaniu nowych danych istnieje. Po tym, jak skrypt echa przetwarzany html, a ajax aktualizuje oryginalny akapit na stronie wywołującej.

Ten skrypt znajduje się w /admin/cms/...etc, co oznacza co najmniej 4 katalogi wewnątrz katalogu głównego witryny.

Po zakończeniu skryptu sprawdzam, używając tego samego skryptu zrzutu sesji, aby zobaczyć, czy dane rzeczywiście zostały zapisane/zatwierdzone, ale nie, $_SESSION ma tylko oryginalne dane ze strony wywołującej. Identyfikator identyczny, ta sama nazwa sesji, ten sam session_start(), ale dane nie zostaną zapisane. Cała ta operacja jest bardzo szybka, więc chociaż może to być problem z szybkością, skrypty kończą się, zanim session_write_close będzie mógł wykonać swoją pracę.

Ale jeśli dodaję nowy klucz do tablicy $_SESSION i umieszczę tam trochę danych, dane zostaną zaktualizowane i zapisane. Jeśli nie wypiszę niczego na tym skrypcie i po prostu przetworzę dane i ustawię zmienne sesji, otrzymam je również zaktualizowane i napisane.

Wygląda na to, że niektóre elementy tablicy $_SESSION są blokowane w celu aktualizacji.

Co zrobiłem, aby śledzić ten błąd i jestem pewien, że nie robię źle.

  • 1.- register_globals znajdują się oczywiście
  • 2.- session_name() i session_start() są zawsze obecne w danym
    kolejności. Miałem wiele
    session_start() -Zamknij się na tej samej stronie
    aby wykorzystać kilka nazwanych sesji, ale udoskonalić problem ten nie jest dłuższy tak.
  • 3.- Używam session_write_close() po przetworzeniu danych sesji. Również
    próbował bez, pozwalając php decydować kiedy zatwierdzać dane, ale bez powodzenia.
  • 4.- Używam ciasteczek tylko dla SID.
  • 5. sesje są przechowywane na/tmp, widzę aktualizację danych.
  • Próbowałem również użyć niestandardowego programu do zapisywania w DB, ale ten sam problem,
    "_write" został wywołany tylko wtedy, gdy brak danych wyjściowych.
  • Szukałem php.net, stackoverflow, google, itp. W tym temacie. Nigdy nie pytam bez badania, to mój pierwszy raz od wielu lat ... ale jest tak nielogiczne, że musi być czymś małym, o czym nie pomyślał.

Najdziwniejsze jest to, że po prostu przetwarzam dane bez danych wyjściowych $_SESSION. Ale jeśli zmodyfikuję ten skrypt później, dodając dane wyjściowe i spróbuję ponownie, zamiast po prostu mieć nową (ostatnią) wartość, otrzymam oryginalną wartość z powrotem, tę utworzoną przez stronę wywołującą na pierwszym miejscu, czasami po pobraniu kilku czasy! PHP nie może buforować wartości między skryptami lub? Nie mam włączonych globów.

Naprawdę nie mam pojęcia. System ten działał bezbłędnie na PHP4.3, ponieważ używam 5.3.3 przez dwie ćmy, których moi użytkownicy używają do wykasowania danych, gdzie się pomieszali, więc sprawdziłem i tak, są poważne problemy. Dzisiaj zaktualizowałem (5.3.6) i nie mogę uzyskać tych wartości sesji.

kod

Script nazywany przez 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 
?> 

naprawdę nic dziwnego tutaj .... główny kod strony jest jeszcze prostsze, żadnych dyrektyw php dziwne, itp

Oto nagłówek dzwoniącego strona

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 

UPDATE: zrobiłem testy późna noc i okazało cos i do not understand.HElP proszę: ma nie tylko do czynienia z sesji, ale również z zapytaniami Mysql. Ten sam kod, ale zamiast próbować pisać do tablicy $_SESSION zrobiłem prostą aktualizację do tabeli Innodb za pomocą session_id. Po wypisaniu kodu, aktualizacja zostaje wykonana, (mogę wypisać ciąg zapytania i nie ma żadnych problemów), ale sprawdzanie bazy danych powoduje, że wiersz nie jest aktualizowany. Wypuszczanie danych wyjściowych, jeśli skrypt i kwerenda zostaną zatwierdzone. Jedyną powszechną rzeczą jest to, że sesje są uruchamiane, a produkcja jest wykonywana.

Ponownie uruchomiłem Apache, itd. (Kto wie), ale bez powodzenia. Potem zrobiłem coś naprawdę głupiego, ponieważ jest to sprawa po stronie serwera. Zmieniłem przeglądarkę na Firefox (używając Safari) i wszystko działa! Ok, sprawdź ponownie, wróć do safari, nic nie działa. Obaj biegają obok siebie, ten sam problem. PHP jest po stronie serwera, w jaki sposób różne przeglądarki mogą obsługiwać kod inny, czy przeglądarka mówi do wycofania apache, żądanie nie jest obsługiwane lub wywołanie tego samego skryptu dwa razy bez powiadomienia (sprawdzona konsola programistów Safari i skrypt jest wywoływany tylko raz)? Czy safari może ponownie przesłać dane w trybie cichym, ponieważ "myśli" nie powiodło się? Sprawdziłem nagłówki przy użyciu narzędzi firebug i narzędzi programistycznych Safaris, nic dziwnego, ale gdy tylko wykonuję połączenie Ajax z safari, strona wywołująca ładuje dane (połączenie Aka z serwerem ...).

Naprawdę niczego nie rozumiem.

+7

@ _ @ To sprawiło, że moje oczy przeszły przez cały proces. – rockerest

+0

Ok, robi się coraz bardziej Nieznajomy, naprawdę potrzebuję pomocy Tutaj: –

+0

Bardzo trudne pytanie. Jeśli cokolwiek, to jest warte dodatkowych punktów. Kto się tym zajął? –

Odpowiedz

0

Nie jestem pewien, ale kilka sugestii może być pomocnych.

Usuń cookies sesyjne przed odświeżeniem strony dla celów testowych :)

Upewnić się, że nie jesteś przypisując żadnych tablic z kluczem zawierającego znak potoku (|). Zapobiega to serializowaniu i zapisywaniu danych sesji.

Do session_regenerate_id (true); wiele przypadków session_write_close nie wydaje się mieć znaczenia bez wartości session_regenerate_id. lub po prostu wykonaj session_start() po session_write_close(), jeśli polegasz na SID; aw twoim przypadku myślę, że to właśnie jest przyczyną problemu, ponieważ za każdym razem kończysz bieżącą sesję i nie uruchamiasz jej na następnej stronie. mam nadzieję, że rozumiem. Więcej informacji Aby upewnić się, że dane rzeczywiście są wypuszczane do przeglądarki, użyj ob_end_flush();

nie mogłem zrozumieć związek między

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

i

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

myślę, że trzeba wkleić trochę więcej kodu, gdzie część danych jest przyczyną problemu zamiast strony logowania administratora.

Mam nadzieję, że to pomaga. :)

1

Miałem podobny problem do tego (jeśli dobrze zrozumiałem). Musiałem wymusić zapis danych sesji (dla niestandardowego sterownika sesji) po zakończeniu działania skryptów. Można zarejestrować funkcję wyłączania, która powinna działać po zakończeniu wykonywania skryptów.

Może to rozwiąże (lub pomoże rozwiązać) twój problem.

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

+0

Nie jest to idealna odpowiedź, ale przynajmniej zaoferowałeś konkretne rozwiązanie i nie zadawał żadnych pytań. Gratulacje! –

0

Czy jest jakiś powód, dla którego ustanowienie nazwę sesji dwukrotnie? W przeszłości miałem problemy, w których mogłem ustanowić sesję bez nazwy, następnie nazywał sesję innym fragmentem skryptu (nie mojego). Nawet na końcu skryptu udało mi się wydrukować zmienną sesji, ale kiedy wszedłem na nową stronę, moja sesja została zapomniana. Dopiero kiedy skopiowałem nazwę zawartą w drugim skrypcie do mojej sesji, został on rozwiązany.

Sprawdź, czy nie ma innych nazw sesji; również, może spróbuj tylko nazwać sesję raz, przy pierwszym wywołaniu sesji?

0

Pytanie: Czy wywołasz session_start() najpierw ... przed JAKIMKOLWIEK wyjściem do przeglądarki i przed przypisaniem jakichkolwiek zmiennych?

Brzmi głupio, ale spróbuj.

Ponadto, dlaczego używasz nazw sesji? Naprawdę nie jest to konieczne, chyba że masz wiele zmiennych sesji o tej samej nazwie, służących różnym celom, a jeśli tak, to najpierw musisz to naprawić!

1

Dziękujemy za pomoc. Robiłem wszystko we właściwej kolejności, a dane z sesji wciąż nie były zapisywane. Nazwy sesji, o ile jest to konieczne, ponieważ czasami testujemy wiele witryn w tej samej domenie przy użyciu tego samego niestandardowego systemu CMS. W końcu, po przeprowadzeniu wielu testów i bez powodzenia, odkryłem, że na tym serwerze działały globale rejestru (nigdy ich nie używamy, kod został napisany z tą opcją oczywiście), ale to psuje sesje !. Wyłączenie tego spowodowało ogromną zmianę. Nigdy więcej problemów. Zrobiłem również niestandardową procedurę obsługi sesji w DB, więc mogłem śledzić problemy w bardziej scentralizowany sposób. Konkluzja: Nigdy nie używaj globali rejestracji + nazwanych sesji, złożonych danych w sesjach. W każdym razie, dam temu problemowi więcej czasu i więcej testów. Wywołania Ajax są również czasami zbyt szybkie, musiałem wprowadzić polecenie sleep, więc zapisanie danych sesji było naprawdę wykonane. Dzięki