PHP

Arrays

Introduction#

An array is a data structure that stores an arbitrary number of values in a single value. An array in PHP is actually an ordered map, where map is a type that associates values to keys.

Syntax#

  • $array = array(‘Value1’, ‘Value2’, ‘Value3’); // Keys default to 0, 1, 2, …,
  • $array = array(‘Value1’, ‘Value2’, ); // Optional trailing comma
  • $array = array(‘key1’ => ‘Value1’, ‘key2’ => ‘Value2’, ); // Explicit keys
  • $array = array(‘key1’ => ‘Value1’, ‘Value2’, ); // Array ( [‘key1’] => Value1 1 => ‘Value2’)
  • $array = [‘key1’ => ‘Value1’, ‘key2’ => ‘Value2’, ]; // PHP 5.4+ shorthand
  • $array[] = ‘ValueX’; // Append ‘ValueX’ to the end of the array
  • $array[‘keyX’] = ‘ValueX’; // Assign ‘valueX’ to key ‘keyX’
  • $array += [‘keyX’ => ‘valueX’, ‘keyY’ => ‘valueY’]; // Adding/Overwrite elements on an existing array

Parameters#

Parameter Detail
Key The key is the unique identifier and index of an array. It may be a string or an integer. Therefore, valid keys would be 'foo', '5', 10, 'a2b', ...
Value For each key there is a corresponding value (null otherwise and a notice is emitted upon access). The value has no restrictions on the input type.
## Remarks#
# See also

Initializing an Array

An array can be initialized empty:

// An empty array
$foo = array();

// Shorthand notation available since PHP 5.4
$foo = [];

An array can be initialized and preset with values:

// Creates a simple array with three strings
$fruit = array('apples', 'pears', 'oranges');

// Shorthand notation available since PHP 5.4
$fruit = ['apples', 'pears', 'oranges'];

An array can also be initialized with custom indexes (also called an associative array):

// A simple associative array
$fruit = array(
   'first'  => 'apples',
   'second' => 'pears', 
   'third'  => 'oranges'
);

// Key and value can also be set as follows
$fruit['first'] = 'apples';

// Shorthand notation available since PHP 5.4
$fruit = [
    'first'  => 'apples', 
    'second' => 'pears', 
    'third'  => 'oranges'
];

If the variable hasn’t been used before, PHP will create it automatically. While convenient, this might make the code harder to read:

$foo[] = 1;     // Array( [0] => 1 )
$bar[][] = 2;   // Array( [0] => Array( [0] => 2 ) )

The index will usually continue where you left off. PHP will try to use numeric strings as integers:

$foo = [2 => 'apple', 'melon'];  // Array( [2] => apple, [3] => melon )
$foo = ['2' => 'apple', 'melon']; // same as above
$foo = [2 => 'apple', 'this is index 3 temporarily', '3' => 'melon']; // same as above! The last entry will overwrite the second!

To initialize an array with fixed size you can use SplFixedArray:

$array = new SplFixedArray(3);

$array[0] = 1;
$array[1] = 2;
$array[2] = 3;
$array[3] = 4; // RuntimeException

// Increase the size of the array to 10
$array->setSize(10);

Note: An array created using SplFixedArray has a reduced memory footprint for large sets of data, but the keys must be integers.


To initialize an array with a dynamic size but with n non empty elements (e.g. a placeholder) you can use a loop as follows:

$myArray = array();
$sizeOfMyArray = 5;
$fill = 'placeholder';

for ($i = 0; $i < $sizeOfMyArray; $i++) {
    $myArray[] = $fill;
}

// print_r($myArray); results in the following:
// Array ( [0] => placeholder [1] => placeholder [2] => placeholder [3] => placeholder [4] => placeholder ) 

If all your placeholders are the same then you can also create it using the function array_fill():

In PHP 5.5 and later you can use array_column() in conjunction with array_search().

This is particularly useful for checking if a value exists in an associative array:

$userdb = [
    [
        "uid" => '100',
        "name" => 'Sandra Shush',
        "url" => 'urlof100',
    ],
    [
        "uid" => '5465',
        "name" => 'Stefanie Mcmohn',
        "pic_square" => 'urlof100',
    ],
    [
        "uid" => '40489',
        "name" => 'Michael',
        "pic_square" => 'urlof40489',
    ]
];

$key = array_search(40489, array_column($userdb, 'uid'));

Validating the array type

The function is_array() returns true if a variable is an array.

$integer = 1337;
$array = [1337, 42];

is_array($integer); // false
is_array($array); // true

You can type hint the array type in a function to enforce a parameter type; passing anything else will result in a fatal error.

function foo (array $array) { /* $array is an array */ }

You can also use the gettype() function.

$integer = 1337;
$array = [1337, 42];

gettype($integer) === 'array'; // false
gettype($array) === 'array'; // true

ArrayAccess and Iterator Interfaces

Another useful feature is accessing your custom object collections as arrays in PHP. There are two interfaces available in PHP (>=5.0.0) core to support this: ArrayAccess and Iterator. The former allows you to access your custom objects as array.

