2016-04-15 13 views
0

Ich möchte eine zufällige ID über rand() für jede Instanz meiner Klasse generieren. Und ich möchte, dass es einzigartig ist. Hier ist, was ich geschrieben habe, aber das funktioniert nicht.Einzigartige Zufallszahl für jede Klasseninstanziierung

class Computer 
{ 
    private $id = 0; // placeholder for ID 
    private $id_list = []; // placeholder to store used IDs 

    public function __construct() 
    { 
     $this->checkID(); 
    } 

    private function checkID() 
    { 
     $this->id = rand(1,3); 
     if (!in_array($this->id, $this->id_list)) 
     { 
      array_push($this->id_list, $this->id); 
     } else { 
      $this->checkID(); 
     } 
    } 
} 

Ich habe dies absichtlich versucht, mit niedrigen Werten zu erzeugen, wie rand(1,3), und ich habe drei Objekte mit IDs 2, 2, 1. So funktioniert es nicht.

Ich nehme an, das ist, weil für jede neue Instanz einer Klasse $id_list Array leer wird. Aber ich habe Leute gesehen, die fast dasselbe machen. Eine $counter Variable deklarieren und setzen $this->counter++ in der __construct Methode. Was ist der Unterschied?

+1

'Rand' macht keine eindeutigen Zahlen. –

+0

Deshalb habe ich eine 'checkID()' -Funktion geschrieben. – Roman

+0

Haben Sie versucht, $ id_list statisch zu machen? – misdreavus79

Antwort

1

Eine $counter Variable, die auf diese Weise verwendet wird, ist nicht zufällig, aber sie ist einzigartig. Es zählt einfach die Objekte, wie sie erstellt werden, beginnend mit 0 oder 1, je nach Vorliebe. Der Unterschied besteht darin, dass alle Objekte der Klasse auf dieselbe Variable zugreifen. Um das zu erreichen, muss die Variable als statisch deklariert werden, etwa so:

public static $counter = 0; 

function __construct() 
    self::$counter++; 
} 

Um eine Zufallszahl zu erzeugen, die auch eindeutig zuzuordnen sind, werden Sie müssen ein Unterprogramm schreiben, das die erzeugte Zahl auf die ID für jeden vergleicht instanziiertes Objekt. Dies könnte sehr schnell ineffizient werden, und ich empfehle es nicht. Aber wenn Sie es tun würden, könnte es etwa so aussehen:

class Computer 
{ 
    private $id = 0; // placeholder for ID 
    private static $id_list = []; // placeholder to store used IDs 

    public function __construct() 
    { 
     $this->id = self::checkID(); 
    } 

    private static function checkID() 
    { 
     $newID = rand(1,10000); 
     if (!in_array($newID, self::$id_list)) 
     { 
      array_push(self::$id_list, $newID); 
      return $newID; 
     } else { 
      self::checkID(); 
     } 
    } 
} 
+0

Aber was ist mit zufälligen Werten? Es geht nicht um Effizienz, ich möchte nur verstehen, wie so etwas funktionieren würde. Wird so etwas auch als fortgeschrittener angesehen? Ich lerne PHP erst seit einem Monat. Vielleicht ist es zu schwer für mich zu verstehen. – Roman

+0

Sicher, das Problem ist, eine Lösung skalieren zu können. Wenn Sie nicht vorhersagen können, wie viele Objekte hochgefahren werden sollen, können Sie den Bereich für Zufallszahlen nicht genau festlegen. Und nachdem der Nummernbereich voll ist, werden Fehler auftreten. Das ist alles, nur über Skalierbarkeit nachzudenken. – larsAnders

+1

Nun, in diesem Fall könnten die IDs in einer Datenbank gespeichert und indiziert werden, aber das ist eine andere Sache für einen anderen Tag. – misdreavus79

1

Sie benötigen $ ID_LIST statisch zu machen, so dass sie die gespeicherten Werte hält, als solche:

class Computer 
{ 
    private $id = 0; // placeholder for ID 
    private static $id_list = []; // placeholder to store used IDs 

    public function __construct() 
    { 
     $this->checkID(); 
     print_r(self::$id_list); 
    } 

    private function checkID() 
    { 
     $this->id = rand(1,3); 
     if (!in_array($this->id, self::$id_list)) 
     { 
      array_push(self::$id_list, $this->id); 
     } else { 
      $this->checkID(); 
     } 
    } 
} 
for($i = 0; $i < 10; $i++){ 
    new Computer(); 
} 

I hinzugefügt die Drucklinien, um das Ergebnis zu präsentieren, aber Sie sollten den Punkt bekommen.

+0

Aha, jetzt sehe ich, dass das Problem, nachdem Sie vorgeschlagen haben, $ id_list static zu machen, war, dass ich 'self ::' nicht innerhalb der Funktion verwendet habe. Vielen Dank. – Roman

0

Verwendung kann die spl_object_hash() Funktion:

Diese Funktion gibt eine eindeutige Kennung für das Objekt. Diese ID kann als Hash-Schlüssel zum Speichern von Objekten oder zum Identifizieren eines Objekts verwendet werden, solange das Objekt nicht zerstört wird. Sobald das Objekt zerstört ist, kann sein Hash für andere Objekte wiederverwendet werden.

können Sie spl_object_hash() rufen jedes Mal, wenn das Objekt konstruieren:

class Computer 
{ 
    private $id = "";   // placeholder for a unique random Id 

    public function __construct() 
    { 
     $this->id = spl_object_hash($this); 
    } 
} 

Beachten Sie, dass die Einzigartigkeit der von spl_object_hash() zurückgegebenen Werte einen ‚schwachen‘ Punkt:

Sobald das Objekt zerstört ist, kann sein Hash für andere Objekte wiederverwendet werden.

In diesem Fall, Sie besitzen hashing Mechanismus mit einem Code wie dieses Konstrukt könnte:

class Computer 
{ 
    private $id = "";   // placeholder for a unique random Id 
    private static $seed = 0; //placeholder for the seed 

    public function __construct() 
    { 
     self::$seed++; 
     $this->id = hash('md5', get_class($this) . self::$seed); 
    } 
} 
Praktisch

, gibt es keine Notwendigkeit für die duplizierten Ids zu überprüfen, weil md5 Hashes eine Kollisionswahrscheinlichkeit hat von 1 in 2^128!