문제

매번 고유 해야하는 4 자의 키를 생성하는 함수가 있습니다. 이를 위해 기능은 먼저 키를 생성 한 다음 데이터베이스 테이블을 확인하여 다른 사람이 사용 중인지 확인합니다.

사용하지 않으면 키를 반환하고 그렇지 않으면 다시 호출되지만 기능이 무한 루프를 수행하게됩니다. 전체 기능은 다음과 같습니다.

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

함수를 다시 호출하는 올바른 방법은 무엇입니까?

그건 그렇고, 저는 CodeIgniter를 사용하고 있습니다 $this.

도움이 되었습니까?

해결책

나는 재귀 스토 나오에 재귀 함수를 사용하지 않을 것입니다 (함수의 결과를 재사용하지 않기 때문에 재귀를 사용하는 것은 의미가 없습니다) ... 불필요한 오버 헤드가 많이 추가됩니다. 다음과 같이하십시오 :

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

return $key;

최대 키 수에 가까워지면 루프 시간이 매우 길어 지므로 최대 한계를 가질 수 있습니다.

아, 그리고 이것이 여러 스레드에서 동시에 발생하고 데이터베이스를 확인하는 경우 동일한 키를 두 번 삽입 할 수 없도록 테이블 쓰기 잠금을 구현해야합니다. 바람직하게는 키가 사용 가능한지 확인하는 기능이 자물쇠, 확인하다, 그리고 가능한 경우 쓰다 충돌을 피하기 위해 동일한 거래에서.

다른 팁

자체 도의 결과를 반환해야합니다. 그렇지 않으면 유효한 키가 재발하면 반환되지 않습니다.

return $this->key_generator($length);

그러나 이것은 기능이 무한 루프를 수행하게합니다.

재귀 전략을 절대적으로 유지하려면 최종 사례를 정의해야합니다. 예를 들어 다음과 같은 카운터를 정의 할 수 있습니다.

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

그러나 코드를 반복적으로 수행하는 것도 가능합니다 ...

당신이 충분히 포함한다면 독창성 주요 세대 루틴에서는 처음 에이 상황을 피할 수 있습니다. 예를 들어, 일상은 현재 타임 스탬프와 로컬 호스트 이름 및/또는 PID를 고려합니다.

이러한 비 결정적 방식으로 반복되는 것은 일반적으로 일부 부분이 너무 순진하다는 증거입니다. 그 좋지 않다. :-)


어쨌든, 요청을 걸고 마침내 시간을내는 것과 반대로 그것을 잡아서 어떤 종류의 오류를 기록하는 것이 좋습니다.

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

첫 번째 미사용 키에 대한 키 값 공간을 스캔하지 않겠습니까? 길고 독특한 4 인물 이외에 추가 제약 조건을 충족시키기위한 열쇠가 필요합니까?

후속 통화에서 스캔을 재개하기 위해 마지막으로 반환 된 키를 기억할 수 있습니다.

후속 호출이 비슷한 키를 반환하지 않으려면 먼저 키 데이터베이스를 셔플 할 수 있습니다. 이는 456976, 1679616, 7311616 또는 14776336 요소 배열 어딘가를 유지해야한다는 것을 의미합니다 (사용 된 알파벳이 숫자가 있거나없는 단일 또는 이중 캐릭터인지에 따라).

코드를 루프에 넣고 키를 결정할 수 있습니다. 반복적으로 대신에재귀 적으로.

예시:

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

  return $key;
}

루프 자체는 진한 루프를 방지하지는 않지만 함수 호출과 달리 스택 공간을 먹지 않으므로 스택 오버플로를 위험에 빠뜨리지 않습니다.

또한 사물을 조금 단순화합니다. 키 유형에 따라 키 생성 방법을 조정할 수도 있습니다. 예를 들어 번호가 매겨진 키를 사용하면 각 반복 할 때 기하 급수적으로 증가 할 수 있습니다.

비고 : 가능하면 자체 키 생성 기능을 롤링하는 대신 데이터베이스의 자동 증가 기능을 사용하십시오.

또한 동시 액세스로부터 코드를 보호하십시오. 이 함수의 두 인스턴스가 키를 생성하고 둘 다 동일하게 결정하면 어떻게됩니까? 중요한 섹션이나 거래를 사용하여 나쁜 일이 발생하지 않도록하십시오.

내부의 함수를 사용합니다

function test($val) {
    /*initialize return value by using the conditions*/
    if($val>=5){
        /*do something with return statement*/
        return $val+10;
    } else {
        /*set the return default value for avoid the error throwing*/
        return "default value";
    }
    /*return the function used for check the condition*/
    return test($val);
}

echo test(4);  // output "default value";
echo test(6);  //output 16
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top