Sei sulla pagina 1di 31

Arrays

So far we've looked at the basic variables types such as strings and integers,
as well as a variety of functions you can use to manipulate these data types.
Beyond the basic data types are arrays and objects, which take a little bit more
work in order for you to take advantage of them properly. More importantly,
arrays take a solid understanding of functions before you try to use them, which
is why they are separated here! As mentioned, objects are covered exclusively in
their own chapter - this chapter is dedicated to the topic of arrays.

In order to model our surroundings in a programming environment accurately, it


is important to recognise that some types of data naturally group together -
colours, for example, naturally clump together into one group. Rather than having
hundreds of separate variables - one for each colour - the reality is that it
makes more sense to have one variable that holds a list, or array of colours.

Topics covered in this chapter are:

Reading arrays

Manipulating arrays

Multidimensional arrays (arrays of arrays)

Saving arrays

Chapter contents

1. 5.1. First steps


2. 5.2. Associative arrays
3. 5.3. The two ways of iterating through arrays
4. 5.4. The array operator
5. 5.5. Returning arrays from functions
6. 5.6. Array-specific functions
1. 5.6.1. Chopping and changing arrays
2. 5.6.2. Stripping out duplicate values
3. 5.6.3. Filtering your array through a function
4. 5.6.4. Converting an array to individual variables
5. 5.6.5. Checking whether an element exists
6. 5.6.6. Using an array as a double-ended queue
7. 5.6.7. Swapping keys and values
8. 5.6.8. Sorting arrays
9. 5.6.9. Grabbing keys and values
10. 5.6.10. Randomising your array
11. 5.6.11. Creating an array of numbers
7. 5.7. Multidimensional arrays
8. 5.8. The array cursor
9. 5.9. Holes in arrays
10. 5.10. Arrays in strings
11. 5.11. Saving arrays
12. 5.12. Summary
13. 5.13. Exercises
14. 5.14. Further reading
15. 5.15. Next chapter

First steps
array array ( [mixed ...])
int count ( mixed var [, int mode])
bool print_r ( mixed expression [, bool return])
void var_dump ( mixed expression [, mixed expression [, mixed ...]])
mixed var_export ( mixed expression [, bool return])

PHP has built-in support for arrays of data, and there are two ways you can
create an array: using the array function, or using a special operator, [ ].

Before we look at how arrays work, there are two key things you need to understand
before you continue:

An array is a normal PHP variable like any others, but it works like a
container - you can put other variables inside it

Each variable inside an array is called an element . Each element has


a key and a value , which can be any other variable.

Now, consider this PHP code:


<?php
$myarray = array("Apples", "Oranges", "Pears");
$size = count($myarray);
print_r($myarray);
?>

On line one we see the most basic way to create an array, the array() function.
The array() function takes a minimum of one parameter (and a maximum of as many
as you want), and returns an array containing those variables. That's right
- $myarray now contains all three variables. Line two contains a new
function, count(), that returns the number of elements consisting in the array
passed to it as its only parameter - in the example we pass in my $myarray,
then store the number of elements (three) in $size.

Author's Note: The array() function actually allows you to have a trailing
comma after the last element, eg: array("Apples", "Oranges", "Pears",). This is
rarely used in hand-written code, but it can make generating code much easier.

Line three contains another new function, print_r(). This takes just one
parameter, but it outputs detailed information about a variable, such as it is
type, length, and contents. In the case of arrays, print_r() iteratively
outputs all elements inside the array - it is a good way to see how arrays
work.

Here is the output of print_r() from the above code:

Array
(
[0] => Apples
[1] => Oranges
[2] => Pears
)

As you can see, there are our three variables - Apples is at index 0 in the
array (signified by "[0]=>"), Oranges is at index 1 in the array, and Pears is
at index 2 in the array. Note that if you are running your scripts through a
web browser as opposed to from the command-line, you may find it help to put a
HTML <pre> tag before your print_r() calls, as this will format them for easier
reading.

Using the proper array terminology defined earlier, the 0, 1, and 2 indices are
the keys of each element, the "Apples", "Oranges", and "Pears" are the values of
each element, and the key and the value considered together are the elements
themselves.

Note that you can provide a second parameter to print_r(), which, if set to
true, will make print_r() pass its output back as its return value, and not
print anything out. To achieve the same output using this method, we would need
to alter the script to this:

<?php
$myarray = array("Apples", "Oranges", "Pears");
$size = count($myarray);
$output = print_r($myarray, true);
print $output;
?>

You can store whatever you like as values in an array, and you can mix values
also. For example: array("Foo", 1, 9.995, "bar",$somevar). You can also put
arrays inside arrays, but we will be getting on to that later.

There is a similar function to print_r(), which is var_dump(). It does largely


the same thing, but a) prints out sizes of variables, b) does not print out
non-public data in objects, and c) does not have the option to pass a second
parameter to return its output. For example, altering the first script to
use var_dump() rather than print_r() would give the following output:

array(3) {
[0]=>
string(6) "Apples"
[1]=>
string(7) "Oranges"
[2]=>
string(5) "Pears"
}

In there you can see var_dump() has told us that the array has three values,
and also prints out the lengths of each of the strings. For teaching
purposes, var_dump() is better as it shows the variable sizes, however you will
probably want to use print_r() in your own work.

Finally, there is the function var_export(), which is similar to


both var_dump() and print_r(). The key difference with var_export(), however,
is that it prints out variable information in a style that can be used as PHP
code. For example, if we had use var_export()instead of print_r() in the test
script, it would have output the following:

