PHP
Массивы
Поиск…
Вступление
Массив - это структура данных, которая хранит произвольное количество значений в одном значении. Массив в PHP на самом деле является упорядоченной картой, где map - это тип, который связывает значения с ключами.
Синтаксис
- $ array = array ('Value1', 'Value2', 'Value3'); // Ключи по умолчанию равны 0, 1, 2, ...,
- $ array = array ('Value1', 'Value2',); // Дополнительная запятая
- $ array = array ('key1' => 'Value1', 'key2' => 'Value2',); // Явные ключи
- $ array = array ('key1' => 'Value1', 'Value2',); // Array (['key1'] => Value1 [1] => 'Value2')
- $ array = ['key1' => 'Value1', 'key2' => 'Value2',]; // Сокращение PHP 5.4+
- $ array [] = 'ValueX'; // Добавим 'ValueX' в конец массива
- $ array ['keyX'] = 'ValueX'; // Назначьте 'valueX' клавише 'keyX'
- $ array + = ['keyX' => 'valueX', 'keyY' => 'valueY']; // Добавление / Перезапись элементов в существующем массиве
параметры
параметр | подробность |
---|---|
ключ | Ключ - это уникальный идентификатор и индекс массива. Это может быть string или integer . Поэтому действительными ключами будут 'foo', '5', 10, 'a2b', ... |
Значение | Для каждого key есть соответствующее значение ( null противном случае и уведомление выдается при доступе ). Значение не имеет ограничений для типа ввода. |
замечания
Инициализация массива
Массив может быть инициализирован пустым:
// An empty array
$foo = array();
// Shorthand notation available since PHP 5.4
$foo = [];
Массив может быть инициализирован и задан со значениями:
// Creates a simple array with three strings
$fruit = array('apples', 'pears', 'oranges');
// Shorthand notation available since PHP 5.4
$fruit = ['apples', 'pears', 'oranges'];
Массив также может быть инициализирован с помощью пользовательских индексов (также называемых ассоциативным массивом) :
// 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'
];
Если переменная ранее не использовалась, PHP создаст ее автоматически. Хотя это удобно, это может затруднить чтение кода:
$foo[] = 1; // Array( [0] => 1 )
$bar[][] = 2; // Array( [0] => Array( [0] => 2 ) )
Индекс, как правило, будет продолжаться там, где вы остановились. PHP будет пытаться использовать числовые строки как целые числа:
$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!
Чтобы инициализировать массив с фиксированным размером, вы можете использовать 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);
Примечание. Массив, созданный с использованием SplFixedArray
имеет уменьшенный объем памяти для больших наборов данных, но ключи должны быть целыми.
Чтобы инициализировать массив с динамическим размером, но с n
непустыми элементами (например, заполнителем), вы можете использовать цикл следующим образом:
$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 )
Если все ваши заполнители совпадают, вы также можете создать его с помощью функции array_fill()
:
array array_fill (int $ start_index, int $ num, смешанное значение $)
Это создает и возвращает массив с num
элементами value
, ключи, начинающиеся с start_index
.
Примечание. Если start_index
отрицательный, он начнет с отрицательного индекса и продолжит с 0 для следующих элементов.
$a = array_fill(5, 6, 'banana'); // Array ( [5] => banana, [6] => banana, ..., [10] => banana)
$b = array_fill(-2, 4, 'pear'); // Array ( [-2] => pear, [0] => pear, ..., [2] => pear)
Вывод: с помощью array_fill()
вы более ограничены тем, что вы действительно можете сделать. Цикл более гибкий и открывает вам более широкий спектр возможностей.
Всякий раз, когда вам нужен массив, заполненный диапазоном чисел (например, 1-4), вы можете либо добавить каждый отдельный элемент в массив, либо использовать функцию range()
:
диапазон массивов (смешанный $ start, mixed $ end [, number $ step = 1])
Эта функция создает массив, содержащий ряд элементов. Требуются первые два параметра, где они устанавливают начальную и конечную точки диапазона (включительно). Третий параметр является необязательным и определяет размер выполняемых шагов. Создавая range
от 0
до 4
с stepsize
1
, результирующий массив будет состоять из следующих элементов: 0
, 1
, 2
, 3
и 4
. Если размер шага увеличен до 2
(то есть range(0, 4, 2)
), то результирующий массив будет равен: 0
, 2
и 4
.
$array = [];
$array_with_range = range(1, 4);
for ($i = 1; $i <= 4; $i++) {
$array[] = $i;
}
print_r($array); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
print_r($array_with_range); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
range
может работать с целыми числами, float, boolean (которые становятся отлитыми от целых чисел) и строками. Однако следует соблюдать осторожность при использовании float в качестве аргументов из-за проблемы точности с плавающей запятой.
Проверьте, существует ли ключ
Используйте array_key_exists()
или isset()
или !empty()
array_key_exists()
!empty()
:
$map = [
'foo' => 1,
'bar' => null,
'foobar' => '',
];
array_key_exists('foo', $map); // true
isset($map['foo']); // true
!empty($map['foo']); // true
array_key_exists('bar', $map); // true
isset($map['bar']); // false
!empty($map['bar']); // false
Обратите внимание, что isset()
обрабатывает null
элемент как несуществующий. Принимая во внимание, что !empty()
делает то же самое для любого элемента, который равен false
(с использованием слабого сравнения, например, null
, ''
и 0
все обрабатываются как false by !empty()
). Хотя isset($map['foobar']);
is true
!empty($map['foobar'])
является false
. Это может привести к ошибкам (например, легко забыть, что строка '0'
рассматривается как ложная), поэтому использование метода !empty()
часто неодобрительно.
Также обратите внимание, что isset()
и !empty()
будут работать (и возвращать false), если $map
вообще не определен. Это делает их несколько склонными к ошибкам использовать:
// Note "long" vs "lang", a tiny typo in the variable name.
$my_array_with_a_long_name = ['foo' => true];
array_key_exists('foo', $my_array_with_a_lang_name); // shows a warning
isset($my_array_with_a_lang_name['foo']); // returns false
Вы также можете проверить порядковые массивы:
$ord = ['a', 'b']; // equivalent to [0 => 'a', 1 => 'b']
array_key_exists(0, $ord); // true
array_key_exists(2, $ord); // false
Обратите внимание, что isset()
имеет лучшую производительность, чем array_key_exists()
поскольку последняя является функцией, а первая - конструкцией языка.
Вы также можете использовать key_exists()
, который является псевдонимом для array_key_exists()
.
Проверка наличия значения в массиве
Функция in_array()
возвращает true, если элемент существует в массиве.
$fruits = ['banana', 'apple'];
$foo = in_array('banana', $fruits);
// $foo value is true
$bar = in_array('orange', $fruits);
// $bar value is false
Вы также можете использовать функцию array_search()
чтобы получить ключ определенного элемента в массиве.
$userdb = ['Sandra Shush', 'Stefanie Mcmohn', 'Michael'];
$pos = array_search('Stefanie Mcmohn', $userdb);
if ($pos !== false) {
echo "Stefanie Mcmohn found at $pos";
}
В PHP 5.5 и более поздних версиях вы можете использовать array_column()
в сочетании с array_search()
.
Это особенно полезно для проверки того, существует ли значение в ассоциативном массиве :
$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'));
Проверка типа массива
Функция is_array()
возвращает true, если переменная является массивом.
$integer = 1337;
$array = [1337, 42];
is_array($integer); // false
is_array($array); // true
Вы можете ввести подсказку типа массива в функции для принудительного применения типа параметра; передача чего-либо другого приведет к фатальной ошибке.
function foo (array $array) { /* $array is an array */ }
Вы также можете использовать gettype()
.
$integer = 1337;
$array = [1337, 42];
gettype($integer) === 'array'; // false
gettype($array) === 'array'; // true
Интерфейсы ArrayAccess и Iterator
Еще одна полезная функция - доступ к вашим коллекциям пользовательских объектов в виде массивов в PHP. Есть два интерфейса, доступных в ядре PHP (> = 5.0.0) для поддержки этого: ArrayAccess
и Iterator
. Первый позволяет вам получить доступ к своим пользовательским объектам в виде массива.
ArrayAccess
Предположим, что у нас есть класс пользователя и таблица базы данных, в которых хранятся все пользователи. Мы хотели бы создать класс UserCollection
который будет:
- позволяют нам обращаться к определенному пользователю с помощью уникального идентификатора имени пользователя
- выполнять основные (не все CRUD, но как минимум Create, Retrieve and Delete) операции с нашей коллекцией пользователей
Рассмотрим следующий источник (в дальнейшем мы используем короткий синтаксис создания массива []
доступный начиная с версии 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
}
то мы можем:
$users = new UserCollection();
var_dump(empty($users['testuser']),isset($users['testuser']));
$users['testuser'] = ['username' => 'testuser',
'password' => 'testpassword',
'email' => '[email protected]'];
var_dump(empty($users['testuser']), isset($users['testuser']), $users['testuser']);
unset($users['testuser']);
var_dump(empty($users['testuser']), isset($users['testuser']));
который выведет следующее, предполагая, что не было testuser
до того, как мы запустили код:
bool(true)
bool(false)
bool(false)
bool(true)
array(17) {
["username"]=>
string(8) "testuser"
["password"]=>
string(12) "testpassword"
["email"]=>
string(13) "[email protected]"
}
bool(true)
bool(false)
ВАЖНО: offsetExists
не вызывается, когда вы проверяете наличие ключа с функцией array_key_exists
. Таким образом, следующий код будет выводить false
дважды:
var_dump(array_key_exists('testuser', $users));
$users['testuser'] = ['username' => 'testuser',
'password' => 'testpassword',
'email' => '[email protected]'];
var_dump(array_key_exists('testuser', $users));
Итератор
Давайте расширим наш класс сверху несколькими функциями из интерфейса Iterator
чтобы разрешить повторить его с помощью foreach
и while
.
Во-первых, нам нужно добавить свойство, содержащее наш текущий индекс итератора, добавим его в свойства класса как $_position
:
// iterator current position, required by Iterator interface methods
protected $_position = 1;
Во-вторых, добавим интерфейс Iterator
в список интерфейсов, реализуемых нашим классом:
class UserCollection implements ArrayAccess, Iterator {
затем добавьте необходимые функции интерфейса:
// 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
Таким образом, все здесь является полным источником класса, реализующего оба интерфейса. Обратите внимание, что этот пример не идеальный, поскольку идентификаторы в базе данных могут быть не последовательными, но это было написано только для того, чтобы дать вам основную идею: вы можете каким-либо образом ArrayAccess
свои коллекции объектов с ArrayAccess
интерфейсов ArrayAccess
и Iterator
:
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
}
и цикл foreach через все пользовательские объекты:
foreach ($users as $user) {
var_dump($user['id']);
}
который выведет что-то вроде
string(2) "1"
string(2) "2"
string(2) "3"
string(2) "4"
...
Создание массива переменных
$username = 'Hadibut';
$email = '[email protected]';
$variables = compact('username', 'email');
// $variables is now ['username' => 'Hadibut', 'email' => '[email protected]']
Этот метод часто используется в рамках, чтобы передать массив переменных между двумя компонентами.