Zend PHP 5 Certification Study Guide (2014)

Arrays

Arrays are the undisputed kings of advanced data structures in PHP. PHP arrays are extremely flexible—they allow numeric auto-incremented keys, alphanumeric keys, or a mix of both, and are capable of storing practically any value, including other arrays. With over seventy functions for manipulating them, arrays can do almost anything you can imagine—and then some.

Array Basics

All arrays are ordered collections of items, called elements. Each element has a value, and is identified by a key that is unique to the array it belongs to. As we mentioned in the previous paragraph, keys can be either integer numbers or strings of arbitrary length.

Arrays are created in multiple ways. The first, and most common, is by explicitly calling the array() construct, which can be passed a series of values and, optionally, keys:

$a = array(10, 20, 30);

$a = array('a' => 10, 'b' => 20, 'cee' => 30);

$a = array(5 => 1, 3 => 2, 1 => 3,);

$a = array();

The first line of code above creates an array by only specifying the values of its three elements. Since every element of an array must also have a key, PHP automatically assigns a numeric key to each element, starting from zero. In the second example, the array keys are specified in the call toarray()—in this case, three alphabetical keys (note that the length of the keys is arbitrary). In the third example, keys are assigned “out of order,” so that the first element of the array has, in fact, the key 5. Note here the use of a “dangling comma” after the last element, which is perfectly legal from a syntactical perspective and has no effect on the final array. Finally, in the fourth example we create an empty array.

A second method of creating arrays is by means of the array operator ([]):

$x[] = 10;

$x['aa'] = 11;

echo $x[0]; // Outputs 10

As you can see, this operator provides a much higher degree of control than array(): in the first example, we add a new value to the array stored in the $x variable. Because we don’t specify the key, PHP will automatically choose the next highest numeric key available for us. In the second example, on the other hand, we specify the key 'aa' ourselves. Note that, in either case, we don’t explicitly initialize $x to be an array, which means that PHP will automatically convert it to one for us if it isn’t; if $x is empty, it will simply be initialized to an empty array.

Short Array Syntax

With PHP 5.4, a new short array syntax was introduced: a simple shorthand, which replaces array() with []. It is identical to the standard syntax in functionality—merely syntactic sugar.

$a = [10, 20, 30];

$a = ['a' => 10, 'b' => 20, 'cee' => 30];

$a = [5 => 1, 3 => 2, 1 => 3,];

$a = [];

Printing Arrays

In the PHP Basics chapter, we illustrated how the echo statement can be used to output the value of an expression, including that of a single variable. While echo is extremely useful, it exhibits some limitations that curb its helpfulness in certain situations. For example, while debugging a script, one often needs to see not just the value of an expression, but also its type. Another problem with echo lies in the fact that it is unable to deal with composite data types like arrays and objects.

To obviate this problem, PHP provides two functions that can be used to output a variable’s value recursively: print_r() and var_dump(). They differ in a few key points:

·        While both functions recursively print out the contents of a composite value, only var_dump() outputs the data types of each value.

·        Only var_dump() is capable of outputting the value of more than one variable at the same time.

·        Only print_r can return its output as a string, as opposed to writing it to the script’s standard output.

Whether echo, var_dump() or print_r should be used in any one given scenario is, clearly, dependent on what you are trying to achieve. Generally speaking, echo will cover most of your bases, while var_dump() and print_r() offer a more specialized set of functionality that works well as an aid in debugging.

Enumerative vs. Associative

Arrays can be roughly divided into two categories: enumerative and associative. Enumerative arrays are indexed using only numerical indexes, while associative arrays (sometimes referred to as dictionaries) allow the association of an arbitrary key to every element. In PHP, this distinction is significantly blurred, as you can create an enumerative array and then add associative elements to it (while still maintaining elements of an enumeration). What’s more, arrays behave more like ordered maps and can actually be used to simulate a number of different structures, including queues and stacks.