array (
0 => 'Apples',
1 => 'Oranges',
2 => 'Pears',
)

Note there is an extra comma after the last element, however this is ignored by
PHP and you can copy and paste that information directly into your own scripts,
like this:

<?php
$foo = array (
0 => 'Apples',
1 => 'Oranges',
2 => 'Pears',
);
?>

Short array syntax


If you're using PHP 5.4 or later (which is highly probable), you can take
advantage of short array syntax: rather than using array(), you can just use
square brackets. So, these two lines of code produce identical results:

<?php
$myarray = array("Apples", "Oranges", "Pears");
$myarray = ["Apples", "Oranges", "Pears"];
?>

Associative arrays
As well as choosing individual values, you can also choose your keys - in the
fruits code above we just specify values, but we could have specified keys along
with them, like this:

<?php
$myarray = array("a"=>"Apples", "b"=>"Oranges", "c"=>"Pears");
var_dump($myarray);
?>

This time, var_dump() will output the following:

array(3) {
["a"]=>
string(6) "Apples"
["b"]=>
string(7) "Oranges"
["c"]=>
string(5) "Pears"
}

As expected, our 0, 1, and 2 element keys have been replaced with a, b, and c,
but we could equally have used "Foo", "Bar", and "Baz", or even variables or
other arrays to act as the keys. Specifying your own keys produces what is
called an associative array - you associate a specific key with a specific
value. Most associative arrays use strings as keys, but do not be afraid to try
more advanced things out.

The one exception here is floating-point numbers: these make very poor array
indexes. The problem lies in the fact that PHP converts them to integers before
they are used, which essentially rounds them down. So, the following code will
create an array with just one element in:

<?php
$array[1.5] = "foo";
$array[1.6] = "bar";
?>

The first line will read 1.5 as the key, round it down to 1, then store "foo" at
index 1. The second line will read 1.6 as the key, also round it down to 1, then
store "bar" at index 1, overwriting "foo". If you really want to use floating-
point numbers as your keys, pass them in as strings, like this:

<?php
$array["1.5"] = "foo";
$array["1.6"] = "foo";
var_dump($array);
?>

That should output the following:

array(2) {
["1.5"]=>
string(3) "foo"
["1.6"]=>
string(3) "foo"
}
This time the floating-point numbers have not been rounded down or converted at
all, because PHP is using them as strings. The same solution applies to reading
values out from an associative array with floating-point keys - you must always
specify the key as a string.

The two ways of iterating through arrays


void list ( mixed ...)
array each ( array input)

If you do not specify a key, as in the first example, PHP will just assign
incrementing numbers starting with 0. However, these numbers cannot be guaranteed
to exist within the array in any given order, or even to exist at all - they are
just key values themselves. For example, an array may have keys 0, 1, 2, 5, 3,
6, 7. That is, it can have its keys out of order or entirely missing. As a result,
code like this should generally be avoided:

<?php
for ($i = 0; $i < count($array); ++$i) {
print $array[$i];
}
?>

However, there is a quick and easy way to accomplish the same thing: a foreach
loop, which itself has two versions. The easiest way to use foreach looks like
this:

foreach($array as $val) {
print $val;
}

Here the array $array is looped through and its values are extracted into $val.
In this situation, the array keys are ignored completely, which usually makes
most sense when they have been auto-generated (i.e. 0, 1, 2, 3, etc).

The second way to use foreach does allow you to extract keys, and looks like
this:

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


print "$key = $val\n";
}

Another commonly used way to loop over arrays is using


the list() and each() functions, like this:

<?php
while (list($var, $val) = each($array)) {
print "$var is $val\n";
}
?>

List() is a function that does the opposite of array() - it takes an array, and
converts it into individual variables. Each() takes an array as its parameter,
and returns the current key and value in that array before advancing the array
cursor. "Array cursor" is the technical term for the element of an array that
is currently being read. All arrays have a cursor, and you can freely move it
around - it is used in the while loop above, where we need to iterate through
an array. To start with, each() will return the first element, then the second
element, then the third, and so on, until it finds there are no elements left,
in which case it will return false and end the loop.

The meaning of that first line is "get the current element in the array, and
assign its key to $var and its value to $val, then advance the array cursor.
There is a lot more detail on array cursors later.

Generally speaking, using foreach loops is the most optimised way to loop
through an array, and is also the easiest to read. In practice, however, you
will find foreach loops and list()/each() loops in about equal proportions,
despite the latter option being slower. The key difference between the two is
that foreach automatically starts at the front of the array,
whereas list()/each() does not.

The array operator


There is another popular way to create and manage arrays, and it uses brackets
[ ] to mean "add to array", earning it the name "the array operator". Using
this functionality, you can both create arrays and add to existing arrays, so
this is generally more popular - you will generally only find
the array() function being used when several values are being put inside the
array, as it will fit on one line. Here are some examples of the array operator
in action:

<?php
$array[] = "Foo";
$array[] = "Bar";
$array[] = "Baz";
var_dump($array);
?>
That should work in precisely the same as using the array() function, except it
is much more flexible - we can add to the array whenever we want to. When it
comes to working with non-default indices, we can just place our key inside the
brackets, like this:

<?php
$array["a"] = "Foo";
$array["b"] = "Bar";
$array["c"] = "Baz";
var_dump($array);
?>

Returning arrays from functions


In PHP you can return one and only one value from your user functions, but you
are able to make that single value an array, thereby allowing you to return many
values.

