2010-01-22 3 views
19

나는이 질문이 해킹되고 이상하다고 생각하지만 PHP에서 런타임에 함수를 제거하는 방법이 있습니까?PHP에서 런타임에 함수 제거

"if"블록에 선언 된 재귀 함수가 있고 "if"블록에서만 해당 함수가 "유효"하도록하고 싶습니다. 나는이 블록 밖에서이 함수를 호출하지 않기를 바란다.

runkit_function_remove을 찾았지만 웹 호스트에서 runkit을 사용할 수 없습니다. 거기에 또 다른 방법이 있을까요?

나는 PHP 5.1.0 만 지원합니다.

편집 : 내 질문은 해키했지만, 여기에 내가 원하는 정확한 일을 알고 : 매직 지수가 ON 일 때

if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) 
{ 
    function stripslashes_deep($value) 
    { 
     return is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value); 
    } 

    $_POST = array_map('stripslashes_deep', $_POST); 
    $_GET = array_map('stripslashes_deep', $_GET); 
    $_COOKIE = array_map('stripslashes_deep', $_COOKIE); 
    $_REQUEST = array_map('stripslashes_deep', $_REQUEST); 

    //runkit_function_remove('stripslashes_deep'); 
} 

"stripslashes_deep"때문에 것입니다, 나는 싶었에만 라이브 내가 끝내면 그걸 없애 버려. 사람들이 항상 이 아닌 기능에 의존하기를 원하지 않습니다.. 나는 그것이 지금 더 분명하기를 바란다. 비 해킹 된 솔루션 제안도 환영합니다!

+3

** 단순히 전화하지 못하는 이유는 무엇입니까 **? –

+0

무엇을 부르지 않습니까? – AlexV

+2

조심하세요! 배열 키는 마법 따옴표로 깎입니다. –

답변

18

: PHP에서

모든 함수와 클래스는 전역이 -는 그들이 내부와 그 반대의 경우도 마찬가지 정의 된 경우에도 함수 외부에서 호출 할 수 있습니다. [...] PHP는 함수 오버로딩을 지원하지 않으며 이전에 선언 된 함수의 정의를 해제하거나 다시 정의 할 수도 없습니다.

예외는 runkit입니다. 그러나 실행 후 함수를 anonymous functionunset으로 정의 할 수 있습니다.

if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) 
    $fn = create_function('&$v, $k', '$v = stripslashes($v);'); 
    array_walk_recursive(array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST), $fn); 
    unset($fn); 
} 

일부 commentors 올바르게 지적했다 (하지만 더 이상 요즘 PHP의 문제), 당신은 자체 내부 익명 함수를 호출 할 수 없습니다. array_walk_recursive을 사용하면이 제한을 피할 수 있습니다. 개인적으로, 나는 단지 정규 함수를 만들고 그것을 삭제하는 것을 걱정하지 않을 것이다. 누구에게도 해가되지 않을 것입니다. stripslashes_gpc_callback과 같은 올바른 이름을 지정하십시오.

참고 : 편집 및 설명 후

+0

"기발한"해결책이지만, 나는 그것을 좋아합니다. OP가 함수 사용을 주장한다면, 이것이 그 방법입니다. –

+0

재귀 익명 기능을 사용할 수 있습니까? – AlexV

+0

좋은 지적.재귀를 사용하여이 작업을 수행하는 방법을 생각할 수 없습니다 (기본적으로 이미 가지고있는 코드로 돌아 가지 않고). 이 경우 그의 (및 내) 편집 내용을 듣고 기능을 제거하는 것에 대해 걱정할 필요가 없습니다. –

3

간단한 대답입니다. 그러나

, 네임 스페이스 내에서 기능을 배치 시도 할 수 클래스 또는 다른 기능 내도 -하지만 그게 당신이 찾고있는 게 아니에요 생각합니다.

당신이 가지고있는 또 다른 옵션 중 하나는 파일/라인/etc ...이 무엇인지 확인하기 위해 debug_backtrace()을 사용하는 것입니다.이 파일은 hackish입니다.하지만 역시 runkit_function_remove()입니다.


편집 - 당신이 그렇지 않으면 당신은 그냥 할 수있는, PHP 5.3+ 실행하지 않는 너무 나쁜 :

if (get_magic_quotes_gpc()) 
{ 
    $_GET = json_decode(stripslashes(json_encode($_GET, JSON_HEX_APOS)), true); 
    $_POST = json_decode(stripslashes(json_encode($_POST, JSON_HEX_APOS)), true); 
    $_COOKIE = json_decode(stripslashes(json_encode($_COOKIE, JSON_HEX_APOS)), true); 
    $_REQUEST = json_decode(stripslashes(json_encode($_REQUEST, JSON_HEX_APOS)), true); 
} 