PHP provides a great amount of flexibility in how numeric keys can be assigned to arrays: numeric keys can be any integer number (both negative and positive), and they don’t need to be sequential, so a large gap can exist between the indices of two consecutive values without the need to create intermediate values to cover every possible key in between. Moreover, the keys of an array do not determine the order of its elements—as we saw earlier when we created an enumerative array with keys that were out of natural order.

When an element is added to an array without specifying a key, PHP automatically assigns a numeric one that is equal to the greatest numeric key already in existence in the array, plus one:

$a = array(2 => 5);

$a[] = 'a';  // This will have a key of 3

Note that this is true even if the array contains a mix of numerical and string keys:

$a = array('4' => 5, 'a' => 'b');

$a[] = 44; // This will have a key of 5

Note that array keys are case-sensitive, but type insensitive. Thus, the key 'A' is different from the key 'a', but the keys '1' and 1 are the same. However, the conversion is only applied if a string key contains the traditional decimal representation of a number; thus, for example, the key'01' is not the same as the key 1. Attempting to use a float as a key will convert it to an integer key, so that '12.5' becomes '12'. Using boolean values of true and false as keys will cast them to 1 and 0 respectively, while using NULL will actually cause them to be stored under the empty string "". Finally, arrays and objects cannot be used as keys.

Multi-dimensional Arrays

Since every element of an array can contain any type of data, the creation of multi-dimensional arrays is very simple: to create multi-dimensional arrays, we simply assign an array as the value for an array element. With PHP, we can do this for one or more elements within any array, allowing for infinite levels of nesting.

Listing 4.1: Declaring nested arrays

$array = array();

$array[] = array(

        'foo',

        'bar'

    );

$array[] = array(

        'baz',

        'bat'

    );

echo $array[0][1] . $array[1][0];

Our output from this example is barbaz. As you can see, to access multi-dimensional array elements, we simply “stack” the array operators, giving the key for the specific element we wish to access in each level.

Unravelling Arrays

It is sometimes simpler to work with the values of an array by assigning them to individual variables. While this can be accomplished by extracting individual elements and assigning each of them to a different variable, PHP provides a quick shortcut—the list() construct:

Listing 4.2: Using list to assign array values

$sql = "SELECT user_first, user_last, last_login

         FROM users";

$result = $pdo->query($sql);

while (list($first, $last, $last_login)

            = $result->fetch($result)) {

    echo "$last, $first - Last Login: $last_login";

}

By using the list construct, and passing in three variables, we are causing the first three elements of the array to be assigned to those variables in order, allowing us to then simply use those elements within our while loop.

Array Operations

As we mentioned in the PHP Basics chapter, a number of operators behave differently if their operands are arrays. For example, the addition operator + can be used to create the union of its two operands:

$a = array(1, 2, 3);

$b = array('a' => 1, 'b' => 2, 'c' => 3);

var_dump($a + $b);

This outputs the following:

array(6) {

  [0]=>

  int(1)

  [1]=>

  int(2)

  [2]=>

  int(3)

  ["a"]=>

  int(1)

  ["b"]=>

  int(2)

  ["c"]=>

  int(3)

}

Note how the the resulting array includes all of the elements of the two original arrays, even though they have the same values; this is a result of the fact that the keys are different. If the two arrays had common keys (either string or numeric), they would only appear once in the end result:

$a = array(1, 2, 3);

$b = array('a' => 1, 'c', 'd');

var_dump($a + $b);

This results in:

array(4) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [“a”]=> int(1) } ~~

Comparing Arrays

Array-to-array comparison is a relatively rare occurrence, but it can be performed using another set of operators. As with other types of arrays, the equivalence and identity operators can be used for this purpose:

Listing 4.3: Comparing arrays

$a = array(1, 2, 3);

$b = array(1 => 2, 2 => 3, 0 => 1);

$c = array('a' => 1, 'b' => 2, 'c' => 3);

var_dump($a == $b); // True

var_dump($a === $b); // False

var_dump($a == $c); // False

var_dump($a === $c); // False

As you can see, the equivalence operator == returns true if both arrays have the same number of elements with the same values and keys, regardless of their order. The identity operator ===, on the other hand, returns true only if the array contains the same key/value pairs in the same order. Similarly, the inequality and non-identity operators can determine whether two arrays are different:

$a = array(1, 2, 3);

$b = array(1 => 2, 2 => 3, 0 => 1);

var_dump($a != $b); // False

var_dump($a !== $b); // True

Once again, the inequality operator only ensures that both arrays contain the same elements with the same keys, whereas the non-identity operator also verifies their position.

Counting, Searching and Deleting Elements

The size of an array can be retrieved by calling the count() function:

Listing 4.4: Counting array elements

$a = array(1, 2, 4);

$b = array();

$c = 10;

echo count($a); // Outputs 3

echo count($b); // Outputs 0

echo count($c); // Outputs 1

As you can see, count() cannot be used to determine whether a variable contains an array, since running it on a scalar value will return one. The right way to tell whether a variable contains an array is to use is_array() instead.

A similar problem exists with determining whether an element with the given key exists. This is often done by calling isset():

$a = array('a' => 1, 'b' => 2);

var_dump(isset($a['a'])); // True

var_dump(isset($a['c'])); // False

However, isset() has the major drawback of considering an element whose value is NULL—which is perfectly valid—as inexistent:

$a = array('a' => NULL, 'b' => 2);

var_dump(isset($a['a'])); // False

The correct way to determine whether an array element exists is to use array_key_exists() instead:

$a = array('a' => NULL, 'b' => 2);

var_dump(array_key_exists('a', $a)); // True

Obviously, neither these functions will allow you to determine whether an element with a given value exists in an array—this is, instead, performed by the in_array() function:

$a = array('a' => NULL, 'b' => 2);

var_dump(in_array(2, $a)); // True

Finally, an element can be deleted from an array by unsetting it:

$a = array('a' => NULL, 'b' => 2);

unset($a['b']);

var_dump(in_array(2, $a)); // False

Flipping and Reversing

There are two functions that have rather confusing names and that are sometimes misused: array_flip() and array_reverse(). The first of these two functions swaps the value of each element of an array with its key:

$a = array('a', 'b', 'c');

var_dump(array_flip($a));

This outputs:

array(3) {

  ["a"]=>

  int(0)

  ["b"]=>

  int(1)

  ["c"]=>

  int(2)

}

On the other hand, array_reverse() actually reverses the order of the array’s elements, so that the last one appears first:

$a = array('x' => 'a', 10 => 'b', 'c');

var_dump(array_reverse($a));

Note how key association is only lost for those elements whose keys are numeric:

array(3) {

  [0]=>

  string(1) "c"

  [1]=>

  string(1) "b"

  ["x"]=>

  string(1) "a"

}

Array Iteration

Iteration is probably one of the most common operations you will perform with arrays—besides creating them, of course. Unlike what happens in other languages, where arrays are all enumerative and contiguous, PHP’s arrays require a set of functionality that matches their flexibility, because “normal” looping structures cannot cope with the fact that array keys do not need to be continuous—or, for that matter, enumerative. Consider, for example, this simple array:

$a = array('a' => 10, 10 => 20, 'c' => 30);

It is clear that none of the looping structures we have examined so far will allow you to cycle through the elements of the array—unless, that is, you happen to know exactly what its keys are, which is, at best, a severe limitation on your ability to manipulate a generic array.

The Array Pointer

Each array has a pointer that indicates the “current” element of an array in an iteration. The pointer is used by a number of different constructs, but can only be manipulated through a set of functions. The pointer does not affect your ability to access individual elements of an array, nor is it affected by most “normal” array operations. The pointer is, in fact, a handy way of maintaining the iterative state of an array without needing an external variable to do the job for us.

The direct way of manipulating the pointer of an array is to use a series of functions designed specifically for this purpose. Upon starting an iteration over an array, the first step is usually to reset the pointer to its initial position using the reset() function; after that, we can move forward or backward by one position by using prev() and next() respectively. At any given point, we can access the value of the current element using current() and its key using key(). Here’s an example:

Listing 4.5: Using the array pointer