This following code shows how easy it is:

<?php
function dofoo() {
$array["a"] = "Foo";
$array["b"] = "Bar";
$array["c"] = "Baz";
return $array;
}

$foo = dofoo();
?>

Without returning an array, the only other way to pass data back to the calling
script is by accepting parameters by reference and changing them inside the
function. Passing arrays by reference like this is generally preferred as it is
less of a hack, and also frees up your return value for some a true/false to
check whether the function was successful.

Array-specific functions
Although arrays are great by themselves, their real usefulness only comes out
when you use special array functions to manipulate your data - this was why we
had to cover functions before arrays.

There are quite a few array functions all doing a variety of things, and you need
not learn them all - your best bet is to give them all a try so that you at least
know how they work, then get back to working on normal code. You'll soon learn
what works for you best!

Chopping and changing arrays


array array_diff ( array array1, array array2 [, array ...])
array array_intersect ( array array1, array array2 [, array ...])
array array_merge ( array array1, array array2 [, array ...])

There are three key functions that handle the comparison of two arrays to
create a new array, and they work in much the same way - they take a minimum of
two arrays as parameters (we will call them $arr1 and $arr2), and return an
array for a result.

The difference is that array_diff() returns a new array containing all the
values of $arr1 that do not exist in $arr2, array_intersect()returns a new array
containing all the values of $arr1 that do exist in $arr2,
and array_merge() just combines the two arrays. These three functions work well
as a team, and allow you to construct combined arrays out of individual arrays.

Here is an example with these three functions in action:

<?php
$toppings1 = array("Pepperoni", "Cheese", "Anchovies", "Tomatoes");
$toppings2 = array("Ham", "Cheese", "Peppers");
$inttoppings = array_intersect($toppings1, $toppings2);
$difftoppings = array_diff($toppings1, $toppings2);
$bothtoppings = array_merge($toppings1, $toppings2);
var_dump($inttoppings);
var_dump($difftoppings);
var_dump($bothtoppings);
?>

As you can see, there are two arrays of pizza toppings, and they both share
cheese as a value. Here is what that script outputs:

array(1) { [1]=> string(6) "Cheese" }


array(3) { [0]=> string(9) "Pepperoni" [2]=> string(9) "Anchovies" [3]=> string(8)
"Tomatoes" }
array(7) { [0]=> string(9) "Pepperoni" [1]=> string(6) "Cheese" [2]=> string(9)
"Anchovies" [3]=> string(8) "Tomatoes" [4]=> string(3) "Ham" [5]=> string(6) "Cheese"
[6]=> string(7) "Peppers" }

Array_intersect(), if you recall, returns an array listing all values in array


parameter one that are also in array parameter two, so this call in our example
will put just one element, cheese, into $inttoppings. The call
to array_diff() will place into $difftoppings all the values from $toppings1 that
aren't in $toppings2, namely pepperoni, anchovies, and tomatoes.

Finally we have a call to array_merge(), which results in seven elements being


placed into $bothtoppings: pepperoni, cheese, anchovies, tomatoes, peppers, ham,
and cheese. As you can see, "cheese" is in there twice, so what you really need
now is a way to strip out duplicate values.

Author's Note: The + operator in PHP is overloaded so that you can use it to merge arrays, eg
$array3 = $array1 + $array2, but will ignore any key clashes, and so is quite confusing to use
unless you have unique keys.

Stripping out duplicate values


array array_unique ( array input)

Consider if the $toppings2 array had been declared like this:

$toppings2 = array("Peppers", "Ham", "Cheese", "Peppers");

In this situation, there'd be two Peppers elements in there, in which case we


would want to strip out the duplicate Peppers before running the merges and
intersects. This is done by using array_unique(), which takes an array as its
parameter and returns the same array with its duplicate values removed, like
this:

$toppings2 = array_unique($toppings2);

Try the example code again, this time removing the duplicate Cheese values
from $bothtoppings.

Filtering your array through a function


array array_filter ( array input [, callback function])

The final array function in this group is array_filter(), which is a very


powerful function that allows you to filter elements through a function you
specify. If the function returns true, the item makes it into the array that is
returned, otherwise it is not. Consider this script:

<?php
function endswithy($value) {
return (substr($value, -1) == 'y');
}
$people = array("Johnny", "Timmy", "Bobby", "Sam", "Tammy", "Danny", "Joe");
$withy = array_filter($people, "endswithy");
var_dump($withy);
?>

In this script we have an array of people, most of which have a name ending
with "y". However, several do not, and for one reason or another we want to
have a list of people whose names ends in "y", so array_filter() is used. The
function endswithy() will return true if the last letter of each array value
ends with a y, otherwise false. By passing that as the second parameter
to array_filter(), it will be called once for every array element, passing in
the value of the element as the parameter to endswithy(), where it is checked
for a "y" at the end.

Converting an array to individual variables


int extract ( array source [, int extract_type [, string prefix]])

Extract() is a very popular function that converts elements in an array into


variables in their own right. Extract takes a minimum of one parameter, an
array, and returns the number of elements extracted. This is best explained
using code, so here goes:

<?php
$Wales = 'Swansea';
$capitalcities['England'] = 'London';
$capitalcities['Scotland'] = 'Edinburgh';
$capitalcities['Wales'] = 'Cardiff';
extract($capitalcities);
print $Wales;
?>

