[php] PHP의 클로저… 정확히 무엇이며 언제 사용해야합니까?

그래서 저는 멋진 최신 객체 지향 방식으로 프로그래밍하고 있습니다. PHP가 구현하는 OOP의 다양한 측면을 정기적으로 사용하지만 언제 클로저를 사용해야할지 궁금합니다. 클로저를 구현하는 것이 유용 할 때를 밝힐 수있는 전문가가 있습니까?



답변

PHP는 5.3에서 기본적으로 클로저를 지원합니다. 클로저는 작고 특정한 목적으로 만 사용되는 로컬 함수를 원할 때 좋습니다. 클로저에 대한 RFC 는 좋은 예입니다.

function replace_spaces ($text) {
    $replacement = function ($matches) {
        return str_replace ($matches[1], ' ', ' ').' ';
    };
    return preg_replace_callback ('/( +) /', $replacement, $text);
}

이렇게하면 replacement함수를 내부 replace_spaces()에서 로컬로 정의 할 수 있으므로 다음과 같지 않습니다.
1) 전역 네임 스페이스를 어지럽히 기
2) 사람들이 3 년 동안 다른 함수 내에서만 사용되는 전역 적으로 정의 된 함수가 있는지 궁금해합니다.

그것은 일을 체계적으로 유지합니다. 함수 자체에 이름이 없는지 확인하십시오. 단순히에 대한 참조로 정의되고 할당됩니다 $replacement.

하지만 PHP 5.3을 기다려야합니다. 🙂

또한 키워드를 사용하여 범위 밖의 변수에 클로저로 액세스 할 수 있습니다 use. 이 예를 고려하십시오.

// Set a multiplier  
 $multiplier = 3;

// Create a list of numbers  
 $numbers = array(1,2,3,4);

// Use array_walk to iterate  
 // through the list and multiply  
 array_walk($numbers, function($number) use($multiplier){
 echo $number * $multiplier;
 });

여기에 훌륭한 설명이 있습니다. PHP 람다와 클로저는 무엇입니까?


답변

현재 결정한 작업을 수행하는 기능이 미래에 필요할 때.

예를 들어, 구성 파일을 읽고 매개 변수 중 하나가 hash_method알고리즘에 대해가 multiply아니라 라고 알려주 square는 경우 무언가를 해시해야 할 때마다 사용할 클로저를 만들 수 있습니다.

클로저는 (예 :)에서 만들 수 있습니다 config_parser(). (구성 파일에서) do_hash_method()지역 변수를 사용하여 호출되는 함수를 생성합니다 config_parser(). do_hash_method()호출 될 때마다 config_parser()해당 범위에서 호출되지 않더라도 의 로컬 범위에있는 변수에 액세스 할 수 있습니다.

좋은 가상의 예 :

function config_parser()
{
    // Do some code here
    // $hash_method is in config_parser() local scope
    $hash_method = 'multiply';

    if ($hashing_enabled)
    {
        function do_hash_method($var)
        {
            // $hash_method is from the parent's local scope
            if ($hash_method == 'multiply')
                return $var * $var;
            else
                return $var ^ $var;
        }
    }
}


function hashme($val)
{
    // do_hash_method still knows about $hash_method
    // even though it's not in the local scope anymore
    $val = do_hash_method($val)
}


답변

기술적 인 세부 사항 외에도 클로저는 함수 지향 프로그래밍으로 알려진 프로그래밍 스타일의 기본 전제 조건입니다. 클로저는 대략 객체 지향 프로그래밍에서 객체를 사용하는 것과 동일한 용도로 사용됩니다. 데이터 (변수)를 일부 코드 (함수)와 함께 바인딩 한 다음 다른 곳으로 전달할 수 있습니다. 따라서 프로그램 작성 방식에 영향을 주거나 프로그램 작성 방식을 변경하지 않으면 전혀 영향을주지 않습니다.

PHP의 맥락에서 PHP는 이미 클래스 기반, 객체 지향 패러다임 및 이전 절차 적 패러다임에 무겁기 때문에 약간 이상합니다. 일반적으로 클로저가있는 언어에는 전체 어휘 범위가 있습니다. 이전 버전과의 호환성을 유지하기 위해 PHP는 이것을 얻지 않을 것입니다. 따라서 여기서 클로저가 다른 언어와는 조금 다를 것입니다. 나는 그들이 어떻게 사용 될지 아직 정확히 보지 못했다고 생각합니다.


답변