$array = array('foo' => 'bar', 'baz', 'bat' => 2);

function displayArray(&$array) {

    reset($array);

    while (key($array) !== null) {

        echo key($array) . ": " . current($array) . PHP_EOL;

        next($array);

    }

}

Here, we have created a function that will display all the values in an array. First, we call reset() to rewind the internal array pointer. Next, using a while loop, we display the current key and value, using the key() and current() functions. Finally, we advance the array pointer, using next(). The loop continues until we no longer have a valid key.

It’s important to understand that there is no correlation between the array pointer and the keys of the array’s elements. Moving ahead or back by one position simply gives you access to the elements of the array based on their position inside it, not on their keys. Also note that when passing an array in as a function argument, unless you pass-by-reference using the & operator as in this example, a copy is passed and the internal pointer is always set to the first position, making a call to reset() unnecessary. For large arrays, passing by reference reduces memory usage.

Since you can iterate back-and-forth within an array by using its pointer, you could—in theory—start your iteration from the last element (using the end() function to reset the pointer to the bottom of the array) and then make your way back to the beginning:

Listing 4.6: Moving pointer backwards

$array = array(1, 2, 3);

end($array);

while (key($array) !== null) {

    echo key($array) . ": " . current($array) . PHP_EOL;

    prev($array);

}

Note how, in the last two examples, we check whether the iteration should continue by comparing the result of a call to key() on the array to NULL. This only works because we are using a non-identity operator—using the inequality operator could cause some significant issues if one of the array’s elements has a key that evaluates to integer zero.

An Easier Way to Iterate

As you can see, using this set of functions requires quite a bit of work; to be fair, there are some situations in which they offer the only reasonable way of iterating through an array, particularly if you need to skip back and forth between its elements.

If, however, all you need to do is iterate through the entire array from start to finish, PHP provides a handy shortcut in the form of the foreach() construct:

$array = array('foo', 'bar', 'baz');

foreach ($array as $key => $value) {

    echo "$key: $value" . PHP_EOL;

}

The process that takes place here is rather simple, but has a few important gotchas. First of all, foreach operates on a copy of the array itself; this means that changes made to the array inside the loop are not reflected in the iteration. For example, removing an item from the array after the loop has begun will not cause foreach to skip over that element. The array pointer is also always reset to the beginning of the array prior to the beginning of the loop, so that you cannot manipulate it in such a way as to cause foreach to start from a position other than the first element of the array.

PHP 5 also introduces the possibility of modifying the contents of the array directly by assigning the value of each element to the iterated variable by reference rather than by value:

Listing 4.7: Modifying array elements by reference

$a = array(1, 2, 3);

foreach ($a as $k => &$v) {

    $v += 1;

}

var_dump($a); // $a will contain (2, 3, 4)

While this technique can be useful, it is so fraught with peril as to be something best left alone. Consider this code, for example:

Listing 4.8: Beware when modifying array elements by reference

$a = array('zero', 'one', 'two');

foreach ($a as &$v) {

}

foreach ($a as $v) {

}

print_r($a);

It would be natural to think that, since this little script does nothing to the array, it will not affect its contents… but that’s not the case! In fact, the script provides the following output:

Array

(

    [0] => zero

    [1] => one

    [2] => one

)

As you can see, the array has been changed, and the last key now contains the value 'one'. How is that possible? Unfortunately, there is a perfectly logical explanation—and this is not a bug. Here’s what is going on. The first foreach loop does not make any change to the array, just as we would expect. However, it does cause $v to be assigned a reference to each of $a’s elements, so that, by the time the first loop is over, $v is, in fact, a reference to $a[2].

As soon as the second loop starts, $v is now assigned the value of each element. However, $v is already a reference to $a[2]; therefore, any value assigned to it will be copied automatically into the last element of the array! Thus, during the first iteration, $a[2] will become zero, then one, and thenone again, being effectively copied on to itself. To solve this problem, you should always unset the variables you use in your by-reference foreach loops—or, better yet, avoid using the former altogether.

List Support in Foreach

With PHP 5.5, the list construct can also be used with foreach loops.