After calling extract, the "England", "Scotland", and "Wales" keys become
variables in their own right ($England, $Scotland, and$Wales), with their values
set to "London", "Edinburgh", and "Cardiff" respectively. By
default, extract() will overwrite any existing variables, meaning that $Wales's
original value of "Swansea" will be overwritten with "Cardiff".

This behaviour can be altered using the second parameter, and averted using the
third parameter. Parameter two takes a special constant value that allows you to
decide how values will be treated if there is an existing variable, and parameter
three allows you to prefix each extract variable with a special string. Here are
the possible values of the second parameter:

EXTR_OVERWRITE On collision, overwrite the existing variable

EXTR_SKIP On collision, do not overwrite the existing variable

On collision, prefix the variable name with the prefix specified by


EXTR_PREFIX_SAME
parameter three

Prefix all variables with the prefix specified by parameter three,


EXTR_PREFIX_ALL
whether or not there is a collision

Only use the prefix specified by parameter three when variables


EXTR_PREFIX_INVALID
names would otherwise be illegal (e.g. "$9")

EXTR_IF_EXISTS Only set variables if they already exist

Only create prefixed variables if non-prefixed version already


EXTR_PREFIX_IF_EXISTS
exists

EXTR_REFS Extract variables as references

The last option, EXTR_REFS, can either be used on its own or in combination with
others using the bitwise OR operator |.

Here are some examples based upon the $capitalcities array from the previous
example:

<?php
$Wales = 'Swansea';
extract($capitalcities, EXTR_SKIP);
print $Wales;
print $Scotland;
extract($capitalcities, EXTR_PREFIX_SAME, "country");
print $Wales;
print $country_England;
extract($capitalcities, EXTR_PREFIX_ALL, "country");
?>

On line one we pre-set $Wales to be a value so that you can clearly see how the
second parameter works. On line two we callextract() using two parameters, with
EXTR_SKIP as parameter two so that our $Wales will not be overwritten. However,
as you will be able to see if you run the script, $England and $Scotland were
set.

On line five we use EXTR_PREFIX_SAME, which will extract variables and use the
third parameter as a prefix if it finds any collisions. As we
set $Wales ourselves and our previous call
to extract() created $England and $Scotland, all our variables will need to be
prefixed. As you can see on line six, $Wales is still set to "Swansea", and on
line seven we have our prefixed variable$country_England. Note that PHP places
an underscore _ after your prefix to make the variable easy to read.

Finally we call extract() with EXTR_PREFIX_ALL, which will unconditionally


create variables with prefixes, overwriting $country_England, etc. Note that
EXTR_OVERWRITE is rarely if ever used, because it is the same as
using extract() without second or third parameters.

Checking whether an element exists


bool in_array ( mixed needle, array haystack [, bool strict])

The in_array() function does precisely what you might think - if you pass it a
value and an array it will return true if the value is in the array, otherwise
false. This following example show it in action:

<?php
$needle = "Sam";
$haystack = array("Johnny", "Timmy", "Bobby", "Sam", "Tammy", "Danny", "Joe");

if (in_array($needle, $haystack)) {
print "$needle is in the array!\n";
} else {
print "$needle is not in the array\n";
}
?>

In_array() has an optional boolean third parameter (set to false by default)


that defines whether you want to use strict checking or not. If parameter three
is set to true, PHP will only return true if the value is in the array and it
is of the same type - that is, if they are identical in the same way as the ===
operator (three equals signs). This is not used very often, but it is important
that you are at least aware of its existence.
Using an array as a double-ended queue
mixed array_shift ( array array)
int array_unshift ( array array, mixed var [, mixed ...])
int array_push ( array array, mixed var [, mix ...])
mixed array_pop ( array array)

If you have ever used the C++ Standard Template Library, you will know how useful
the deque (double-ended queue, pronounced "deck") type is. If you have never used
STL, or C++ for that matter, a deque allows you to store elements in an array-
like structure, then work with either the very first element or the very last
element. This might not sound useful, after all we've already seen that PHP lets
you read from any variable in an array at any time, so why would it be good to
work with only the first and last elements?

Well, using what you know already, how would you insert a variable at the very
first position in your array? Or how would you read the first element and remove
it from the array? It would be tricky, for sure - and that's where the deque
principle comes in.

Array_shift() takes an array as its only parameter, and returns the value from
the front of the array while also removing it from the array. Consider this
script:

<?php
$names = array("Johnny", "Timmy", "Bobby", "Sam", "Tammy", "Danny", "Joe");
$firstname = array_shift($names);
var_dump($names);
?>

If you run that script, you will see that $firstname is set to "Johnny", and the
array $names now only has the values Timmy, Bobby, Sam, Tammy, Danny, and Joe -
Johnny gets removed. To remove an element from the end of an array (as opposed
to the start), there is also array_pop(), which works in the same way
as array_shift(). Both these functions also have
opposites, array_unshift() andarray_push(), which place an element into an
array at the start or at the end respectively. This next script should clear up
any confusion:

<?php
$names = array("Johnny", "Timmy", "Bobby", "Sam", "Tammy", "Danny", "Joe");
$firstname = array_shift($names);
// First element of $names is now Timmy; last is Joe
array_push($names, $firstname);
// first is Timmy; last is now Johnny

$firstname = array_pop($names);
// first is Timmy; last is Joe again

array_unshift($names, $firstname);
// first is Johnny, last is Joe

var_dump($names);
?>

Extracting the first and last variable from an array is a very popular task, so
try to keep these functions in the back of your mind.

