2016-04-15 2 views
0

私のクラスのインスタンス化ごとにランダムなIDをrand()で生成したいとします。私はそれがユニークであることを望んでいます。ここに私が書いたものがありますが、これはうまくいきません。すべてのクラスインスタンス化のための一意の乱数

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(); 
     } 
    } 
} 

私はrand(1,3)のように、低い値を生成して、意図的にこれを試してみた、と私はそれが働いていないIDが2、2、1と3つのオブジェクトを得ました。

これは、クラス$id_listの新しいインスタンスが空になるためです。しかし、私はほとんど同じことをやっている人々を見てきました。 $counter変数を宣言し、メソッドに$this->counter++と入力します。違いは何ですか?

+1

'rand'は一意の番号を作成しません。 –

+0

そのため、私は 'checkID()'関数を作りました。 – Roman

+0

$ id_listを静的にしようとしましたか? – misdreavus79

答えて

1

$counterこのように使用される変数はランダムではありませんが、ユニークです。あなたの好みに応じて0または1から始めて、作成されたオブジェクトを単純に数えます。違いは、クラスのすべてのオブジェクトが同じ変数にアクセスしていることです。そのようにそれを達成するために、変数は、staticとして宣言する必要があります。

public static $counter = 0; 

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

もユニークな乱数を生成するには、すべてののidを生成した数を比較し、サブルーチンを記述する必要がありますインスタンス化されたオブジェクト。これは非常に迅速に非効率になる可能性があり、私はそれをお勧めしません。しかし、あなたはそれをやろうとしていた場合、それはこのようなものになります:

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

しかし、ランダムな値はどうですか?それは効率についてではなく、私はちょうどこのようなものがどのように働くかを理解したいと思う。また、このようなものはより高度なものと思われますか?私は1ヶ月間だけPHPを学習してきました。おそらく、私が理解することは難しいでしょう。 – Roman

+0

確かに、問題は解決策をスケールすることができます。何個のオブジェクトをスピンアップするのか予測できない場合は、乱数の範囲を正確に設定することはできません。番号の範囲がいっぱいになると、エラーが多く発生します。スケーラビリティについて考えてみるだけです。 – larsAnders

+1

その場合、IDはデータベースに格納され、索引付けされる可能性がありますが、別の問題です。 – misdreavus79

1

をあなたはそれのような、格納された値を保つように$ ID_LIST静的にする必要があります。

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(); 
} 

私が追加結果を示すために印刷ラインが表示されますが、ポイントを取得する必要があります。

+0

Aha、今、 '$ id_list'を静的にすることを提案した後の問題は、関数内で' self :: 'を使わなかったことです。ありがとう。 – Roman

0

使用しspl_object_hash()機能を使用することができます。

この関数はオブジェクトの一意の識別子を返します。このIDは、 オブジェクトを格納するためのハッシュキーとして、またはオブジェクトが破棄されない限り オブジェクトを識別するために使用できます。オブジェクトが破棄されると、そのハッシュは他のオブジェクトに再利用される可能性があります。オブジェクトたら

spl_object_hash()によって返される値の一意性は、「弱い」のポイントを持っていることを

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

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

注:あなたがオブジェクトを作成するたびにspl_object_hash()を呼び出すことができます

そのハッシュが他の オブジェクトに対して再利用される可能性があります。この場合

、あなたが構築することができますが、このようなこの一つとして、コードを使用してhashingメカニズムを所有する:

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); 
    } 
} 

MD5ハッシュは、衝突確率を持っているので、事実上、重複したIDにチェックする必要はありません2^128の1の1!

関連する問題