A coder's home for Marc "Foddex" Oude Kotte, who used to be located in Enschede, The Netherlands, but now in Stockholm, Sweden!
foddex.net

PHP Lesson 2: Arrays

What is an array, and similarities with objects



Arrays are a wonderfully flexible concept in PHP. Some coders struggle with grasping all the concepts of them, so I decided to write a lesson about them. Although the most simple concept is quite obvious - an array is a value that contains other values - the more advanced concepts might not even be fully known to the more experienced PHP developer.

For starters, the above description of the basic concept is not even refined enough, as objects could be described in exactly the same fashion! So what's the difference between the two? Objects can contain functions and constructors/destructors, all of which arrays can not. But apart from the syntactical differences, that's about it: after all objects can be dynamically assigned new properties, arrays can be assigned new keys, objects can be
foreach
-ed, so can arrays, objects can be serialized, so can arrays! It is because of these similarities that objects and arrays can be cast to one another, without the loss of data. Obviously, since arrays are functionless, once you've cast an object to an array, you cannot cast it back to the exact same class type. But your data will remain. Take a look at the following code.

class MyClass { private $_internal = 1; public $set_me = 'Hello'; public function __toString() { return $this->set_me . ' ' . $this->_internal; } }; $myObject = new MyClass(); // $myObject now is an object of class MyClass with two members, _internal and set_me echo $myObject; // this works, because PHP can auto-convert objects to strings when a function __toString is present $arr = (array)$myObject; // $arr now is an array with two keys: _internal (value 1) and set_me (value 'Hello') $myObject = (object)$arr; // $myObject is now NOT an object of class MyClass, but of the built in class type stdClass // hence the following will fail at run time: echo $myObject



It's time to introduce the different types of arrays in PHP. There are two, (actually three), types of arrays in PHP: there are indexed arrays, associative arrays, and when you mix the two you get indexed-and-associative-arrays, but this basically functions as an associative array (explaining the two, no three ;-)).

Indexed arrays



What are indexed arrays? Indexed arrays are arrays that have consecutive key values (NOTE: the terms 'key' or 'index' are interchangeable here). When you create an array without settings keys, it becomes indexed:

$arr = array( 1, 2, 4, 8 );


The above array $arr has size 4, and four values, and thus also four keys (or indices). At key (index) 0, you have value 1. At key 1, you have value 2, at key 2, you have value 4, and finally at key 3 you have value 8. Quite simple and straightforward: keys are zero-based, in other words they start at key 0, and then go up.

To add an additional value at the end of an indexed array, you have two options:

$arr[] = 16; // the array is now of size 5, with value 16 at key 4 array_push( $arr, 32 ); // the array is now of size 6, with value 32 at key 5


Every time you add to an array, it becomes bigger in size. With the
[]
syntax, the array size always grows by one. With the array_push function you can add more than one value at the same time:

array_push( $arr, 64, 128, 256 ); // the array is now of size 9, as three values were added


Overwriting a value in an indexed array is very easy. You just figure out the key you wish to edit, and write:

$arr[2] = -4; // the array now still contains 9 values: 1, 2, -4, 8, 16, 32, 64, 128, 256


