Chắc hẳn ai cũng biết đến vòng lặp foreach. Đây là một vòng lặp vô cũng hữu ích để duyệt một mảng trong PHP. Hôm nay chúng ta cùng nhau tìm hiểu bản chất của vòng lặp này nhé!
Ở mỗi vòng lặp foreach php sẽ tạo ra các bản sao để chúng ta lấy dữ liệu của phần tử đang lặp đó, bản sao này sẽ được loại bỏ ngay lập tức sau khi kết thúc vòng lặp. Và ở mỗi vòng lặp sẽ kiểm tra còn phần tử liền kề hay không? Nếu còn thì vòng lặp được tiếp tục, ngược lại thì sẽ dừng. Ví dụ dưới đây là một cách sử dụng vòng lặp foreach trong php thông dụng:
$array = array(‘one’, ‘two’, ‘three’, ‘four’, ‘five’); foreach ( $array AS $value ) { echo $value.'<br/>’; }
Chạy lên kết quả sẽ là:
one two three four five
Các bản sao của biến $array được tạo ra nên chúng ta không thể thay đổi giá trị các phần tử trong mảng bằng cách thay đổi giá trị biến $value sau as theo cách thông thường
$array = array(‘one’, ‘two’, ‘three’, ‘four’, ‘five’); foreach ( $array as $value ) { $value = strtoupper($value); } echo ‘<pre>’; print_r($array);
Kết qủa là:
Array ( [0] => one [1] => two [2] => three [3] => four [4] => five )
Trong vòng lặp mình đã biến đổi giá trị của các phần tử sang chữ hoa, nhưng kết thúc vòng lặp mình in ra giá trị của mảng thì nó không hề thay đổi.
Vậy có cách nào để thay đổi giá trị của phẩn tử đang lặp thông qua biến copy $value? Để thay đổi giá trị của phần tử hiện tại ta sẽ sử dụng tham chiếu. Ví dụ:
$array = array(‘one’, ‘two’, ‘three’, ‘four’, ‘five’); foreach ( $array as &$value ) { $array = strtoupper($value); } echo ‘<pre>’; print_r($array);
Kết qủa là:
Array ( [0] => ONE [1] => TWO [2] => THREE [3] => FOUR [4] => FIVE )
Giá trị các phần tử của mảng đã bị thay đổi sang chữ in hoa sau khi vòng lặp foreach kết thúc.
Như vậy ta có kết luận rằng khi bắt đầu vòng lặp foreach, PHP sẽ tạo ra một bảng sao của mảng để lặp nên khi chúng ta thay đổi hoàn toàn không ảnh hưởng, nhưng nếu chúng ta sử dụng tham chiếu để truy xuất đến mảng gốc thì sẽ không có vụ tạo mảng copy nên mọi thứ đều gọi tới mảng gốc, từ đó ta có thể thay đổi giá trị cho mảng gốc.
Xem tiếp ví dụ dưới đây:
$array = array(‘one’, ‘two’, ‘three’, ‘four’, ‘five’); foreach ( $array as $value ) { $array[] = $value; } echo ‘<pre>’; print_r($array);
Kết quả:
Array ( [0] => one [1] => two [2] => three [3] => four [4] => five [5] => one [6] => two [7] => three [8] => four [9] => five )
Trong mỗi vòng lặp ta đã gán thêm một phẩn tử vào mảng thì đáng lẽ ra vòng lặp sẽ dẫn đến lặp vô hạn. Nhưng không, tại vì trong vòng lặp đang lặp mảng copy của mảng gốc, vì thế khi ta thay đổi mảng gốc thì không ảnh hưởng gì, và sau khi vòng lặp kết thúc mảng copy sẽ được xóa và mảng gốc đã bị thay đổi.
Bây giờ sử dụng tham chiếu các phần tử trong mỗi lần lặp xem thế nào?
$array = array(‘one’, ‘two’, ‘three’, ‘four’, ‘five’); foreach ( $array as &$value ) { $array[] = $value; echo $value . ‘ ‘; } echo ‘<pre>’; print_r($array);
Chạy lên thì vòng lặp foreach bị lặp vô hạn. Tại sao vậy? Tại vì mảng copy KHÔNG được tạo ra, nó sẽ sử dụng đến mảng gốc và sau mỗi vòng lặp mảng gốc sẽ thêm một phần tử, ở cuối mỗi vòng lặp foreach sẽ kiểm tra còn phần tử liền kề hay không để tiếp tục lặp, rõ ràng ta đang truy xuất đến mảng gốc nên phần tử liền kề luôn luôn tồn tại.
Nhưng giả sử mảng chỉ có một phần tử thì sao?
$array = array(‘one’); foreach ( $array as $key => &$value ) { $array[] = $value; echo($value); }
Chạy lên thì nó lại không lặp vô hạn. Tại vì theo như trên mình trình bày: trình biên dịch sẽ kiểm tra còn phần tử kế tiếp hay không, lúc này chỉ có 1 phần tử nên nó chạy luôn và sẽ dừng. Tuy nhiên vẫn có thể thay đổi giá trị cho mảng đó nhé vì ta đang tham chiếu mà.
Nhưng mọi chuyện không phải đơn giản như vậy, ta xét ví dụ tiếp theo sau đây:
$array = array(‘one’, ‘two’); $a = &$array; foreach ( $array as $value ) { $array[] = $value; echo($value); }
Chạy lên vòng lặp foreach vẫn bị lặp vô hạn. Như vậy nếu mảng bị tham chiếu ở ngoài vòng lặp thì bản thân nó vẫn bị lặp vô hạn. Trường hợp này lý do là do lúc ta tham chiếu thế này thì ta đã có 2 biến tham chiếu đến vị trí ô nhớ đó nên trình biên dịch sẽ không copy mà chạy thẳng vào mảng gốc. Vì thế dẫn đến vô hạn.
Xét ví dụ tiếp theo:
$array = array(‘one’, ‘two’, ‘three’, ‘four’, ‘five’); $a = &$array; foreach ( $array as $value ) { $value = strtoupper($value); } echo ‘<pre>’; print_r($array);
kết quả sẽ là:
Array ( [0] => one [1] => two [2] => three [3] => four [4] => five )`
Trong vòng lặp mình đã thay đổi giá trị của các phần tử sang in hoa nhưng kết thúc vòng lặp mảng lại không bị ảnh hưởng.
Kết luận:
- Foreach trong PHP sẽ tạo ra một bản sao của mảng để lặp
- Muốn thay đổi phần tử hiện tại trong khi lặp phải dùng tham chiếu.
Nguồn: http://freetuts.net/