Swapping keys and values


array array_flip ( array input)

The array_flip() function takes just one parameter, an array, and exchanges all
the keys in that array with their matching values, returning the new, flipped
array. You can see how it works in this script:

<?php
$capitalcities['England'] = 'London';
$capitalcities['Scotland'] = 'Edinburgh';
$capitalcities['Wales'] = 'Cardiff';
$flippedcities = array_flip($capitalcities);
var_dump($flippedcities);
?>

When executed, that will output the following:

array(3) {
["London"]=>
string(7) "England"
["Edinburgh"]=>
string(8) "Scotland"
["Cardiff"]=>
string(5) "Wales"
}

As you can see, "London", "Edinburgh", and "Cardiff" are the keys in the array
now, with "England", "Scotland", and "Wales" as the values - simple.

Sorting arrays
bool asort ( array input [, int sort_flags])
bool ksort ( array input [, int sort_flags])
bool arsort ( array input [, int sort_flags])
bool krsort ( array input [, int sort_flags])

Although there is a basic array sorting function, called simply sort(), it


makes no attempt to preserve the values of your keys and so usually does more
harm than good. In its place are asort() and ksort(), which are very
similar- asort() sorts an array by its values, whereas ksort() sorts an array
by its keys. The difference can be seen clearly in this next script:

<?php
$capitalcities['England'] = 'London';
$capitalcities['Wales'] = 'Cardiff';
$capitalcities['Scotland'] = 'Edinburgh';
ksort($capitalcities);
var_dump($capitalcities);
asort($capitalcities);
var_dump($capitalcities);
?>

Note that both ksort() and asort() work by reference, directly changing the
value you pass in - the return value is either true or false, depending on
whether the sorting was successful. The first var_dump will output the array
sorted by key, therefore it will be England, Scotland, then Wales. The second
var_dump will output the array sorted by values, therefore it will be Cardiff,
Edinburgh, London.

These two functions also have companions, arsort() and krsort(), which reverse
sort the array and reverse sort the array by key respectively.

There is one particular situation that may catch you out when sorting arrays,
and that's when you have not assigned your own keys and are accessing the data
by index. Consider this next script:

<?php
$capitalcities[] = 'London';
$capitalcities[] = 'Cardiff';
$capitalcities[] = 'Edinburgh';
var_dump($capitalcities);
asort($capitalcities);
var_dump($capitalcities);
?>

This time the keys are being assigned by PHP, so 0 will be London, 1 will be
Cardiff, and 2 will be Edinburgh. When sorted, however, the keys 0, 1, and 2
stay with the values, which means the second var_dump() call will output this:
array(3) {
[1]=>
string(7) "Cardiff"
[2]=>
string(9) "Edinburgh"
[0]=>
string(6) "London"
}

Now, if you were to try to access that using a for loop and use $capitalcities[$i],
you would find the data in the original order. This is because even though
"London" is last in the array, it still uses the key 0 and will therefore be
accessed first.

There are two ways to solve this problem. First, you can use a foreach loop to
access the array in its natural order; this is the preferred method of
accessing arrays anyway, and you should use it if you can. Alternatively, you
can use the array_values() function to effectively reset the array keys.

By default, the sort functions sort so that 2 comes before 10. While this might
be obvious, consider how a string sort would compare 2 and 10 - it would work
character by character, which means it would compare 2 against 1 and therefore
put 10 before 2. Sometimes this is the desired behaviour, and so you can pass a
second parameter to the sort functions to specify how you want the values sorted,
like this:

<?php
$array["1"] = "someval1";
$array["2"] = "someval2";
$array["3"] = "someval3";
$array["10"] = "someval4";
$array["100"] = "someval5";
$array["20"] = "someval6";
$array["200"] = "someval7";
$array["30"] = "someval8";
$array["300"] = "someval9";
var_dump($array);
ksort($array, SORT_STRING);
var_dump($array);
?>

If you want to force a strictly numeric sort, you can pass SORT_NUMERIC as the
second parameter.

Grabbing keys and values


array array_keys ( array input [, mixed search_value [, bool strict]])
array array_values ( array input)

Array_keys() and array_values() are very closely related functions: the former
returns an array of all the keys in an array, and the latter returns an array
of all the values in an array. For example, consider you had an array with user
IDs as keys and usernames as values, you could use array_keys() to generate an
array where the values were the keys. Try this following example out:

<?php
$users[923] = 'TelRev';
$users[100] = 'Skellington';
$users[1202] = 'CapnBlack';
$userids = array_keys($users);
var_dump($userids);
?>

After execution, $userids will be an array of user IDs, as you will see when
the var_dump() function outputs $userids to the screen.

There are two other parameters that can be passed to array_keys(), which are,
in order, a value to match, and whether to perform strict matching. These two
are there to allow you to filter your array keys - if you specify "tennis", for
example, then the only keys that array_keys() will return are the ones that
have the value "tennis". By default this is done by checking each key's value
with the == operator (is equal to), however if you specify 1 as the third
parameter the check will be done with === (is identical to).

<?php
$users[923] = 'TelRev';
$users[100] = 'Skellington';
$users[1202] = 'CapnBlack';
$userids = array_keys($users, "TelRev");
var_dump($userids);
?>

This time the $userids array will only contain one element, with a value of 923,
as the script filters by value "TelRev".