Listing 4.9: Using list in foreach

$pdo->setAttribute(

    PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC

);

$sql = "SELECT user_first, user_last, last_login

        FROM users";

$result = $pdo->query($sql);

foreach ($result as list($first, $last, $last_login)) {

   echo "$last, $first - Last Login: $last_login" . PHP_EOL;

}

The Database Programming chapter contains more information on working with database results.

Passive Iteration

The array_walk() function and its recursive cousin array_walk_recursive() are used to perform an iteration of an array in which a user-defined function is called. Here’s an example:

Listing 4.10: Iterating with array_walk

function setCase(&$value, &$key) {

    $value = strtoupper($value);

}

$type = array('internal', 'custom');

$output_formats[] = array('rss', 'html', 'xml');

$output_formats[] = array('csv', 'json');

$map = array_combine($type, $output_formats);

array_walk_recursive($map, 'setCase');

var_dump($map);

Using the custom setCase() function, a simple wrapper for strtoupper(), we are able to convert each of the array’s values to uppercase. One thing to note about array_walk_recursive() is that it will not call the user-defined function on anything but scalar values; because of this, the first set of keys,internal and custom, are never passed in.

The resulting array looks like this:

array(2) {

  ["internal"]=>

  &array(3) {

    [0]=>

    string(3) "RSS"

    [1]=>

    string(4) "HTML"

    [2]=>

    string(3) "XML"

  }

  ["custom"]=>

  &array(2) {

    [0]=>

    string(3) "CSV"

    [1]=>

    string(4) "JSON"

  }

}

Sorting Arrays

There are a total of eleven functions in the PHP core whose only goal is to provide various methods of sorting the contents of an array. The simplest of these is sort(), which sorts an array from lowest to highest based on its values:

$array = array('a' => 'foo', 'b' => 'bar', 'c' => 'baz');

sort($array);

var_dump($array);

As you can see, sort() modifies the actual array it is provided, since the latter is passed by reference. This means that you cannot call this function by passing anything other than a single array variable to it.

array(3) {

  [0]=>

  string(3) "bar"

  [1]=>

  string(3) "baz"

  [2]=>

  string(3) "foo"

}

Thus, sort() effectively destroys all the keys in the array and renumbers its elements starting from zero. If you wish to maintain key association, you can use asort() instead:

$array = array('a' => 'foo', 'b' => 'bar', 'c' => 'baz');

asort($array);

var_dump($array);

This code will output something similar to the following:

array(3) {

  ["b"]=>

  string(3) "bar"

  ["c"]=>

  string(3) "baz"

  ["a"]=>

  string(3) "foo"

}

Both sort() and asort() accept a second, optional parameter that allows you to specify how the sort operation takes place:

Sort Flags

Description

SORT_REGULAR

Compare items as they appear in the array, without performing any kind of conversion. This is the default behaviour.

SORT_NUMERIC

Convert each element to a numeric value for sorting purposes.

SORT_STRING

Compare all elements as strings.

SORT_LOCALE_STRING

Compare all elements as strings, based on the current locale.

SORT_NATURAL

Compare all elements as strings, using “natural ordering” like the natsort function.

SORT_FLAG_CASE

When combined with SORT_STRING OR SORT_NATURAL, compare all elements as case-insensitive strings.

Both sort() and asort() sort values in ascending order. To sort them in descending order, you can use rsort() and arsort().

The sorting operation performed by sort() and asort() either takes into consideration the numeric value of each element, or performs a byte-by-byte comparison of string values. This can result in an “unnatural” sorting order. For example, the string value '10t' will be considered “lower” than'2t' because it starts with the character 1, which has a lower value than 2. If this sorting algorithm doesn’t work well for your needs, you can try using natsort() instead:

$array = array('10t', '2t', '3t');

natsort($array);

var_dump($array);

This will output:

array(3) {

  [1]=>

  string(2) "2t"

  [2]=>

  string(2) "3t"

  [0]=>

  string(3) "10t"

}