Removing a value from an indexed array is slightly more complicated, provided you wish to keep the array indexed (There is a very easy way, but this will make the array associative automatically so we'll get there later.) There are basically three possibilities:
  • you wish to remove the first element from the array
  • you wish to remove the last element from the array
  • you wish to remove one or more elements, or from a position in the middle of the array


Removing the first element is done using the
array_shift
function:

array_shift( $arr ); // we have popped value 1 at key 0, and $arr now contains 8 values: 2, -4, 8, 16, 32, 64, 128, 256


Removing the last element is done using the
array_pop
function:

array_shift( $arr ); // we have popped value 256 at key 7 (yes!), and $arr now contains 7 values: 2, -4, 8, 16, 32, 64, 128


Removing an arbitrary amount of consecutive elements from an arbitrary position in the array is slightly more complicated. If the amount of items we wish to continue is in $amount, and the position of the first of the elements is in $offset, this becomes:

$offset = 2; $amount = 2; array_splice( $arr, $offset, $amount ); // $arr now has only 5 values left: 2, -4, 32, 64, 128 // note that values 8 and 16 have been removed, as 8 was the value at key 2, and 16 followed it


Inserting an array at a different location than at the end (for this case we already covered), there are two options:
  • you want to add an element at the beginning of the array
  • you want to add an element at an arbitrary position


Adding an element at the beginning of an indexed array is done using the
array_unshift
function:

array_unshift( $arr, -1 ); // $arr is now of size 6 again: -1, 2, -4, 32, 64, 128


Again, adding at an arbitrary position is slightly more complex. Assuming that the element you wish the new value to reside at is in $offset, shifting all other elements "to the right", you write:

$offset = 1; array_splice( $arr, $offset, 0, array( 1.5 ) ); // $arr is now of size 7: -1, 1.5, 2, -4, 32, 64, 128


Now it's time to list the features of indexed arrays:
  • keys are automatically numbered
  • keys always start at 0, and go up by one
  • when you remove an element from an array, all values that follow it automatically get a key that is one lower, so if you have
    array( 1, 2, 4 )
    , and you remove value 2, value from shifts from index 2 to index 1 automatically
  • when you insert an element anywhere but at the end, all values at the "right side" of the array automatically get a key that is one higher, so if you have
    array( 1, 2, 4 )
    and you insert value 8 at position 1, you get
    array( 1, 8, 2, 4 )
    , shifting value 2 from key 1 to key 2, and shifting value 4 from key 2 to key 3.


Associative arrays



What are associative arrays? They are arrays with arbitrary keys: the following is a valid definition of an associative array:

$arr = array( 'foo' => 'bar', 16 => 'sixteen', false => 'not true', 1 => 'cool', 3.5 => 4.5, );


Keys can be specified as strings, integer values, boolean values and floating point values. Do notice though that all values that are not an integer and also not a string, are automatically converted to integer values. The above array thus is equal to the following array:

$arr = array( 'foo' => 'bar', 16 => 'sixteen', 0 => 'not true', 1 => 'cool', 3 => 4.5, );


Due to this automatic conversion, I urge you to never, ever use boolean and floating point values as keys: the automatic casting to integer values may provide you with unexpected results. Stick to strings and integer values, and you're fine.

Note that any string value is a valid key, so the following is a valid array:

$arr = array( '' => 'empty', '�' => '€', );


Adding a new value to an associative array is very easy: you simply set it's key and you're done. Check the following code:

$arr = array( 'foo' => 'bar', 'hello' => 'world', ); $arr['jack'] = 'sparrow'; // $arr is now an array of size 3, with three keys: 'foo', 'hello' and 'jack'


Removing a value from an associative array is very easy, use the
unset
function:

unset( $arr['foo'] ); // $arr is now again of size 2, the key 'foo', along with its value 'bar' was removed from $arr unset( $arr['foo2'] ); // $arr is still of size 2, and no warning is produced: unsetting something that wasn't set is not an error.


Associative arrays have no automatic indexing, and thus the concept of "inserting at a specific location" is not really possible. When you assign to a key in an array the beforehand wasn't set, the key gets added to the back of the array, as demonstrated with adding the key 'jack' in an earlier code fragment.

Checking if a specific key is already set or not, is also easy: use the
isset
function:

if (isset( $arr['jack'] )) echo 'There be pirates, harrrr';


However, this function has a major caveat. Check out the following code:

$arr['jane'] = NULL; if (!isset( $arr['jane'] )) echo 'Jack is a sad puppy.';


If I hadn't started talking about caveats, you probably would have expected Jack to be happy. However, using isset makes Jack a sad puppy, as the above code will output that
Jack is a sad puppy.
. This is because unset returns
false
for keys that have
NULL
as the value. Why they did this is beyond me, but it's true. Luckily, however, there is a cure:
array_key_exists
:

if (!array_key_exists( $arr, 'jane' )) echo 'Jack is a sad puppy.';


The above code will not print the same statement, as
array_key_exists
returns true when the key exists: no exceptions.

Automatic (unexpected) conversion from associative to indexed and the other way around



Beware of functions that always return indexed arrays, even when the input is associative. An example of such a function is the
sort
function. It is very useful, as it quicksorts your array by value. However, much to your suprise, you might find that when the input is associative, the result array is not! This is simply a fact (and reasonably well documented on php.net). You'll just have to learn which functions mangle your keys, and which do not.

For this very reason there are multiple sort functions:
  • sort
    : sorts by value, returns indexed, making associative arrays indexed
  • asort
    : sorts by value, keeps indices, making indexed arrays associative
  • rsort
    : sorts descending by value, returns indexed, making associative arrays indexed
  • arsort
    : sorts descending by value, keeps indices, making indexed arrays associative
  • ksort
    : sorts by keys, keeps indices, making indexed arrays associative
  • krsort
    : sorts descending by keys, keeps indices, making indexed arrays associatve
  • usort
    : sorts by value, uses user-specified comparison, returns indexed, making associatve arrays indexed
  • uasort
    : sorts by value, uses user-specified comparison, keeps indices, making indexed arrays associative
  • uksort
    : sorts by keys, uses user-specified comparison, keeps indices, making indexed arrays associative


There are more array functions in PHP that might change the type of your array. Some even have a property that allows you to define the behaviour in this respect (such as
array_slice
). Simply remember to always read the documentation properly when you start using a new array function.

Other array functions



There are many array functions in PHP, for example:
  • array_rand
    : picks random elements from input array
  • array_sum
    : calculate total of all values in an array
  • array_merge
    : combines multiple arrays into a single array
  • array_chunk
    : chop an array up in fixed-size pieces
  • array_keys
    : return all the keys in an array as an indexed array
  • array_walk
    : execute a user defined function on each element in an array
  • and so on, and so on... check out this page on php.net for a complete list




0 comment(s)

Name:
URL: (optional!)
Write your comment:
Answer this question to prove you're human:
What's the white stuff on top of mountains called?