Kendi içindeki bir işlevi çağırmak nasıl?

6 Cevap php

Ben her zaman için benzersiz olmak zorundadır 4 karakterli bir anahtar oluşturur bir işlevi var. Bunu yapmak için, işlev ilk olarak bir anahtar oluşturur, ve sonra bir başkası tarafından kullanılıyor olup olmadığını görmek için bir veritabanı tablosunu denetler.

Kullanımda değilse, o kendisini yeniden çağırır, başka, bir anahtar verir, ama bu bir hayır-hayır bir sonsuz döngü, yapılacak işlevini neden olur. İşte bütün fonksiyonu bulunuyor:

function key_generator($length = 4)
{
    // I've subsequently left out the generating code,
    // which is not necesarry in this case

    $key = 'xxxx';

    if ($this->user_model->valid_key($key) == true)
    {
        return $key;
    }
    else
    {
        $this->key_generator(4);
    }
}

Tekrar işlevini çağırmak için doğru yolu nedir?

Bu arada, ben CodeIgniter'ı kullanıyorum, dolayısıyla $this.

6 Cevap

Ben deneme-senaryoları için özyinelemeli işlevleri kullanmak olmaz (sen işlevinin sonucu yeniden yok çünkü, bu özyineleme kullanmak anlamsız) ... Bu gereksiz yükü bir sürü ekler. Böyle bir şey yapın:

do {
    $key = ...; // Generate your key here...
} while (!$this->user_model->valid_key($key));

return $key;

Eğer tuşları maksimum sayıda yakınında iseniz, bu çok uzun bir döngü süreleri neden olur, böylece maksimum sınırı çeşit koymak isteyebilirsiniz.

Bu aynı anda birden fazla iş parçacığı üzerinde meydana gelen ve bir veritabanı kontrol ediyoruz eğer aynı tuşa iki kez takılamıyor böylece Oh, ve, tablo yazma kilitlemeyi uygulamalıdır. Bir anahtar mevcut olup olmadığını kontrol eder, tercihen fonksiyon gerektiği lock, check, ve varsa write herhangi çarpışmaları önlemek için aynı işlem.

ancak bu işlev sonsuz bir döngü yapmak neden olur,

Size kesinlikle özyinelemeli strateji tutmak istiyorsanız size bir son durumu tanımlamak zorunda. Örneğin bu gibi bir sayaç tanımlayabilir:

function key_generator($length = 4, $limit=5)
{
    if($limit === 0) {
         throw new YourException();
    }

    // I've subsequently left out the generating code,
    // which is not necesarry in this case

    $key = 'xxxx';

    if ($this->user_model->valid_key($key) == true)
    {
        return $key;
    }
    else
    {
        return $this->key_generator(4, ($limit-1));
    }
}

Bu iteratif kodunuzu yapmak da ancak mümkündür ...

Eğer anahtar üretimi rutin uniqueness yeterli eklerseniz, ilk etapta bu durumu önlemek mümkün olabilir. Örneğin dikkate rutin üstlenmek geçerli zaman damgası ve yerel bilgisayar adını ve / veya PID.

Böyle bir deterministik olmayan bir biçimde loop genellikle kısmı çok naif olmanın kanıtıdır. Bu iyi değil. :-)


Her neyse, en azından onu yakalamak ve istek asılı ve nihayet dışarı zamanlama aksine hata çeşit oturum iyi bir uygulama olacaktır:

    function key_generator($length = 4)
    {
        /* The $attempts_left clearly depends on how much trust 
           you give your key generation code combined with the key space size. */
        $attempts_left = pow(16, $length) * 2;
        /* ... just guessing, in case your key base is 16, i.e. [0-9a-z] for example */

        do {
            // ... key generation goes here ...
            $key = 'xxxx';
        } while ( $this->user_model->valid_key($key) == false && $attempts_left-- > 0 );

        if( $attempts_left < 1 )
            return false;
        else
            return $key;
    }

Bunu recurses kez aksi geçerli anahtar iade almazsınız, kendini aramanın sonucunu dönmek gerekiyor.

return $this->key_generator($length);

Neden sadece ilk kullanılmayan anahtarının anahtar değeri alanı taramak değil mi? Dört karakter uzunluğunda ve eşsiz olmanın üstüne ek kısıtlamaları yerine getirmek için anahtar ihtiyacı var?

Sen sonraki çağrılarda oradan taramaya devam etmek için son döndü anahtarını hatırlıyorum olabilir.

Benzer anahtarları dönmek için değil sonraki çağrılar istiyorsanız, öncelikle anahtar veritabanı shuffle olabilir. Bu, bir yerde (kullanılan alfabe ile veya rakam olmayan, tek veya çift cidarlı karakterler olup olmadığına bağlı olarak) bir 456.976, 1.679.616, 7.311.616, 14.776.336 veya eleman dizi tutmak gerekir anlamına gelir.

You could put your code into a loop and determine the key iteratively instead of recursively.

Example:

function key_generator($length = 4)
{
  do {
    $key = 'xxxx'; //TODO
    if (timeOutReached()) return InvalidKey;
  } while (!$this->user_model->valid_key($key))

  return $key;
}

Döngü kendisi Infinte döngü engellemez, ancak bir işlev çağrısı aksine, bu yığın yer yemez, bu yüzden bir yığın taşması riski yoktur.

Ayrıca şeyleri biraz kolaylaştırır. Ayrıca her bir yineleme ile katlanarak artabilir numaralı tuşları ile, örneğin, anahtar üretim yöntemi uyarlayabilirsiniz anahtarın türüne bağlı.

Mümkün ise Remarks:, yerine kendi anahtar nesil özelliği yuvarlanan bir veritabanının otomatik artış özelliğini kullanın.

Ayrıca eşzamanlı erişime karşı kodunuzu korumak emin olun. Ne bu fonksiyonun iki örneklerini bir anahtar oluşturmak için deneyin ve her ikisi de aynı tespit edersek? Emin kötü bir şey olmuyor yapmak için kritik bölümleri veya işlemleri kullanın.