인프런 커뮤니티 질문&답변

devedu님의 프로필 이미지
devedu

작성한 질문수

PHP 7+ 프로그래밍

함수 지향적 php? 에 대해서 하나도 모르겠습니다. 코드 설명해주실 수 있으신가요?

작성

·

774

0

콜백함수 개념이 없어서 그런지 이해할 수가 없습니다ㅠㅠ

더 상세하게 설명해주실 수 있으실까요?

아래 코드를 이해하기 위해 어떻게 공부하면 될까요?

function first($query, $params) 
{
    return raw($query, $params, function ($result) {
        if ($row = mysqli_fetch_assoc($result)) {
            if (is_array($row) && count($row) > 0) {
                return $row;
            }
        }
        return [];     
    });
}

function rows($query, ...$params)
{
    return raw($query, $params, function ($result) {
        $rows = [];
        while ($row = mysqli_fetch_assoc($result) {
            array_push($rows, $row);
        }
        return $rows;
    });
}


function execute($query, ...$params) 
{
    return raw($query, $params);
}


function raw($query, $params=[], $callback=null) 
{
    $stmt = mysqli_prepare($GLOBALS['DB_CONNECTION'], $query);
    if (count($params) > 0) {
        $mappings = [
            'integer' => 'i',
            'string'  => 's',
            'double'  => 'd'
        ];
        $bindstring = array_reduce($params, function ($bindstring, $arg) use ($mappings) {
            return $bindstring .= $mappings[gettype($arg)];
        });
        mysqli_stmt_bind_param($stmt, $bindstring, ...array_values($params));
    }
    if (mysqli_stmt_execute($stmt)) {
        if (is_callable($callback)) {
            $res = call_user_func($callback, mysqli_stmt_get_result($stmt));
        }
        $is = $res ?? true;
    }
    mysqli_stmt_close($stmt);
    return $is ?? [];
}

이 함수는 어떻게 실행되는 건가요? $posts와 $post가 어떻게 되는 건지 모르겠습니다

$posts = array_map(function ($post) {
    $stmt = mysqli_prepare($GLOBALS['DB_CONNECTION'], 'SELECT * FROM users WHERE id = ? LIMIT 1');
    mysqli_stmt_bind_param($stmt, 'i', $post['user_id']);
    if (mysqli_stmt_execute($stmt)) {
        $result = mysqli_stmt_get_result($stmt);
        [ 'username' => $username ] = mysqli_fetch_assoc($result);
    }
    mysqli_stmt_close($stmt);

    $content = filter_var(mb_substr(strip_tags($post['content']), 0, 200), FILTER_SANITIZE_FULL_SPECIAL_CHARS);

    $mappings = array_merge(
        compact('username', 'content'),
        [
            'created_at' => date('h:i A, M j', strtotime($post['created_at'])),
            'url'        => "/Board/post/read.php?id=" . $post['id']
        ]
    );
    return array_merge($post, $mappings);
}, $posts);

답변 6

1

정상우님의 프로필 이미지
정상우
지식공유자

네 그거 보시면 됩니다~~

1

정상우님의 프로필 이미지
정상우
지식공유자

자바스크립트를 알고 계시다면, 자바스크립트로 함수형 프로그래밍을 공부해주시면 될텐데, 인프런에 자바스크립트 함수형 프로그래밍 무료 강좌가 있는 것으로 알고 있습니다. 그것을 수강하시면 어느정도는 감을 잡으실 수 있을겁니다.

사실 위의 코드만 어느정도 이해하면 객체지향 파트 들어가도 괜찮습니다. 저 수준 이상의 함수형은 나오지 않고 오히려 거기서는 객체지향이 제일 먼저이기 때문에 다른 관점으로 이해해야 합니다. :)

1

정상우님의 프로필 이미지
정상우
지식공유자

[아래의 부분은 함수형 프로그래밍의 이론적인 부분입니다.]

일단, 함수지향 자체를 먼저 이야기하죠. 함수지향 프로그래밍은 함수를 가지고 데이터를 지지고 볶는 것을 말하는데, 기본 단위가 함수이기 때문에 함수 자체가 외부에 영향을 주는 일이 없고 입력과 출력의 형태로 소통합니다. 따라서 함수의 구현이나 알고리즘을 명시하는 것이 아니라 어떤 것을 입력해서 어떠한 값을 받는지에 대한 것만 이야기합니다. 또한 콜백 형태로 넘겨주면 콜백으로 넘겨준 함수의 실행과 평가는 실행 시점과 관계없이 어느 때든 할 수 있습니다.

