Use PHP arrays like a boss

Use PHP arrays like a boss

These are the slides from a talk given at WordCamp Los Angeles 2016.

You’ve heard of the good ol’ school PHP loops. You have your “for” loops, your “foreach” loops, your “while” loops, your “fruit” loops… Well maybe not that last one!

As a WordPress developer, you use arrays and loops all the time. They’re an essential part of your developer toolbox. But do you know everything about them?

PHP has a wealth of array functions. They’re used by PHP experts to make their life easier. They let you reduce the amount of PHP code you need. This helps prevent bugs and makes your code more maintainable.

You’ll learn about functions like array_filter, array_map and array_reduce. All within the context of regular WordPress work. By the end of this talk, loops won’t look at you the same way ever again.

You can read the companion article at: https://carlalexander.ca/php-array-functions-instead-loops/

5a4758faa5ba6c1322bdfb0f6ebcf56c?s=128

Carl Alexander

September 10, 2016
Tweet

Transcript

  1. Use PHP arrays like a BOSS

  2. Carl Alexander

  3. @twigpress

  4. carlalexander.ca

  5. None
  6. You use arrays a LOT with WordPress

  7. You use loops a LOT with these arrays

  8. Loops are easy to overuse

  9. Makes your code complex

  10. Makes your code hard to read

  11. Makes your code hard to test

  12. PHP has a ton of array functions

  13. Relevant concepts

  14. Array data type

  15. Concept of array in computer science

  16. Used to store a collection of values

  17. Each value stored at a specific location

  18. Retrieved using an index or key

  19. Arrays are also used in mathematics

  20. with mathematical functions

  21. Functional programming

  22. Important with PHP array functions

  23. Revolves around functions

  24. Mathematical ones, not PHP ones

  25. What’s special about these functions?

  26. They always take an input

  27. They always return a value

  28. They also come in two categories

  29. Higher-order functions

  30. Accept functions as arguments

  31. Anonymous functions

  32. Serve higher-order functions

  33. Same as a string or array data type

  34. PHP callables

  35. Defines a function or method call

  36. Also known as a callback

  37. They have three different forms

  38. Array and string: norm with WordPress

  39. Anonymous function: new with PHP 5.3

  40. Same type of functions as earlier

  41. We can do functional programming!

  42. This is what we’ll use to replace loops

  43. You can use the other forms in your code

  44. Questions?

  45. Replacing loops

  46. When can you use array functions?

  47. Not a definitive list

  48. Just a starting point

  49. Validating array values

  50. Using a loop to remove array values

  51. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key') ); $posts_with_valid_meta_key = array();

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { $posts_with_valid_meta_key[] = $post; } }
  52. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key') ); $posts_with_valid_meta_key = array();

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { $posts_with_valid_meta_key[] = $post; } }
  53. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key') ); $posts_with_valid_meta_key = array();

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { $posts_with_valid_meta_key[] = $post; } }
  54. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key') ); $posts_with_valid_meta_key = array();

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { $posts_with_valid_meta_key[] = $post; } }
  55. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key') ); $posts_with_valid_meta_key = array();

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { $posts_with_valid_meta_key[] = $post; } }
  56. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key') ); $posts_with_valid_meta_key = array();

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { $posts_with_valid_meta_key[] = $post; } }
  57. array_filter function

  58. Filters the values inside an array

  59. You pass it an array and a callable

  60. Iterates through each array value

  61. Callable decides if value is kept or not

  62. Returns filtered array

  63. Replacing loop with array_filter

  64. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key') ); $posts_with_valid_meta_key = array_filter(

    $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } );
  65. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key’ )); $posts_with_valid_meta_key = array_filter(

    $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } );
  66. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key’ )); $posts_with_valid_meta_key = array_filter(

    $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } );
  67. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key’ )); $posts_with_valid_meta_key = array_filter(

    $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } );
  68. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key’ )); $posts_with_valid_meta_key = array_filter(

    $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } );
  69. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key’ )); $posts_with_valid_meta_key = array_filter(

    $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } );
  70. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key’ )); $posts_with_valid_meta_key = array_filter(

    $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } );
  71. Questions?

  72. Generating new arrays

  73. Using a loop to create a new array

  74. $recent_posts = get_posts(); $recent_post_permalinks = array(); foreach ($recent_posts as $post)

    { $recent_post_permalinks[] = get_post_permalink($post->ID); }
  75. $recent_posts = get_posts(); $recent_post_permalinks = array(); foreach ($recent_posts as $post)

    { $recent_post_permalinks[] = get_post_permalink($post->ID); }
  76. $recent_posts = get_posts(); $recent_post_permalinks = array(); foreach ($recent_posts as $post)

    { $recent_post_permalinks[] = get_post_permalink($post->ID); }
  77. $recent_posts = get_posts(); $recent_post_permalinks = array(); foreach ($recent_posts as $post)

    { $recent_post_permalinks[] = get_post_permalink($post->ID); }
  78. $recent_posts = get_posts(); $recent_post_permalinks = array(); foreach ($recent_posts as $post)

    { $recent_post_permalinks[] = get_post_permalink($post->ID); }
  79. array_map function

  80. Modifies an array using a callable

  81. Each array value passed to callable

  82. Callable applies changes to it

  83. Returns transformed array

  84. Replacing loop with array_map

  85. $recent_posts = get_posts(); $recent_post_permalinks = array_map( function(WP_Post $post) { return

    get_post_permalink($post->ID); }, $recent_posts );
  86. $recent_posts = get_posts(); $recent_post_permalinks = array_map( function(WP_Post $post) { return

    get_post_permalink($post->ID); }, $recent_posts );
  87. $recent_posts = get_posts(); $recent_post_permalinks = array_map( function(WP_Post $post) { return

    get_post_permalink($post->ID); }, $recent_posts );
  88. $recent_posts = get_posts(); $recent_post_permalinks = array_map( function(WP_Post $post) { return

    get_post_permalink($post->ID); }, $recent_posts );
  89. $recent_posts = get_posts(); $recent_post_permalinks = array_map( function(WP_Post $post) { return

    get_post_permalink($post->ID); }, $recent_posts );
  90. $recent_posts = get_posts(); $recent_post_permalinks = array_map( function(WP_Post $post) { return

    get_post_permalink($post->ID); }, $recent_posts );
  91. $recent_posts = get_posts(); $recent_post_permalinks = array_map( function(WP_Post $post) { return

    get_post_permalink($post->ID); }, $recent_posts );
  92. Transforming array of posts into links

  93. Powerful concept

  94. Questions?

  95. Searching an array

  96. Using a loop to get an array value

  97. $recent_posts = get_posts(); $longest_recent_post = null; foreach ($recent_posts as $post)

    { if (!$longest_recent_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_recent_post->post_content) ) { $longest_recent_post = $post; } }
  98. $recent_posts = get_posts(); $longest_recent_post = null; foreach ($recent_posts as $post)

    { if (!$longest_recent_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_recent_post->post_content) ) { $longest_recent_post = $post; } }
  99. $recent_posts = get_posts(); $longest_recent_post = null; foreach ($recent_posts as $post)

    { if (!$longest_recent_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_recent_post->post_content) ) { $longest_recent_post = $post; } }
  100. $recent_posts = get_posts(); $longest_recent_post = null; foreach ($recent_posts as $post)

    { if (!$longest_recent_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_recent_post->post_content) ) { $longest_recent_post = $post; } }
  101. $recent_posts = get_posts(); $longest_recent_post = null; foreach ($recent_posts as $post)

    { if (!$longest_recent_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_recent_post->post_content) ) { $longest_recent_post = $post; } }
  102. $recent_posts = get_posts(); $longest_recent_post = null; foreach ($recent_posts as $post)

    { if (!$longest_recent_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_recent_post->post_content) ) { $longest_recent_post = $post; } }
  103. $recent_posts = get_posts(); $longest_recent_post = null; foreach ($recent_posts as $post)

    { if (!$longest_recent_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_recent_post->post_content) ) { $longest_recent_post = $post; } }
  104. $recent_posts = get_posts(); $longest_recent_post = null; foreach ($recent_posts as $post)

    { if (!$longest_recent_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_recent_post->post_content) ) { $longest_recent_post = $post; } }
  105. array_reduce function

  106. Shrinks an array to a single value

  107. Compares array values using callable

  108. More complex than earlier callable

  109. Callable uses two parameters

  110. Current return value

  111. Current array value

  112. Compare the two and return one of them

  113. Replacing loop with array_reduce

  114. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  115. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  116. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  117. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  118. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  119. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  120. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  121. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  122. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  123. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  124. $recent_posts = get_posts(); $longest_recent_post = array_reduce( $recent_posts, function($longest_post, WP_Post $post)

    { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  125. Questions?

  126. Searching for a valid array value

  127. Combines two loops from earlier

  128. Validates array values

  129. But also finds the longest post

  130. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = null;

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { if (!$longest_post_with_valid_meta_key instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post_with_valid_meta_key->post_content) ) { $longest_post_with_valid_meta_key = $post; } } }
  131. Please don't do this loop in practice!

  132. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = null;

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { if (!$longest_post_with_valid_meta_key instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post_with_valid_meta_key->post_content) ) { $longest_post_with_valid_meta_key = $post; } } }
  133. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = null;

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { if (!$longest_post_with_valid_meta_key instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post_with_valid_meta_key->post_content) ) { $longest_post_with_valid_meta_key = $post; } } }
  134. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = null;

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { if (!$longest_post_with_valid_meta_key instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post_with_valid_meta_key->post_content) ) { $longest_post_with_valid_meta_key = $post; } } }
  135. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = null;

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { if (!$longest_post_with_valid_meta_key instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post_with_valid_meta_key->post_content) ) { $longest_post_with_valid_meta_key = $post; } } }
  136. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = null;

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { if (!$longest_post_with_valid_meta_key instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post_with_valid_meta_key->post_content) ) { $longest_post_with_valid_meta_key = $post; } } }
  137. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = null;

    foreach ($posts_with_meta_key as $post) { if (my_plugin_is_meta_key_valid($post->post_meta_key)) { if (!$longest_post_with_valid_meta_key instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post_with_valid_meta_key->post_content) ) { $longest_post_with_valid_meta_key = $post; } } }
  138. Combining array functions

  139. No new array function!

  140. New concept: function composition

  141. Used with functional programming

  142. None
  143. No need to create large functions

  144. Make functions as small as possible

  145. Compose multiple functions together

  146. Composing array functions

  147. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  148. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  149. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  150. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  151. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  152. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  153. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  154. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  155. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  156. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  157. $posts_with_meta_key = get_posts(array( 'meta_key' => ‘post_meta_key' )); $longest_post_with_valid_meta_key = array_reduce(

    array_filter( $posts_with_meta_key, function(WP_Post $post) { return my_plugin_is_meta_key_valid($post->post_meta_key); } ), function($longest_post, WP_Post $post) { if (!$longest_post instanceof WP_Post || str_word_count($post->post_content) > str_word_count($longest_post->post_content) ) { return $post; } return $longest_post; } );
  158. Questions?

  159. Why do this?

  160. Loops are familiar

  161. Using array functions isn’t

  162. You won’t always feel that way

  163. You’ll get better with time

  164. Reduces complexity

  165. Improves code quality

  166. Prevents technical debt

  167. Questions?

  168. Thank you!