PHP you still have this option 이전 버전의 경우 :

if (get_magic_quotes_gpc()) { 
    $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST); 
    while (list($key, $val) = each($process)) { 
     foreach ($val as $k => $v) { 
      unset($process[$key][$k]); 
      if (is_array($v)) { 
       $process[$key][stripslashes($k)] = $v; 
       $process[] = &$process[$key][stripslashes($k)]; 
      } else { 
       $process[$key][stripslashes($k)] = stripslashes($v); 
      } 
     } 
    } 
    unset($process); 
} 

거기에는 기능이 없으며 코드가 그렇게 길지 않습니다. =)

+0

그는 5.1.0을 사용하고 있으므로 네임 스페이스가 없습니다. 그는 여전히 * 시도 할 수 있습니다. 확실히 오류가 발생합니다 :) – Gordon

+0

필자는 PHP 5.3.0을 실행중인 로컬 서버에서 프로젝트 작업을하고 PHP 5.2.1을 실행중인 서버에 업로드했습니다. 두통, 두통. –

+0

@Gordon : 오, 나는 그것에 관심을 기울이지 않았다. 내 실수. –

0

runkit_function_remove 없이는 불가능합니다. Runkit은 이와 같은 일을하기위한 것입니다.

if 블록이 완료된 후 함수가 유효합니까? if 블록 내에서 정의 된 경우 나중에 액세스 할 수 없게 될 것이라고 생각했을 것입니다.

+0

틀렸어. 'if' 문장은 그들 자신의 범위를 가지고 있지 않습니다. –

+0

함수가 변수처럼 작동하지 않습니다. 정의 된 후에는 '범위를 벗어남'이 아니며 정의/선언 된 위치에 상관없이 전체 애플리케이션에서 사용할 수 있습니다. –

0

나는 Alix에 동의합니다. 그러나 함수를 제거함으로써 함수가 다른 곳에서 호출되는 것을 피할 수 있습니다. 재귀 함수를 반복 루프로 다시 작성하십시오. 메모리 사용량을 줄이는 이점이 있습니다.

업데이트 : 코드 예에서이 함수가 다시 호출되지 않도록해야하는 이유가 확실하지 않습니다. 배열의 일부 문자열을 반복적으로 형식을 지정하기 만하면 ... 반복적으로이 작업을 수행하고 처음부터 함수를 사용하지 않아도됩니다. 그렇지 않으면 그냥 그대로두고 다시 부르지 마십시오.PHP Manual on Functions에서

+0

그리고 중복 된 코드와 이웃 –

+1

분명히 한 위치에서만 사용되는 함수에서? 나는 확실히 알지 못하지만, 질문에서 확실히 재귀를 사용하는 함수가있는 것처럼 들린다. –

+0

그는 잘못된 이유로 그 일을하고 있을지 모르지만 코드가 한 번만 사용 되더라도 코드를 여러 기능으로 나눌 수 있습니다. –

1

번호를 응축 그러나 함수 정의를 제거은 바보입니다.
else 블록에서 함수를 다르게 정의하고 프로그램 상태에 따라 변경하려면 정의가 필요하며 효과적으로 프로젝트를 디버그에 더 가깝고 더 가깝게 만들거나 해당 함수를 호출하는 코드는 충돌하지 않고 충돌 할 수 있습니다. 런타임에는 정의되지 않습니다. 당신은 단지 조건이 한 번 테스트하려는 경우

class foo { 

    private $bar_function = NULL; 

    public function __construct() { 

     if(/* some condition */) { 
      $this->bar_function = baz; 
     } else { 
      $this->bar_function = bazzer; 
     } 

    } 

    public function bar() { 

     $this->$bar_function(); 

    } 
     ... 

나는 당신이 뭘 하려는지 알 수 없거나,

class foo { 

    public function bar() { 

     if(/* some condition */) { 
      $this->baz(); 
     } else { 
      $this->bazzer(); 
     } 

    } 

    private function baz() { 

     /* if the if condition was met */ 

    } 