Moving on, the usefulness of the array_values() function may at first not be
apparent - after all, why would you want the values of a new array to be set to
the values of an old array? This all boils down to how numerical arrays are
indexed. If you use the array operator [] to assign variables to an array, PHP
will use 0, 1, 2, etc as the keys. If you then sort the array using a function
such asasort(), which keeps the keys intact, the array's keys will be out of
order because asort() sorts by value, not by key.
However, using the array_values() function makes PHP create a new array where
the indexes are recreated and the values are copied from the old array,
essentially making it renumber the array elements.

This next script demonstrates array_values() in action:

<?php
$array[] = "Hello";
$array[] = "World";
$array[] = "Foo";
$array[] = "Bar";
$array[] = "Baz";
var_dump($array);
asort($array);

var_dump($array);
var_dump(array_values($array));
?>

The first var_dump() prints the array out in its original ordering. The second
prints it out ordered by the values - the keys will be jumbled up, however. The
final call to var_dump() uses array_values() to create a new array, and you
should see that the jumbled up keys have been re-ordered. Here's how it looked
on my screen:

array(5) { [0]=> string(5) "Hello" [1]=> string(5) "World" [2]=> string(3) "Foo" [3]=>
string(3) "Bar" [4]=> string(3) "Baz" }
array(5) { [3]=> string(3) "Bar" [4]=> string(3) "Baz" [2]=> string(3) "Foo" [0]=>
string(5) "Hello" [1]=> string(5) "World" }
array(5) { [0]=> string(3) "Bar" [1]=> string(3) "Baz" [2]=> string(3) "Foo" [3]=>
string(5) "Hello" [4]=> string(5) "World" }

You should use array_values() when you want to re-order an array's indexes
either because they are jumbled up or because they have holes in, but you can
also use it to convert an associative array with strings as the indexes to a
plain numerical array.

Randomising your array


void shuffle ( array input)
mixed array_rand ( array input [, int num_req])

Very often you will find yourself not wanting to read from your array in a
strictly ordered fashion, and in this situation you need to make use of
either shuffle() or array_rand().
Shuffle() takes the entire array and randomises the position of the elements in
there. In earlier versions of PHP the shuffle()algorithm was not very good,
leading the "randomisation" to be quite weak, however that problem is now
fixed.

Take a look at this example:

<?php
$natural_born_killers = array("lions", "tigers", "bears", "kittens");
shuffle($natural_born_killers);
var_dump($natural_born_killers);
?>

One major drawback to using shuffle() is that it mangles your array keys. This
is unavoidable sadly, and you need to live with it when you use shuffle(). Note
that shuffle uses its parameter by reference - it returns true, but shuffles up
the parameter you pass to it.

If you want to pick out just one random value from an array, you can
use array_rand() - it takes an array to read from, then returns one random key
from inside there. The advantage to array_rand() is that it leaves the original
array intact - you can use the random key returned to grab the related value
from the array, but other than that the original array is left untouched.

Array_rand() has an optional second parameter that allows you to specify the
number of elements you would like returned. These are each chosen randomly from
the array, and are not necessarily returned in any particular order.

Before I show you an example, you need to be aware of the following attributes
of array_rand():

It returns the keys in your array. If these aren't specified, the default
integer indexes are used. To get the value out of the array, just look up
the value at the key.

If you ask for one random element, or do not specify parameter two, you
will get a standard variable back.

If you ask for more than one random element, you will receive an array of
variables back.

If you ask for more random elements than there are in the array you will
get an error
Array_rand() will not return duplicate elements if you request more than
one random element

If you want to read most or all of the elements from your array in a
random order, use a mass-randomiser like shuffle() - it is faster.

With that in mind, here's an example of array_rand() in action:

<?php
$natural_born_killers = array("lions", "tigers", "bears", "kittens");
var_dump(array_rand($natural_born_killers, 2));
?>

Creating an array of numbers


array range ( int low, int high [, int step])

Consider this problem:

A school has to give all its students an end-of-year examination

The test consists of the same 40 questions for each student

To minimise cheating, the school wants those 40 questions to be randomly


ordered

How would you code that in PHP? The obvious answer is code like this:

<?php
$questions = array(1, 2, 3, 4, 5, ..., 38, 39, 40);
$questions = shuffle($questions);
?>

The slightly smarter programmer might save themselves some typing with more
intelligent code like this:

<?php
for ($i = 1; $i <= 40; ++$i) {
$questions[] = $i;
}

shuffle($questions);
?>

However, that's still not the most efficient way of doing it. Instead, PHP has
a special range() function that allows you to create an array of numbers
between a low value (parameter one) and a high value (parameter two). So the
best way to write the script is this:

<?php
$questions = range(1,40);
$questions = shuffle($questions);
?>

As you can see, range() returns the array between 1 and 40 (inclusive), ordered
sequentially. This is then passed through shuffle() to get the random question
numbers - perfect!

There are a three other tricks to range() that you should be aware of. Firstly,
it has a third parameter that allows you specify a step amount in the range.
For example:

$questions = range(1, 10, 2); // gives 1, 3, 5, 7, 9


$questions = range(1, 10, 3) // gives 1, 4, 7, 10
$questions = range(10, 100, 10);

Although the step parameter should always be positive, the second trick is that
if your low parameter (parameter one) is higher than your high parameter
(parameter two), you get an array counting down, like this:

$questions = range(100, 0, 10);

Finally, you can also use range() to create arrays of characters, like this:

$questions = range("a", "z", 1); // gives a, b, c, d, ..., x, y, z


$questions = range("z", "a", 2);

