2009-10-23 4 views
7

매번 고유해야하는 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입니다.

+2

그것은 또한 재귀 – Makach

+1

라고하며, $이 CodeIgniter의 독점이 아니다. –

+1

나는이 코드가 어디에서 왔는지와 코드 스 니펫에서 정의되지 않은 이유를 설명하고 있다고 생각한다. – JAL

답변

25

함수의 결과를 재사용하지 마십시오. 재귀를 사용하는 것이 무의미합니다.) ... 불필요한 오버 헤드가 많이 발생합니다. 이런 식으로 뭔가를 수행합니다 키의 최대 수 근처에있을 경우 최대 한도의 어떤 종류를 넣을 수 있도록

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

return $key; 

이 매우 긴 루프시기에 발생합니다.

아, 여러 스레드에서 동시에 발생하고 데이터베이스를 검사하는 경우 동일한 키를 두 번 삽입 할 수 없도록 테이블 쓰기 잠금을 구현해야합니다.키가 사용 가능한지 확인하는 기능은 , 체크 및 사용 가능한 경우 을 같은 트랜잭션으로 잠궈 충돌을 피하는 것이 좋습니다.

+0

네 말이 맞아. 이것은 최고의 (그리고 가장 단순한) 솔루션 인 것처럼 보입니다. 감사! –

+0

이상적인 해결책은 많은 경우에 지나치게 긴 루프를 방지하기 위해 일부 메커니즘을 설치하는 데주의하십시오. – Stuart

1

당신은 루프에 코드를 넣고 키 반복적으로 대신 반복적으로 의를 결정할 수있다.

예 :

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

    return $key; 
} 

자체가 infinte 루프를 방지하지 않습니다,하지만 당신은 스택 오버플로 위험하지 않도록 함수 호출과는 달리,이 스택 공간을 먹지 않습니다 루프.

또한 간단한 작업을 수행합니다. 키 유형에 따라 키 생성 방법을 적용 할 수도 있습니다. 예를 들어 번호가 매겨진 키를 사용하면 각 반복마다 기하 급수적으로 증가 할 수 있습니다.

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

동시 액세스로부터 코드를 보호해야합니다. 이 함수의 두 인스턴스가 키를 생성하려고 시도하고 둘 다 같은 것을 결정하면 어떨까요? 중요한 부분이나 거래를 사용하여 나쁜 일이 발생하지 않도록하십시오.

2

그러나 이것은 무한 루프를 수행하는 기능을 원인

당신이 절대적으로 당신의 재귀 전략을 유지하려는 경우 당신은 엔드 케이스를 정의해야합니다. 예를 들어, 당신은 다음과 같이 카운터를 정의 할 수 있습니다 :

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

반복적으로 코드를 할 그러나 수도 있습니다 ... 당신이 '돈 때문에 내가 (재시도 시나리오 재귀 함수를 사용하지 않을

5

자기 호출의 결과를 반환해야합니다. 그렇지 않으면 유효한 키가 재발되면 반환되지 않습니다. 당신이 당신의 키 생성 루틴 고유성 충분히 포함하는 경우

return $this->key_generator($length); 
+0

좋은 지적 =) 나는이 경우에도 재귀를 사용하지 않을 것을 권한다. – Blixt

2

, 당신은 처음부터 이런 상황을 방지 할 수 있습니다. 예 : 루틴에 현재 타임 스탬프와 로컬 호스트 이름 및/또는 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; 
    } 
1

을 왜 수행합니다 :-) 어쨌든


, 적어도 그것을 잡아 시간 초과 마지막 요청을 걸려와 반대로 몇몇 에러를 기록하는 좋은 방법이 될 것입니다 첫 번째 사용하지 않은 키의 키 값 공간을 스캔하면됩니까? 4 개의 문자가 길고 독창적 인 것 위에 추가 제약 조건을 충족시키기위한 열쇠가 필요합니까?

이후에 호출 할 때 마지막으로 반환 된 키를 기억하여 거기에서 스캔을 다시 시작할 수 있습니다.

후속 호출이 유사한 키를 리턴하지 않게하려면, 먼저 키 데이터베이스를 섞을 수 있습니다. 이것은 456976, 1679616, 7311616 또는 14776336 요소 배열을 어딘가에 보유해야 함을 의미합니다 (사용 된 알파벳이 단일 또는 이중 대문자인지, 숫자 사용 여부에 따라 다름). 자체 내부 기능을 사용

0

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