2013-07-05 17 views
6

W PHP mam poważne problemy z używaniem serialize/ na dużej liczbie obiektów (100 000+ obiektów). Obiekty te mogą mieć wiele różnych typów, ale wszystkie są potomkami z klasy bazowej.PHP: tablica obiektów - serialize vs json_encode - alternatywy?

Jakimś sposobem, gdy używam unserialize na tablicy obiektów, około 0,001% obiektów jest generowanych nieprawidłowo! Zamiast tego generowany jest cały inny obiekt. Nie dzieje się to przypadkowo, ale za każdym razem z tymi samymi obiektami. Ale jeśli zmienię kolejność tablic, dzieje się tak z innymi obiektami, więc wygląda mi to na błąd.

Przełączyłem na json_encode/json_decode, ale okazało się, że to zawsze używa stdClass jako klasy obiektu. Rozwiązałem to, włączając nazwę klasy każdego obiektu jako właściwość, a następnie użyłem tej właściwości do skonstruowania nowego obiektu, ale to rozwiązanie nie jest zbyt eleganckie.

Używanie var_export z eval działa dobrze, ale jest około 3 razy wolniejsze niż inne metody i zużywa znacznie więcej pamięci.

Teraz moje pytania to:

  • co może powodować błędów/Niewłaściwy obiektów, które zostały utworzone z unserialize?
  • jest lepszy sposób użycia json_decode z tablicą obiektów, aby klasy były w jakiś sposób przechowywane w jsonie automatycznie?
  • jest może nawet inna metoda do odczytu/zapisu dużej liczby obiektów w PHP?

UPDATE

Zaczynam wierzyć, że musi być coś dziwnego z moim macierzach danych, ponieważ z msgpack_serialize (rozszerzenia PHP, alternatywnego do serialize) otrzymuję ten sam rodzaj błędów (ale o dziwo, nie te same obiekty są generowane źle!).

UPDATE 2

znalazł rozwiązanie Zamiast prowadzenia serialize na całej tablicy, to zrobić na każdym obiektu teraz pierwszy serialize i base64_encode i przechowywać co szeregowany przedmiot oddzielna linia w pliku tekstowym. W ten sposób mogę wygenerować całą tablicę obiektów, a następnie iterować każdy obiekt, używając file() z i base64_decode: żadnych więcej błędów!

+0

jakie dokładnie pojawiają się błędy? – Robert

+0

W jakiś sposób NIEKTÓRE z obiektów wygenerowanych z nieproporcjonalnie dużą liczbą obiektów są w rzeczywistości zupełnie innym obiektem, który również znajduje się w tablicy, ale w ten sposób wygenerowało dwa razy. Więc wydaje się, że coś jest nie tak z niektórymi wewnętrznymi wskaźnikami obiektów ... – Dylan

+0

Sprawdź moją odpowiedź Dylan serialize() jest lepsza dla dużych obiektów json_encode jest lepsza dla obiektów, które nie mają zasobów i nie obchodzi cię, jeśli " obudź się "prawidłowo. – Robert

Odpowiedz

3

Z funkcjami serializacji/unserializacji 2 magiczne metody są połączone.

__sleep()

serialize() sprawdza, czy twoja klasa zawiera funkcję o magicznej nazwie __sleep(). Jeśli tak, ta funkcja jest wykonywana przed serializacją. Może wyczyścić obiekt i ma zwrócić tablicę z nazwami wszystkich zmiennych tego obiektu, które powinny być serializowane. Jeśli metoda nie zwraca niczego, wówczas NULL jest serializowana i wydawane jest E_NOTICE.

Dzięki usypianiu masz lepszą kontrolę nad serializacją, możesz przekazać zmienne, które można serializować, a czyste zasoby - serwicowanie.

Kiedy unserialize nazywany jest wtedy inna funkcja należy wymienić

__wakeup()

Przeznaczenie __wakeup() jest do przywrócenia żadnych połączeń z bazą danych, które mogły zostać utracone podczas serializacji i wykonywać inne reinicjowanie zadania.

O json_encode()

  1. nie posiada magiczne metody __wakeup, __sleep więc masz mniej kontroli
  2. Nie serializowania właściwości prywatnych
  3. Obiekty są zawsze przechowywane jako stdClass
  4. json_encode jest szybszy niż serializacji

To od Ciebie zależy, co wybierzesz, ale dla bardziej zaawansowanych klas z połączeniem db itp. Sugerowałbym serializować()