나는 troelskn의 게시물에서 제공하는 컨텍스트를 좋아합니다. PHP에서 Dan Udey의 예제와 같은 작업을하고 싶을 때는 OO 전략 패턴을 사용합니다. 제 생각에는 런타임에 동작이 결정되는 새로운 전역 함수를 도입하는 것보다 훨씬 낫습니다.

http://en.wikipedia.org/wiki/Strategy_pattern

PHP에서 메소드 이름을 포함하는 변수를 사용하여 함수와 메소드를 호출 할 수도 있습니다. 따라서 Dan의 또 다른 예는 다음과 같습니다.

class ConfigurableEncoder{
        private $algorithm = 'multiply';  //default is multiply

        public function encode($x){
                return call_user_func(array($this,$this->algorithm),$x);
        }

        public function multiply($x){
                return $x * 5;
        }

        public function add($x){
                return $x + 5;
        }

        public function setAlgorithm($algName){
                switch(strtolower($algName)){
                        case 'add':
                                $this->algorithm = 'add';
                                break;
                        case 'multiply':        //fall through
                        default:                //default is multiply
                                $this->algorithm = 'multiply';
                                break;
                }
        }
}

$raw = 5;
$encoder = new ConfigurableEncoder();                           // set to multiply
echo "raw: $raw\n";                                             // 5
echo "multiply: " . $encoder->encode($raw) . "\n";              // 25
$encoder->setAlgorithm('add');
echo "add: " . $encoder->encode($raw) . "\n";                   // 10

물론, 어디서나 사용할 수 있도록하려면 모든 것을 정적으로 만들 수 있습니다.


답변

클로저는 기본적으로 한 컨텍스트에서 정의를 작성하지만 다른 컨텍스트에서 실행하는 함수입니다. Javascript는 모든 곳에서 JavaScript에서 사용되기 때문에 이러한 것들을 이해하는 데 많은 도움이되었습니다.

PHP에서는 함수 내에서 “전역”(또는 “외부”) 변수의 범위와 접근성이 다르기 때문에 JavaScript보다 덜 효과적입니다. 그러나 PHP 5.4부터 클로저는 객체 내에서 실행될 때 $ this 객체에 액세스 할 수 있으므로 훨씬 더 효과적입니다.

이것이 클로저에 관한 것이며 위에 쓰여진 내용을 이해하는 것으로 충분해야합니다.

즉, 어딘가에 함수 정의를 작성하고 함수 정의 내에서 $ this 변수를 사용한 다음 함수 정의를 변수에 할당 한 다음 (다른 사용자는 구문 예제를 제공함)이 변수를 객체에 전달할 수 있어야합니다. 객체 컨텍스트에서 호출하면 함수는 $ this를 통해 객체를 액세스하고 조작 할 수 있습니다. 마치 해당 객체의 클래스 정의에 정의되어 있지 않고 다른 곳에서 정의 된 메서드 중 하나 인 것처럼.

명확하지 않더라도 걱정하지 마세요. 사용하기 시작하면 명확 해집니다.


답변

기본적으로 Closure는 외부 변수에 액세스 할 수있는 내부 함수이며, 익명 함수 (이름이없는 함수)에 대한 콜백 함수로 사용됩니다.

 <?php
      $param='ironman';
      function sayhello(){
          $param='captain';
          $func=function () use ($param){
                $param='spiderman';
          };
       $func();
       echo  $param;
       }
      sayhello();
?>

//output captain

//and if we pass variable as a reference as(&$param) then output would be spider man;


답변

다음은 PHP의 클로저 예제입니다.

// Author: HishamDalal@gamil.com
// Publish on: 2017-08-28

class users
{
    private $users = null;
    private $i = 5;

    function __construct(){
        // Get users from database
        $this->users = array('a', 'b', 'c', 'd', 'e', 'f');
    }

    function displayUsers($callback){
        for($n=0; $n<=$this->i; $n++){
            echo  $callback($this->users[$n], $n);
        }
    }

    function showUsers($callback){
        return $callback($this->users);

    }

    function getUserByID($id, $callback){
        $user = isset($this->users[$id]) ? $this->users[$id] : null;
        return $callback($user);
    }

}

$u = new users();

$u->displayUsers(function($username, $userID){
    echo "$userID -> $username<br>";
});

$u->showUsers(function($users){
    foreach($users as $user){
        echo strtoupper($user).' ';
    }

});

$x = $u->getUserByID(2, function($user){

    return "<h1>$user</h1>";
});

echo ($x);

산출:

0 -> a
1 -> b
2 -> c
3 -> d
4 -> e
5 -> f

A B C D E F

c