    private function bazzer() { 

     /* if the if condition failed */ 

    } 

} 

또는 :

는 클래스에서이 함수를 놓아야합니다 왜 함수 정의를 제거하고 싶습니까?하지만 잘하면이 방법이 더 깔끔하게 할 수 있습니다.

+1

+1, 수업을 사용하여 비공개로 만들기 – Paolo

+0

편집 된 OP에 내가 정확히 무엇을하고 있는지 설명이 추가되었습니다 ... – AlexV

+0

POST, GET 등의 변수를 얻는 Request 클래스와 선택적으로 OOP를 사용할 수 있습니다. 그들에 stripslashes를 사용합니다. stripslashes_deep 함수는 나머지 응용 프로그램이 사용하지 않고 알 수없는 개인 메서드 일 수 있습니다. –

1

나는 조건에 따라 "생중계"또는 "생존"기능을 허용 할 이유가 거의 없지만 질문에 대답하기 위해 익명의 기능을 사용하는 것이 가능합니다. @Gordon은 이미 그것이 완료된 방법을 설명했다. PHP 5.3.0부터 다음과 같이 익명 함수를 사용할 수 있습니다. 합니다 (create_function() 접근 기능적인 차이가 없다.)

if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) 
{ 
    $stripslashes_deep = function($value) 
    { 
     return is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value); 
    } 

    $_POST = array_map($stripslashes_deep, $_POST); 
    $_GET = array_map($stripslashes_deep, $_GET); 
    $_COOKIE = array_map($stripslashes_deep, $_COOKIE); 
    $_REQUEST = array_map($stripslashes_deep, $_REQUEST); 

    unset ($stripslashes_deep); 
} 
+0

'array_map ('stripslashes_deep', $ value)'가 작동할까요?! 어쨌든, PHP 5.3+에는 좀 더 우아한 해결책이 있습니다. 제 답변을보십시오. –

+0

예, 작동합니다 (테스트 됨). 당신의 솔루션은 비열하고 잘합니다! :) –

+0

고마워요! 저는 람다 함수에 대한 열렬한 팬이 아니지만 그럼에도 불구하고 잘 알고 있습니다. –

0

이런 그 사용량을 변화시켜 기능을 대체하기위한 다른 방법이있을 수있다;

function function1(){ 
echo "1"; 
} 

function function2(){ 
echo "2"; 
} 

if(FUNCTION_CHOOSER_CONDITION) $the_function = "function2"; 
else $the_function="function1"; 
$the_function(); // displays 2 if condition is TRUE; 

아마이 없습니다 당신이 상황에서 당신은이 기능의 교체에 대해 이야기 할 적절한 장소가 비록 기능하지만 난을 파괴하고 싶어한다.

3

초기 함수 정의는 다음과 같습니다

// includes/std_functions.php 
if (! function_exists('the_function')) { 
    function the_function() { 
    global $thefunction; 
    return call_user_func_array($thefunction, func_get_args()); 
    } 
    $GLOBALS['thefunction'] = function() { 
    echo 'foo'; 
    }; 
} 

당신은 당신이 코드를 다시 작성할 수있는 테스트 조건이있는 경우 : 그 전이나로드됩니다

// somewhere in your code 
if (<replacethefunctioncondition>) { 
    $GLOBALS['thefunction'] = function() { 
    echo 'bar'; 
    }; 
} 

다른에 과부하를하는 경우 포함을 원본 파일 다음 :

// includes/custom_functions.php 
if (! function_exists('the_function')) { 
    function the_function() { 
    global $thefunction; 
    return call_user_func_array($thefunction, func_get_args()); 
    } 
} 
$GLOBALS['thefunction'] = function() { 
    echo 'bar'; 
}; 
5

PHP 5.3부터는 ano nymous 기능 :이 같은

$anonymous_function = function($value){ 
    // do stuff 
}; 

전화를 :

$returned_value = $anonymous_function('some parameter'); 

이 기능을 삭제하려면, 단지 해제 변수 : 여기

unset($anonymous_function); 

는 기능을 구현하는 방법의 예입니다 :

$stripslashes_deep = function (&$object){ 
    global $stripslashes_deep; 
    if(is_array($object)) 
    foreach($object as &$value){ 
     if(is_array($value)) 
     $stripslashes_deep($value); 
     else 
     $value = stripslashes($value); 
    } 
}; 

익명 함수에는 이름이 없습니다. 따라서 array_map은 매개 변수로만 함수 이름을 사용하기 때문에 사용할 수 없습니다.

익명 함수에는 가변 범위가 있습니다. 따라서 함수를 포함하는 변수를 전역 변수로 선언하여 재귀 함수 내에서 변수에 도달해야합니다.

불행히도 익명 함수 내에서 일반 함수를 정의하면 변수가 해제 된 후에도 변수가 전역 적으로 사용 가능하게됩니다. 변수가입니다. (나는 그 이점을 실제로 보지 못합니다. 나중에 실수를 저지르는 것이 실수라고 생각합니다 :-)

+0

[작동하지 않을 것입니다 - 먼저 세미콜론이 누락되어 있으며 둘째 'stripslashes_deep' (https://eval.in/521784)라는 기능이 없습니다. – h2ooooooo

+1

나는 여기에서 요점을 놓치고 있다고 생각한다. :) 그러나 세미콜론에 대해서는 당신이 맞다. 감사. –

관련 문제