PHP 는 함수를 값으로 넘기거나 변수에 지정할 수 있고, 또한 함수를 리턴할 수도 있습니다. 이것이 먼저 되어야 함수형 프로그래밍을 할 수 있으며 함수를 값으로 취급할 수 있으므로 이를 일급 함수라 칭하고, 함수를 파라매터로 받거나 리턴하는 형태로 함수를 활용하는 함수에 대해서는 고차 함수라고 이야기합니다.

콜백 함수는 사용자가 직접 호출하지 않으며 런타임 중에 넘겨준 함수를 프로그램이 호출합니다.

아래의 코드는 함수형에서 가장 기초적으로 이야기하는 each() 함수이며 그저 배열을 한 바퀴 돌아서 값을 넘겨줍니다.

function each(array $arr, \Closure $callback)
{
    foreach ($arr as $key => $value) {
        call_user_func($callback, $value, $key);
    }
}

each(['Hello, world', 'Who are you?'], fn ($value) => var_dump($value));

위의 코드를 이해하면 함수형을 이해할 수 있습니다. \Closure 와 같은 내용은 객체지향 부분이므로 일단 무시합니다. 어찌되었든 콜백 함수를 받아서 호출해주며 each() 함수를 사용하는 사용자 입장에서는 함수를 값으로써 넘겨주면 됩니다. 위의 코드를 이해가 될 때까지 고민하셔야 본 어플리케이션도 이해할 수 있습니다.

array_map() 에 해당하는 map() 함수는 파라매터로 받은 배열을 돌면서 콜백 함수가 반환한 값으로 각 원소를 대체합니다. 기본에 만들어둔 each() 함수를 사용합니다. 

function map(array $arr, \Closure $callback) 
{
    each($arr, function ($_, $key) use (&$arr, $callback) {
        $arr[$key] = call_user_func($callback);
    });
    return $arr;
}

$goodbyeMessages = map(['Hello, world', 'Who are you?'], fn() => 'Goodbye');

// -> ['Goodbye', 'Goodbye']
var_dump($goodbyeMessages);

마지막으로 array_reduce() 에 대해 알아봅니다 reduce() 함수는 처음엔 이해하기 어려울 수도 있습니다. 배열을 순회하면서 각 값을 이용해 접어서 하나의 값으로 만듭니다. 예를 들어 [1, 2, 3, 4] 를 적용한 아래의 결과값은 10이 됩니다.

function reduce(array $arr, \Closure $callback) {
    $r = null;
    each($arr, function ($value, $key) use (&$r, $callback) {
        $r = call_user_func($callback, $r, $value, $key);
    });
    return $r;
}

$sum = reduce([1, 2, 3, 4], fn ($sum, $arg) => $sum += $arg);
var_dump($sum); // -> 10

여기서 reduce() 의 구현을 보면, 값으로 넘겨준 $r 변수에 대해 콜백으로 받은 리턴값을 또 다시 $r 변수에 할당합니다. 이부분이 핵심입니다. 이렇듯 reduce() 는 배열 원소에 대해 값을 적용하고 이를 하나의 값으로 반환합니다. 본 어플리케이션에서 쓰인 의미 또한 같습니다. 

함수형 프로그래밍을 공부하기 위해서는 PHP 보다는 자바스크립트로 함수형 프로그래밍을 공부하심을 추천드립니다. 사실 그게 더 자료가 많기 때문이죠. 설명이 이해가 되었길 바랍니다 :)

0

어렵다.ㅠ

0

devedu님의 프로필 이미지
devedu
질문자

'자바스크립트로 알아보는 함수형 프로그래밍 (ES5)' 이라는 강의를 찾아서 지금 보고 있습니다. 이 강의가 연관된 강의가 맞나요?

0

devedu님의 프로필 이미지
devedu
질문자

바로 php oop 강의로 들어가려고 했는데... 막상 들어가면 이해를 못할 거 같네요ㅠㅠ 인프런 강의나 다른 곳 강의 추천해주실 수 있을까요? 강의와는 상관없이 제가 모르는 부분이었는데 상세하게 설명해주셔서 감사합니다. 이해는 제 몫일 거 같네요.

devedu님의 프로필 이미지
devedu

작성한 질문수

질문하기