For creating these simple kinds of arrays, there is nothing better than
using range() - it is very fast, very easy to read, and the step parameter can
save you extra work.

Multidimensional arrays
One key advantage to arrays is that they can contain other arrays. Currently our
arrays just hold standard, non-array variables, which makes them one-dimensional.
However, by switching to a two-dimensional array - each element holds an array
as its value, and each element in the child array holds a non-array variable -
we can store much more information. Consider this script:

<?php
$capitalcities['England'] = array("Capital"=>"London", "Population"=>40000000,
"NationalSport"=>"Cricket");
$capitalcities['Wales'] = array("Capital"=>"Cardiff", "Population"=>5000000,
"NationalSport"=>"Rugby");
$capitalcities['Scotland'] = array("Capital"=>"Edinburgh", "Population"=>8000000,
"NationalSport"=>"Football");
var_dump($capitalcities);
?>
This time we're creating our $capitalcities array elements as before, but we're
using an array for each value. Each child array has three elements: Capital,
Population, and NationalSport. At the end there is a var_dump() for the parent
array, which should really show you how helpful var_dump() is. Here is the
output:

array(3) {
["England"]=>
array(3) {
["Capital"]=>
string(6) "London"
["Population"]=>
int(40000000)
["NationalSport"]=>
string(7) "Cricket"
}
["Wales"]=>
array(3) {
["Capital"]=>
string(7) "Cardiff"
["Population"]=>
int(5000000)
["NationalSport"]=>
string(5) "Rugby"
}
["Scotland"]=>
array(3) {
["Capital"]=>
string(9) "Edinburgh"
["Population"]=>
int(8000000)
["NationalSport"]=>
string(8) "Football"
}
}
As you can see, not only does var_dump() recurse into child arrays to output
their contents to, but it indents all the output according to the array level.

Think of multidimensional arrays as allowing you to store arrays of arrays,


because that is their most common purpose. Of course, they can also store arrays
of arrays of arrays and so on, but it is all the same.

Author's Note: The count() function has a helpful second parameter that, when
set to 1, makes count() perform a recursive count. The difference is that if
you pass in a multidimensional array, count() will count all the elements in
the first array, then go into the first array element and count all the
elements in there, and go into any elements in there, etc, etc. For example,
the$capitalcities array above has three elements in, so if you do not use the
second parameter to count() you will get 3 back. However, if you pass in 1 for
the second parameter, you will get 12: three for the first-level elements
("England", "Wales", "Scotland"), and three each for the variables inside those
elements ("Capital", "Population", "NationalSport").

The array cursor


mixed reset ( array array)
mixed end ( array array)
mixed next ( array array)
mixed prev ( array array)

If you're just learning PHP, I would recommend skipping this section entirely - using
foreach loops is easier, faster and cleaner.

Earlier on I mentioned that each array has a "cursor", which you can think of as
an arrow pointing to the next array element in line to be operated on. It is the
array cursor that allows code like while (list($var, $val) = each($array)) to
work - each moves forward the array cursor of its parameter each time it is
called, until it eventually finds itself at the end of the array, and so returns
false, ending the loop.

Now, consider this next piece of code:

<?php
$array = array("Foo", "Bar", "Baz");
print "First time...\n";
while (list($var, $val) = each($array)) {
print "$var is $val\n";
}

print "Second time...\n";

while (list($var, $val) = each($array)) {


print "$var is $val\n";
}
?>

The chances are, that piece of code will not do what you expect, because it
will not print out the contents of $array the second time around. The reason for
the strange result is because each() does not move the array cursor back to the
first element when you first call it - it just picks up from where the cursor
was. As a result, after our first while loop, the cursor is right at the end of
the array, so that when it comes to the second while loop, the each() function
returns false immediately because it is pointing to the last item in the array.

It is in situations like this where you need to set the position of the array
cursor forcibly, and there are four functions to help you
out: reset(), end(), next(), and prev(). They all take just one parameter, the
array to work with, and return a value from the array.

Reset() rewinds its array parameter's cursor to the first element, then returns
the value of that element, whereas end() set the array cursor to the last
element, and returns that value. Next() and prev() both move the cursor pointer
forward or backward one element respectively, returning the value of the
element now pointed to. If any of the four functions cannot return a value (if
there are no elements in the array, or if the array cursor has gone past the
last element), they will return false. As such, you can use them all in loops
if you want.

For example, to iterate through an array in reverse, use this code:

<?php
$array = array("Foo", "Bar", "Baz", "Wom", "Bat");
print end($array);

while($val = prev($array)) {
print $val;
}
?>
Note that we print the output of end(), because it sets the array cursor to
point at "Bat", and prev() will shift the array cursor back one to "Wom",
meaning that "Bat" would otherwise not be printed out.

Holes in arrays
Consider this script:

<?php
$array["a"] = "Foo";
$array["b"] = "";
$array["c"] = "Baz";
$array["d"] = "Wom";
print end($array);

while($val = prev($array)) {
print $val;
}
?>

As you can see, it is fairly similar to the previous example - it should


iterate through an array in reverse, printing out values as it goes. However,
there is a problem - the value at key "b" is empty, and it just so happens that
both prev() and next() consider an empty value to be the sign that the end of
the array has been reached, and so will return false, prematurely ending the
while loop.

The way around this is the same way around the problems inherent to using for
loops with arrays, and that is to use each() to properly iterate through your
arrays, as each() will cope fine with empty variables and unknown keys.
Therefore, the script should have been written as this:

<?php
$array["a"] = "Foo";
$array["b"] = "";
$array["c"] = "Baz";
$array["d"] = "Wom";

while (list($var, $val) = each($array)) {


print "$var is $val\n";
}
?>

Arrays in strings
Very often you will want to use an array directly inside a string using code
something like this:
<?php
$myarray['foo'] = "bar";
print "This is from an array: $myarray['foo']\n";
?>

Sadly, that won't work - PHP will consider $myarray to be a variable by itself
and consider the ['foo'] part as a normal string that it should tack on to the
end of the value of $myarray. The way around this is to use braces { and }
around the variable, which is how you tell PHP that you are passing it an array
to read from. This next snippet is the right way to do things:

<?php
$myarray['foo'] = "bar";
print "This is from an array: {$myarray['foo']}\n";
?>

Saving arrays
string serialize ( mixed value)
mixed unserialize ( string input)
string urlencode ( string text)
string urldecode ( string encoded)

As arrays are complex data types, you cannot see their contents directly. If
you try printing out the value of an array, you will see PHP just outputs
"Array", which means that passing the value of an array through a link requires
a lot of work. Luckily, PHP comes to the rescue with four functions that do all
the hard work for you: serialize(), unserialize(), urlencode(),
and urldecode().

Serialize() converts an array, given as its only parameter, into a normal


string that you can save in a file, pass in a URL, etc.Unserialize() is the
opposite of serialize() - it takes a serialize()d string and converts it back
to an array.

Urlencode() and urldecode() also work in tandem, and convert the string that is
sent to them as their only parameter into a version that is safe to be passed
across the web. All characters that aren't letters and numbers get converted
into web-safe codes that can be converted back into the original text
using urldecode().
Passing arrays across pages is best done using urlencode() and urldecode(),
however you should consider using them both on any data you pass across the
web, just to make sure there are no incompatible characters in there.

Take a look at this next script:

<?php
$array["a"] = "Foo";
$array["b"] = "Bar";
$array["c"] = "Baz";
$array["d"] = "Wom";

$str = serialize($array);
$strenc = urlencode($str);
print $str . "\n";
print $strenc . "\n";
?>

That will output two lines (the second of which I've forced to wrap so that it
appears properly!):

a:4:{s:1:"a";s:3:"Foo";s:1:"b";s:3:"Bar";s:1:"c";s:3:"Baz";s:1:"d";s:3:"Wom";}
a%3A4%3A%7Bs%3A1%3A%22a%22%3Bs%3A3%3A%22Foo%22%3Bs%3A1%3A%22b%22%3Bs%3A0%3A%22%22%3Bs%
3A1%3A%22c%22%3Bs%3A3%3A%22Baz%22%3Bs%3A1%3A%22d%22%3Bs%3A3%3A%22Wom%22%3B%7D

The first is the direct, serialize()d output of our array, and you can see how
it works by looking through the text inside there. The second line contains
the urlencode()d serialize()d array, and is very hard to read. Despite being
hard to read, the latter is wholly web safe, and there much better to use.

Once your array is in text form, you can do with it as you please. To return
back to the original array, it needs to be urldecode()d, then unserialize()d,
like this:

<?php
$arr = unserialize(urldecode($strenc));
var_dump($arr);
?>

Author's Note: If you want to transfer binary data over the web, you should
use rawurlencode() and rawurldecode() as opposed
to urlencode() and urldecode(), as the raw versions are binary-safe.

Summary
Arrays are a great way of storing variables that natural collect together,
such as colours, days of the week, members of a team, or items in a shopping
basket.

Multidimensional arrays allow you to store array within arrays to store


very complex data in one convenient location.

Use the extract() function to pull all items out of an array and into the
global scope, as it is faster and also easier to work with.

Cycle through your arrays using foreach() or similar means, as holes in


your array can cause more simple loops to access empty values.

The var_dump() function is a great way to see what is inside your


variables, whether they are arrays or not - make liberal use of it when
debugging to save headaches!

Exercises
1. What is the difference between an associative array and a multidimensional
array?

2. How many times should srand() be called?

o a) Once ever

o b) Once per script

o c) Once for every call to shuffle(), before the call

o d) Once for every call to shuffle(), after the call

3. To safely pass an array over the web, what is the correct sequence of
function calls:

o a) urlencode(), serialize(), unserialize(), urldecode()

o b) urldecode(), unserialize(), serialize(), urlencode()

o c) serialize(), unserialize(), urlencode(), urldecode()

o d) serialize(), urlencode(), urldecode(), unserialize()

4. When passing a negative "step" parameter to the range() function, the


initial value must always be larger than the end value: true or false?
5. To randomise the order of an array, which function(s) can you use:

o a) shuffle()

o b) mt_shuffle()

o c) Both of the above

o d) Neither a) nor b)

6. Which of the following statements are true about arrays that have a hole
(e.g. it has keys 0, 1, 2, and 4):

o a) You can use foreach to loop through the array and ignore the hole

o b) You can use the array_values() function to re-order the keys

o c) You can use the arsort() function to re-order the keys

o d) All of the above

Further reading
The shuffle() and array_rand() functions are fairly good at providing
pseudo-random information, but the whole topic of randomisation is much
more massive and complex than you may realise. If you are interested in
learning more about randomisation, I suggest you learn from the best:
Donald Knuth's "Art of Computer Programming, Volume 2: Seminumerical
Algorithms" should do the trick, if your maths is up to scratch.

Potrebbero piacerti anche