2008-11-21 18 views
45

Używam PHP 5.2. Chciałbym znaleźć sposób na wyprowadzenie unikalnego identyfikatora dla każdego obiektu, więc łatwo jest przeglądać logi, aby zobaczyć, które obiekty są takie same.Jak znaleźć identyfikator obiektu w PHP?

W Ruby po prostu powiedziałbym object.object_id, aby uzyskać wewnętrzny identyfikator Ruby dla obiektu. Nie wydaje się oczywiste, aby zrobić to w PHP.

Czy ma to wbudowany sposób? Jeśli nie, możesz zaproponować inne sugestie?

Odpowiedz

80

Użyj do tego celu spl_object_hash().

Zwraca unikalny identyfikator dla każdej instancji obiektu, a nie nazwę klasy, więc wydaje się bardziej odpowiedni dla ciebie.

Edit:

dla PHP użytkowników < 5.2.x zobacz this answer.

+3

Jeśli obiekty są równe, tj. Różnią się tylko tożsamością, to skróty obiektów tworzone przez 'spl_object_hash()' mogą wyglądać bardzo podobnie. Właśnie spróbowałem i mam to: a: 00000000462ff471000000005e39f75b b: 00000000462ff46c000000005e39f75b Są różne, ale trzeba patrzeć uważnie. –

+2

Należy także zauważyć, że komentarz dotyczący planety na stronie referencyjnej o hashach może być taki sam, gdy odniesienie jest zniszczone. – koen

+0

@Ollie Saunders, Aby to poprawić, możesz użyć skrótu (np. SHA1) 'sql_object_hash()'. Jednak mogą * zdarzyć się kolizje, ale nie sądzę, że w tym przypadku należy się czymś martwić. – strager

15

Obecnie nie ma sposobu, aby to zrobić w PHP, począwszy od wersji 5.3.6.

spl_object_hash() nie robi tego, co chcesz - ponieważ przetwarza identyfikatory po usunięciu obiektów, spowoduje to błędy w (na przykład) obiektowo-relacyjnym oprogramowaniu odwzorowującym, które będzie próbowało śledzić obiekty w sesji.

Opis u góry strony dokumentacji ("Ta funkcja zwraca unikalny identyfikator obiektu. Ten identyfikator może być użyty jako skrót do przechowywania obiektów lub do identyfikacji obiektu.") Jest błędny - prawda jest ujawniony w notatce na tej stronie: "Gdy obiekt jest niszczony, jego skrót może być ponownie użyty dla innych obiektów", lub innymi słowy, funkcja zawsze zwraca unikalny identyfikator i zawsze może być zawsze unikalna. używany do przechowywania lub identyfikacji obiektów.

Technika demonstrowana w this comment może działać w niektórych przypadkach, ale nie jest niezawodna i nie będzie działać konsekwentnie, ponieważ próba dostępu do niezdefiniowanej właściwości wywoła metody magiczne __get() i __set(), których wyniki są nieprzewidywalne.

Podsumowując, krótka odpowiedź na twoje pytanie (niestety) brzmi "nie" - nie ma takiej metody w PHP i nie ma sposobu napisania takiej metody, która będzie działać konsekwentnie dla dowolnego obiektu.

Jeśli chciałbyś, aby zobaczyć tę funkcję dodane do PHP, proszę głosowania i/lub skomentować tutaj:

http://bugs.php.net/bug.php?id=52657

+0

Alternatywna technika będzie działać tak długo, jak dany obiekt nie będzie implementował metod magicznych "__get',' __set' i '__isset'. Masz rację, że (na przykład) obiektowy program odwzorowujący relację może wykorzystywać te, aby mapować niezdefiniowane właściwości do kolumn tabeli. Dziwne rzeczy mogą się zdarzyć w tym momencie, gdy ORM próbuje obsłużyć własność '__oid__'. – azkotoki

+0

Wierzę, że po prostu powtarzacie to, co już powiedziałem o magicznych metodach? A większość nowoczesnych ORMów używa ClassReflection :: getProperties(), więc nie zobaczą właściwości __oid__. Jeśli twój ORM naprawdę nie używa _annego_ rodzaju filtrowania właściwości i po prostu ślepo utrzymuje wszystkie właściwości, to i tak twierdziłbym, że jest bardzo słaby - większość ORM używa konfiguracji odwzorowania, konwencji, osadzonych metadanych lub odbicia stołu, lub kombinacje tych ... –

+0

Nie, właśnie wyjaśniałem lepiej, co powiedziałeś o magicznych metodach, co nie było w 100% poprawne. Tęskniłeś '__zestawem' :) – azkotoki

0

Wiem, że to stary temat, ale myślę, że znalazł rozwiązanie.

Sztuczka polega na przechowywaniu odniesienia do każdego obiektu w tablicy z przypisanym kluczem. Następnie można uzyskać identyfikator obiektu, przeszukując tę ​​tablicę i zwracając znaleziony klucz.

<?php 

class objectMarker 
{ 
    private $storage; 

    function add($object) { 
     $this->storage[] = $object; 
    } 

    function getId($object) { 
     foreach ($this->storage as $id => $item) { 
      if ($item === $object) { 
       return $id; 
      } 
     } 

     return null; 
    } 
} 

$marker = new objectMarker; 

$t1 = new stdClass; 
$t2 = new stdClass; 

$marker->add($t1); 
$marker->add($t2); 

echo $marker->getId($t1) . "\n"; 
echo $marker->getId($t2) . "\n"; 

unset($t1); 

$t1 = new stdClass; 
$marker->add($t1); 

echo $marker->getId($t1) . "\n"; 

$t2->x = 1; 
echo $marker->getId($t2) . "\n"; 

/* output: 
0 
1 
2 
1 
*/