ArrayAccess

Assume we have a user class and a database table storing all the users. We would like to create a UserCollection class that will:

  1. allow us to address certain user by their username unique identifier
  2. perform basic (not all CRUD, but at least Create, Retrieve and Delete) operations on our users collection

Consider the following source (hereinafter we’re using short array creation syntax [] available since version 5.4):

class UserCollection implements ArrayAccess {
    protected $_conn;
    
    protected $_requiredParams = ['username','password','email'];
    
    public function __construct() {
        $config = new Configuration();

        $connectionParams = [
            //your connection to the database
        ];
        
        $this->_conn = DriverManager::getConnection($connectionParams, $config);
    }
    
    protected function _getByUsername($username) {
        $ret = $this->_conn->executeQuery('SELECT * FROM `User` WHERE `username` IN (?)',
            [$username]
        )->fetch();
        
        return $ret;
    }
    
    // START of methods required by ArrayAccess interface
    public function offsetExists($offset) {
        return (bool) $this->_getByUsername($offset);
    }

    public function offsetGet($offset) {
        return $this->_getByUsername($offset);
    }

    public function offsetSet($offset, $value) {
        if (!is_array($value)) {
            throw new \Exception('value must be an Array');
        }

        $passed = array_intersect(array_values($this->_requiredParams), array_keys($value));
        if (count($passed) < count($this->_requiredParams)) {
            throw new \Exception('value must contain at least the following params: ' . implode(',', $this->_requiredParams));
        }
        $this->_conn->insert('User', $value);
    }

    public function offsetUnset($offset) {
        if (!is_string($offset)) {
            throw new \Exception('value must be the username to delete');
        }
        if (!$this->offsetGet($offset)) {
            throw new \Exception('user not found');
        }
        $this->_conn->delete('User', ['username' => $offset]);
    }
    // END of methods required by ArrayAccess interface
}

then we can :

$users = new UserCollection();

var_dump(empty($users['testuser']),isset($users['testuser']));
$users['testuser'] = ['username' => 'testuser', 
                      'password' => 'testpassword',
                      'email'    => 'test@test.com'];
var_dump(empty($users['testuser']), isset($users['testuser']), $users['testuser']);
unset($users['testuser']);
var_dump(empty($users['testuser']), isset($users['testuser']));

which will output the following, assuming there was no testuser before we launched the code:

bool(true)
bool(false)
bool(false)
bool(true)
array(17) {
  ["username"]=>
  string(8) "testuser"
  ["password"]=>
  string(12) "testpassword"
  ["email"]=>
  string(13) "test@test.com"
}
bool(true)
bool(false)

IMPORTANT: offsetExists is not called when you check existence of a key with array_key_exists function. So the following code will output false twice:

var_dump(array_key_exists('testuser', $users));
$users['testuser'] = ['username' => 'testuser', 
                      'password' => 'testpassword',
                      'email'    => 'test@test.com'];
var_dump(array_key_exists('testuser', $users));

Iterator

Let’s extend our class from above with a few functions from Iterator interface to allow iterating over it with foreach and while.

First, we need to add a property holding our current index of iterator, let’s add it to the class properties as $_position:

// iterator current position, required by Iterator interface methods
protected $_position = 1;

Second, let’s add Iterator interface to the list of interfaces being implemented by our class:

class UserCollection implements ArrayAccess, Iterator {

then add the required by the interface functions themselves:

// START of methods required by Iterator interface
public function current () {
    return $this->_getById($this->_position);
}
public function key () {
    return $this->_position;
}
public function next () {
    $this->_position++;
}
public function rewind () {
    $this->_position = 1;
}
public function valid () {
    return null !== $this->_getById($this->_position);
}
// END of methods required by Iterator interface

So all in all here is complete source of the class implementing both interfaces. Note that this example is not perfect, because the IDs in the database may not be sequential, but this was written just to give you the main idea: you can address your objects collections in any possible way by implementing ArrayAccess and Iterator interfaces:

class UserCollection implements ArrayAccess, Iterator {
    // iterator current position, required by Iterator interface methods
    protected $_position = 1;
    
    // <add the old methods from the last code snippet here>
    
    // START of methods required by Iterator interface
    public function current () {
        return $this->_getById($this->_position);
    }
    public function key () {
        return $this->_position;
    }
    public function next () {
        $this->_position++;
    }
    public function rewind () {
        $this->_position = 1;
    }
    public function valid () {
        return null !== $this->_getById($this->_position);
    }
    // END of methods required by Iterator interface
}

and a foreach looping through all user objects:

foreach ($users as $user) {
    var_dump($user['id']);
}

which will output something like

string(2) "1"
string(2) "2"
string(2) "3"
string(2) "4"
...

Creating an array of variables

$username = 'Hadibut';
$email = 'hadibut@example.org';

$variables = compact('username', 'email');
// $variables is now ['username' => 'Hadibut', 'email' => 'hadibut@example.org']

This method is often used in frameworks to pass an array of variables between two components.


This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow