내부에서 함수를 호출하는 방법?
-
05-07-2019 - |
문제
매번 고유 해야하는 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