array_map()
เป็นฟังก์ชันที่เอาไว้รับอาเรย์เข้าไป เอามาประมวลผล value ของอาเรย์ แล้วคืนค่ากลับออกมาเป็นอาเรย์ตัวใหม่ โดยค่า index หรือ key ของอาเรย์นั้นจะคงเดิมเหมือนกับในอาเรย์ต้นฉบับ
อากิวเมนต์ตัวแรกของฟังก์ชันจะเป็น callback function ส่วนตัวถัดไปจะเป็นอาเรย์ที่ต้องการจะเอามาประมวลผล
<?php // กรณี indexed array $numbers = [1, 2, 3, 4, 5, 6]; $multiplied = array_map( function( $number ) { return $number * 2; }, $numbers ); print_r( $multiplied ); // ได้ผลลัพธ์เป็น [2, 4, 6, 8, 10, 12]; // กรณี associative array $fruits = [ 'banana' => 1, 'orange' => 5, 'apple' => 3, ]; $restocked = array_map( function( $fruit ) { return $fruit + 5; }, $fruits ); print_r( $restocked ); /* ผลลัพธ์: [ 'banana' => 6, 'orange' => 10, 'apple' => 8, ] */
ท่าที่ผมเอามาใช้ประจำคือเอามาประมวลผล WP_Query::posts
ออกมาเป็นก้อนข้อมูล ก่อนที่จะส่งไปให้เท็มเพลตใช้งาน เช่น
<?php $movies_data = new WP_Query( [ 'post_type' => 'movies', ] ); $movies = array_map( function( $movie ) { return [ 'title' => $movie->post_title, 'genre' => get_field( 'genre', $movie->ID ), ]; }, $movies_data ); print_r( $movies ); /* ผลลัพธ์: [ [ 'title' => 'Pandorum', 'genre' => 'Sci-fi', ], [ 'title' => 'Pearl Harbor', 'genre' => 'Action', ], ] */
ข้อดีของการใช้ array_map()
คือมันจะทำให้โค้ดเราสะอาดขึ้น ช่วยลดความสับสนเวลาเขียนโค้ด และเป็นการล็อคตัวแปรให้อยู่แค่ในสโคปของ closure function ไม่ต้องกลัวว่าจะเผลอไปเปลี่ยนค่าตัวแปรนอกฟังก์ชัน
ปกติแล้วเวลาจะลูปประมวลผลตัวแปร เรามักจะใช้ foreach
กัน ซึ่งมันมีปัญหาขาประจำอย่างหนึ่งคือเผลอเอาตัวแปรเก่ามาใช้แล้วลืมรีเซ็ตค่า (ซึ่งการรีเซ็ตค่าก็ต้องประกาศตัวแปรเปล่าๆ หนึ่งบรรทัดเพิ่มเข้ามาให้โค้ดรกเล่นๆ) เช่น
<?php // บรรทัดที่ 10 $source = [ ... something ... ]; foreach ( $data => $value ) { $data[] = doSomething( $value ); } // บรรทัดที่ 120 ลืมไปแล้วว่าเคยใช้ $data แล้วลืมรีเซ็ตตัวแปร $source = [ ... another thing ... ]; foreach ( $data => $value ) { $data[] = doAnother( $value ); // ผลลัพธ์ไปรวมกับ $data ที่เคยใช้ก่อนหน้านี้ } // บรรทัด 150 รีเซ็ต $data ให่้สักหน่อย $source = [ ... everything ... ]; $data = []; foreach ( $data => $value ) { $data[] = doEverything( $value ); }
อาจจะดูเล็กน้อย แต่ผมบอกว่าเลยเรื่องหลงๆ ลืมๆ แบบนี้ สร้างบั๊กตัวโตมาหลายรอบแล้ว
และหากเราใช้ PHP 7.4 ในหลายกรณีเราสามารถทำให้โค้ดสะอาดและอ่านง่ายได้ขึ้นอีกนิดหน่อยด้วยการใช้ arrow function เช่นจากตัวอย่างข้างบน เราเขียนส่วน array_map()
ใหม่ได้แบบนี้
$movies = array_map( fn( $movie ) => [ 'title' => $movie->post_title, 'genre' => get_field( 'genre', $movie->ID ), ], $movies_data );
ทั้งนี้มีข้อควรระวังอยู่เหมือนกัน คือในกรณีที่มีข้อมูลจำนวนมาก (เช่นสักล้านตัว) array_map()
จะกินใช้เวลาในการประมวลผลกว่าการใช้ foreach
เพราะมันมี overhead ที่เกิดจากการเรียกใช้ callback function เพิ่มเข้ามา
Leave a Reply