2008-11-21 59 views
45

Tôi đang sử dụng PHP 5.2. Tôi muốn tìm một cách để xuất ra một id duy nhất cho mọi đối tượng, vì vậy thật dễ dàng khi xem qua các bản ghi để xem các đối tượng nào giống nhau.Cách tìm ID đối tượng trong PHP?

Trong Ruby, tôi chỉ cần nói object.object_id để nhận định danh nội bộ của Ruby cho đối tượng. Có vẻ như không phải là một cách rõ ràng để làm điều này trong PHP.

Có cách tích hợp để thực hiện việc này không? Nếu không có, bạn có thể đưa ra bất kỳ đề xuất nào khác không?

Trả lời

80

Sử dụng spl_object_hash() cho điều đó.

Nó trả về một mã định danh duy nhất cho mỗi cá thể đối tượng chứ không phải tên của lớp, vì vậy nó có vẻ phù hợp hơn với bạn.

Edit:

Đối với PHP sử dụng < 5.2.x, xem this answer.

+3

Nếu các đối tượng bằng nhau, tức là chỉ bằng cách nhận dạng băm đối tượng được tạo bởi 'spl_object_hash()' có thể xuất hiện rất giống nhau. Tôi chỉ thử nó và tôi đã nhận được điều này: a: 00000000462ff471000000005e39f75b b: 00000000462ff46c000000005e39f75b Đó là khác nhau nhưng bạn phải xem xét cẩn thận. –

+2

Ngoài ra, lưu ý nhận xét về hành tinh trên trang tham chiếu về các băm có thể giống nhau khi tham chiếu bị hủy. – koen

+0

@Ollie Saunders, Để sửa lỗi này, bạn có thể lấy hàm băm (ví dụ: SHA1) của 'sql_object_hash()'. Tuy nhiên, có * có thể * là va chạm, nhưng tôi không nghĩ đó là điều đáng lo ngại trong trường hợp này. – strager

15

Hiện tại không có cách nào để thực hiện việc này trong PHP, kể từ phiên bản 5.3.6.

spl_object_hash() không thực hiện những gì bạn muốn - bởi vì nó tái tạo số nhận dạng khi đối tượng bị xóa, điều này sẽ dẫn đến lỗi trong (ví dụ) trình ánh xạ đối tượng cố gắng theo dõi đối tượng trong phiên.

Mô tả ở đầu trang tài liệu ("Hàm này trả về mã định danh duy nhất cho đối tượng. Id này có thể được sử dụng làm khóa băm để lưu trữ đối tượng hoặc xác định đối tượng.") Là sai - sự thật được tiết lộ trong ghi chú trên trang đó: "Khi một đối tượng bị phá hủy, hàm băm của nó có thể được sử dụng lại cho các đối tượng khác", hay nói cách khác, hàm không luôn trả về mã định danh duy nhất và có thể không được sử dụng để lưu trữ hoặc xác định các đối tượng. Kỹ thuật được trình bày trong this comment có thể hoạt động trong một số trường hợp, nhưng nó không đáng tin cậy và sẽ không hoạt động một cách nhất quán, vì cố gắng truy cập một thuộc tính không xác định sẽ gọi phương thức ma thuật __get() và __set(). không thể đoán trước được. Trong kết luận, câu trả lời ngắn cho câu hỏi của bạn (không may) là "không" - không có phương pháp như vậy trong PHP, và không có cách nào để viết một phương pháp như thế này sẽ làm việc nhất quán cho bất kỳ đối tượng nào.

Nếu bạn muốn xem tính năng này thêm vào PHP, hãy bỏ phiếu và/hoặc bình luận ở đây:

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

+0

Kỹ thuật thay thế sẽ hoạt động miễn là đối tượng đã cho không thực hiện các phương thức ma thuật '__get',' __set' và '__isset'. Bạn nói đúng (ví dụ) một người lập bản đồ quan hệ đối tượng có thể sử dụng những cái này, để ánh xạ các thuộc tính không xác định cho các cột trong bảng. Những điều kỳ lạ có thể xảy ra tại thời điểm này khi ORM cố gắng xử lý thuộc tính '__oid__'. – azkotoki

+0

Tôi tin rằng bạn đang lặp lại những gì tôi đã nói về các phương pháp ma thuật? Và hầu hết các ORM hiện đại sử dụng ClassReflection :: getProperties() để chúng không thấy thuộc tính __oid__. Nếu ORM của bạn thực sự không sử dụng tính năng lọc _any_ loại tài sản, và chỉ mù quáng tồn tại tất cả các thuộc tính, tôi sẽ cho rằng thiết kế cực kỳ kém - hầu hết các ORM sử dụng cấu hình ánh xạ, quy ước, siêu dữ liệu nhúng hoặc phản chiếu bảng hoặc sự kết hợp của những ... –

+0

Không, tôi chỉ giải thích tốt hơn những gì bạn nói về các phương pháp ma thuật, không đúng 100%. Bạn đã bỏ lỡ '__isset' :) – azkotoki

0

Tôi biết đây là chủ đề cũ, nhưng tôi nghĩ rằng tôi đã tìm thấy một giải pháp.

Bí quyết là lưu trữ tham chiếu đến từng đối tượng trong mảng với khóa được chỉ định. Sau đó, bạn có thể nhận id đối tượng bằng cách tìm kiếm thông qua mảng đó và trả về khóa tìm thấy.

<?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 
*/ 
Các vấn đề liên quan