The natsort() function will, unlike sort(), maintain all the key-value associations in the array. A case-insensitive version of the function, natcasesort() also exists, but there is no reverse-sorting equivalent of rsort().

Other Sorting Options

In addition to the sorting functions we have seen thus far, PHP allows you to sort by key (rather than by value) using the ksort() and krsort() functions, which work analogously to sort() and rsort():

$a = array('a' => 30, 'b' => 10, 'c' => 22);

ksort($a);

var_dump($a);

This will output:

array(3) {

  ["a"]=>

  int(30)

  ["b"]=>

  int(10)

  ["c"]=>

  int(22)

}

Finally, you can also sort an array by providing a user-defined function:

Listing 4.11: User-defined comparison

function myCmp($left, $right) {

    // Sort according to the length of the value.

    // If the length is the same, sort normally

    $diff = strlen($left) - strlen($right);

    if (!$diff) {

        return strcmp($left, $right);

    }

    return $diff;

}

$a = array(

    'three',

    '2two',

    'one',

    'two'

);

usort($a, 'myCmp');

var_dump($a);

This short script allows us to sort an array by a rather complicated set of rules: first, we sort according to the length of each element’s string representation. Elements whose values have the same length are further sorted using regular string comparison rules; our user-defined function must return a value of zero if the two values are to be considered equal, a value less than zero if the left-hand value is lower than the right-hand one, and a positive number otherwise. Thus, our script produces this output:

array(4) {

  [0]=>

  string(3) "one"

  [1]=>

  string(3) "two"

  [2]=>

  string(4) "2two"

  [3]=>

  string(5) "three"

}

As you can see, usort() has lost all key-value associations and renumbered our array; this can be avoided by using uasort() instead. You can even sort by key (instead of by value) by using uksort(). Note that there is no reverse-sorting version of any of these functions, because reverse sorting can performed by simply inverting the comparison rules of the user-defined function:

Listing 4.12: Reversing sort order

function myCmp($left, $right) {

    // Reverse-sort according to the length of the value.

    // If the length is the same, sort normally

    $diff = strlen($right) - strlen($left);

    if (!$diff) {

        return strcmp($right, $left);

    }

    return $diff;

}

This will result in the following (reversed) output:

array(4) {

  [0]=>

  string(5) "three"

  [1]=>

  string(4) "2two"

  [2]=>

  string(3) "two"

  [3]=>

  string(3) "one"

}

The Anti-Sort

There are circumstances in which, instead of ordering an array, you will want to scramble its contents so that the keys are randomized; this can be done by using the shuffle() function:

$cards = array(1, 2, 3, 4);

shuffle($cards);

var_dump($cards);

Since the shuffle() function randomizes the order of the elements of the array, the result of this script will be different every time, but here’s an example:

array(9) {

  [0]=>

  int(4)

  [1]=>

  int(1)

  [2]=>

  int(2)

  [3]=>

  int(3)

}

As you can see, the key-value association is lost; however, this problem is easily overcome by using another array function, array_keys(), which returns an array whose values are the keys of the array passed to it. For example:

Listing 4.13: Get an array’s keys

$cards = array('a' => 10, 'b' => 12, 'c' => 13);

$keys = array_keys($cards);

shuffle($keys);

foreach ($keys as $v) {

    echo $v . " - " . $cards[$v] . PHP_EOL;

}

As you can see, this simple script first extracts the keys from the $cards array, and then shuffles $keys, so that the data can be extracted from the original array in random order without losing its key-value association.

If you need to extract individual elements from the array at random, you can use array_rand(), which returns one or more random keys from an array:

$cards = array('a' => 10, 'b' => 12, 'c' => 13);

$keys = array_rand($cards, 2);

var_dump($keys);

var_dump($cards);

If you run the script above, its output will look something like this:

array(2) {

  [0]=>

  string(1) "a"

  [1]=>

  string(1) "b"

}

array(3) {

  ["a"]=>

  int(10)

  ["b"]=>

  int(12)

  ["c"]=>

  int(13)

}

As you can see, extracting the keys from the array does not remove the corresponding element from it. You will have to do that manually if you don’t want to extract the same key more than once.

