Giới thiệu qua về Splat Operator trong PHP

Hồi tháng trước, trong lúc bối rối mình đã có viết qua một chút về Magic methods trong PHP. Phần đầu của bài viết này, lẽ ra nên nhập vào bài đó thì hợp hơn, nhưng thôi, lỡ rồi, căn bản mục tiêu duy nhất giữ 2 ngày lương khỏi bị cướp cũng đã đạt đc. Phần đầu tiên, tiếp nối tiết mục lần trước, mình muốn giới thiệu tiếp một toán tử khá thú vị và hữu ích khác của PHP ( từ phiên bản 5.6 trở lên ) , 2 toán tử tuy-hai-mà-một này, được gọi chung là splat operator

Splat Operator

Variadic functions

  • Làm luôn cái ví dụ cho nó trực quan. Bạn hãy thử chạy đoạn code này

function concatenate(...$parameters) {
    $string = '';
    foreach($parameters as $parameter) {
        $string .= $parameter;
    }
    return $string;
}
echo concatenate(" ༼ ", "つ ", "◕_◕", " ༽つ", " Give", " DIRETIDE");

sẽ cho ta output ༼ つ ◕_◕ ༽つ give DIRETIDE . Nghĩa là ở đây, khi ta khai báo một hàm nhận biến đầu vào có dạng ...$parameter, khi ta gọi hàm đó và truyền vào nhiều hơn 1 biến, thì tất cả parameter ta truyền sẽ được cho vào cùng một mảng , bên trong hàm, ta có thể gọi đến mảng đó bằng $parameters Và tất nhiên ( cái này nói hơi bị thừa, nhưng thêm vào cho nó dài =)), với lại tránh biết đâu có thánh hiểu nhầm được thật ), ta hoàn toàn có thể sử dụng toán tử naỳ kèm với các tham số khác như thường. Ví dụ

function concatenate($method, ...$parameters) {
    $string = '';
    foreach($parameters as $parameter) {
        $string .= $parameters;
    }
    
   return $method($string);
}
echo concatenate("strtoupper", " ༼ ", "つ ", "◕_◕", " ༽つ", " Give", " DIRETIDE");

Trong trường hợp này, khi ta gọi hàm concatenate() và truyền vào nhiều hơn 2 tham số, thì từ tham số thứ 2 trở đi, tất cả sẽ được cho vào trong array $parameters, và output của ta ở đây sẽ là ༼ つ ◕_◕ ༽つ GIVE DIRETIDE.

Lan man thêm một chút là, như ngay trong Manual của php.net cũng có đề cập, Variadic function được giới thiệu có thể dùng thay vì func_get_args(), có nghĩa là ta hoàn toàn có thể viết hàm như trên, dùng func_get_args() .


function concatenate() {
    $parameters = func_get_args();
    $string = '';
    foreach($parameters as $parameter) {
        $string .= $parameter;
    }
    return $string;
}
echo concatenate(" ༼ ", "つ ", "◕_◕", " ༽つ", " Give", " DIRETIDE");

Đoạn này cũng sẽ cho ta output ༼ つ ◕_◕ ༽つ give DIRETIDE. Tl;dr : Khi bạn gặp tình huống mà ta chưa biết sẽ truyền bao nhiêu tham số vào trong hàm, thì Variadic function là một giải pháp.

Argument unpacking

Vâng, đứng một mình thì nó cũng không thú vị lắm, nên xin được giới thiệu nửa còn lại của nó, đối lập với Variadic functionArgument unpacking . Và để cho nó vui, thì ở đây cũng xin được trình bày theo lối ngược lại, nghĩa là giải thích trước rồi ví dụ. Bây giờ, hãy tưởng tượng, ta có một function dailyReport() , trong đó ta report lại những công việc mình đã làm trong ngày, không quá 4 việc. Việc nào làm thì ghi ra, việc nào không thì ghi là Refractor code vào đấy. Một ông bạn "tốt" đã viết cho ta một hàm getTodayJobs() rồi, trong đó trả về cho ta tên những đầu việc ta đã làm, có điều là có nhiều ngày đẹp trời, ít việc, cả ngày bạn làm được ít hơn 4 job. Giờ nếu như bình thường, ta viết có thể nó sẽ đại loại thế này

function dailyReport() {
    $jobs = $this->getTodayJobs();
    for ($i=0; $i < 4; $i++) { 
        if (isset($jobs[$i])) {
            echo 'I was working on ' . $jobs[$i] . "\r\n";
         } else {
             echo 'I was Refractor code' ."\r\n";
        }
    }
    return;
}

Vâng, code cùi , nhưng đại loại nó thế. Hay code đỡ thối hơn tẹo, thì ta có thể dùng array_pad đưa array ta nhận được về length mong muốn, đỡ phải if else

function dailyReport() {
    $jobs = array_pad($this-getTodayJobs(), 4, 'Refractor code');
    foreach ($jobs as $job) {
        echo 'I was working on ' . $jobs . "\r\n";
    }
}

Rồi, giờ vào vấn đề chính, ở đây ta dùng Argument unpacking thì sao

function makeReport($first = 'Refractor code', $second = 'Refractor code', $third = 'Refractor code', $fourth = 'Refractor code') {
    echo 'First, i was working on ' . $first . "\r\n";
    echo 'After that, i move to ' . $second. "\r\n";
    echo 'In the after noon, i tackle the problem of ' . $third . "\r\n";
    echo 'My final job of the day was ' . $forth;
}
function dailyReport() {
    $jobs = $this->getTodayJobs();
    $this->makeReport(...$jobs);
}

Syntax ở đây tương tự như trên, ta cùng dùng cú pháp ...$parameters, nhưng trong trường hợp này, khi ta viết

$this->makeReport(...$jobs);

ta đã thực hiện việc gọi đến hàm makeReport(), và lần lượt truyền các phần tử thuộc array $jobs tương ứng lần lượt với từng parametes của hàm makeReport(). Ở đây xin có một lưu ý không nhỏ lắm, đó là Argument unpacking không hoạt động với các associative array ( nghĩa là các array có dạng như kiểu ['Apple' => 'red', 'Watermelon' => 'green']

Giới thiệu xong về magic methodssplat operator rồi, hẹn gặp lại ở 2 ngày lương tháng sau, khi đó mình sẽ giới thiệu qua một vài chi tiết trong phần base của laravel framework, trong đó có động đến các khái niệm này. Chào thân ái và quyết thắng.