Arrays as Stacks, Queues and Sets

Arrays are often used as stack (Last In, First Out, or LIFO) and queue (First In, First Out, or FIFO) structures. PHP simplifies this approach by providing a set of functions that can be used to push and pop (for stacks) and shift and unshift (for queues) elements from an array.

We’ll take a look at stacks first:

$stack = array();

array_push($stack, 'bar', 'baz');

var_dump($stack);

$last_in = array_pop($stack);

var_dump($last_in, $stack);

In this example, we first create an array, and then add two elements to it using array_push(). Next, using array_pop(), we extract the last element added to the array, resulting in this output:

array(2) {

  [0]=>

  string(3) "bar"

  [1]=>

  string(3) "baz"

}

string(3) "baz"

array(1) {

  [0]=>

  string(3) "bar"

}

As you have probably noticed, when only one value is being pushed, array_push() is equivalent to adding an element to an array using the syntax $a[] = $value. In fact, the latter is much faster, since no function call takes place and, therefore, this should be the preferred approach unless you need to add more than one value.

If you intend to use an array as a queue (FIFO), you can add elements at the beginning using array_unshift() and remove them again using array_shift():

$stack = array('qux', 'bar', 'baz');

$first_element = array_shift($stack);

var_dump($stack);

array_unshift($stack, 'foo');

var_dump($stack);

In this example, we use array_shift() to push the first element out of the array. Next, using array_unshift(), we do the reverse and add a value to the beginning of the array. This example results in:

array(2) {

  [0]=>

  string(3) "bar"

  [1]=>

  string(3) "baz"

}

array(3) {

  [0]=>

  string(3) "foo"

  [1]=>

  string(3) "bar"

  [2]=>

  string(3) "baz"

}

Set Functionality

Some PHP functions are designed to perform set operations on arrays. For example, array_diff() is used to compute the difference between two (or more) arrays:

$a = array(1, 2, 3);

$b = array(1, 3, 4);

var_dump(array_diff($a, $b));

The call to array_diff() in the code above will cause all the values of $a that do not also appear in $b to be returned, while everything else is discarded:

array(1) {

  [1]=>

  int(2)

}

Note that the keys are ignored—if you want the difference to be computed based on key-value pairs, you will have to use array_diff_assoc() instead, whereas if you want it to be computed on keys alone, array_diff_key() will do the trick. Both of these functions have user-defined callback versions, called array_diff_uassoc() and array_diff_ukey(), respectively.

Conversely to array_diff(), array_intersect() will compute the intersection between two (or more) arrays:

$a = array(1, 2, 3);

$b = array(1, 3, 4);

var_dump(array_intersect($a, $b));

In this case, only the values that are included in both arrays are returned in the result:

array(2) {

  [0]=>

  int(1)

  [2]=>

  int(3)

}

As with array_diff(), array_intersect only keeps in consideration the value of each element; PHP provides array_intersect_key() and array_intersect_assoc() versions for key- and key/value-based intersection, together with their callback variants array_intersect_ukey() and array_intersect_uassoc().

Dereferencing Arrays

PHP 5.4 introduced the ability to access array members directly when an array is returned by a function:

arrayResult()["foo"];

Additionally, in PHP 5.5, the ability to do the same with array literals was added:

["foo", "bar"][1]; // bar

This is known as array dereferencing, and the key may be any valid expression; for example, you can use rand() to get a random result:

$color = ["blue", "pink", "purple", "red"][rand(0, 3)];

Summary

Arrays are probably the single most powerful data management tool available to PHP developers. Therefore, learning to use them properly is essential for a good developer. A full list of array related functions can be found in Appendix A.

Naturally, you don’t have to become a “living manual” in order to use arrays and pass the exam, but a good understanding of where to mark the line between using built-in functionality and writing your own array-manipulation routines is very important: because arrays are often used to handle large amounts of data, PHP’s built-in functions provide a significant performance improvement over anything written on the user’s side and, therefore, can have a dramatic impact on your application’s efficiency and scalability.