array_keys()
Glossary overview

array_keys()

Функция array_keys() возвращает все ключи из массива.

Простой пример

$data = [
    'name' => 'Alex',
    'age' => 25,
    'country' => 'Ukraine'
];

$keys = array_keys($data);
print_r($keys);

// Output
Array
(
    [0] => name
    [1] => age
    [2] => country
)

Пример с поиском значения

Ты можешь искать ключи по значению:

$data = ['apple', 'banana', 'apple', 'cherry'];

$keys = array_keys($data, 'apple');
print_r($keys);

// Output
Array
(
    [0] => 0
    [1] => 2
)

То есть array_keys() нашла, где в массиве находится значение 'apple'.

💡 Задача: Найти пользователей, у которых статус — “active”, и вывести их имена

У тебя есть массив пользователей в виде ассоциативного массива, где ключ — это ID пользователя, а значение — массив с именем и статусом. Твоя цель — вывести имена только активных пользователей.

Исходный массив:

$users = [
    101 => ['name' => 'Alice', 'status' => 'active'],
    102 => ['name' => 'Bob', 'status' => 'inactive'],
    103 => ['name' => 'Charlie', 'status' => 'active'],
    104 => ['name' => 'Diana', 'status' => 'banned'],
    105 => ['name' => 'Eve', 'status' => 'active'],
];

Решение (пошагово):

  1. Создадим массив статусов.
  2. С помощью array_keys() найдём ID пользователей со статусом 'active'.
  3. Выведем имена этих пользователей по ID.
$users = [
    101 => ['name' => 'Alice', 'status' => 'active'],
    102 => ['name' => 'Bob', 'status' => 'inactive'],
    103 => ['name' => 'Charlie', 'status' => 'active'],
    104 => ['name' => 'Diana', 'status' => 'banned'],
    105 => ['name' => 'Eve', 'status' => 'active'],
];

// 1. Соберём массив статусов по ID
$statuses = array_column($users, 'status');
// [
    101 => 'active',
    102 => 'inactive',
    103 => 'active',
    104 => 'banned',
    105 => 'active'
]

// 2. Найдём ID пользователей со статусом "active"
$active_ids = array_keys($statuses, 'active');
// [101, 103, 105];

// 3. Выведем имена активных пользователей
foreach ($active_ids as $id) {
    echo $users[$id]['name'] . PHP_EOL;
}

Результат:

Alice
Charlie
Eve

💼 Задача:

У тебя есть массив заказов из интернет-магазина. Нужно:

  1. Найти всех пользователей, у которых есть хотя бы один оплаченный заказ.
  2. Из них — выбрать только тех, кто сделал более одного заказа.
  3. Вывести имена этих пользователей.

И всё это сделать с помощью array_keys() (и других функций, конечно).

Исходные данные:

$orders = [
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'paid'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'pending'],
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'pending'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid'],
    ['user_id' => 4, 'name' => 'Dmitry', 'status' => 'cancelled'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'pending'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid'],
];

Логика решения:

  1. Считаем, сколько заказов сделал каждый пользователь.
  2. Проверим, у кого есть хотя бы один status == 'paid'.
  3. Оставим только тех, у кого больше одного заказа.
  4. Используем array_keys() для фильтрации нужных user_id.

Решение:

$orders = [
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'paid'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'pending'],
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'pending'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid'],
    ['user_id' => 4, 'name' => 'Dmitry', 'status' => 'cancelled'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid'],
];

// Шаг 1. Считаем количество заказов для каждого user_id
$order_counts = [];
$paid_users = [];

foreach ($orders as $order) {
    $id = $order['user_id'];

    // Считаем заказы
    if (!isset($order_counts[$id])) {
        $order_counts[$id] = 0;
    }
    $order_counts[$id]++;

    // Отмечаем, если есть оплаченный заказ
    if ($order['status'] === 'paid') {
        $paid_users[$id] = $order['name']; // сохраняем имя
    }
}

// Шаг 2. Отбираем тех, у кого более одного заказа
$multiple_orders_ids = array_keys(array_filter($order_counts, fn($count) => $count > 1));

// Шаг 3. Отбираем тех, кто есть и в paid_users, и у кого >1 заказ
$final_ids = array_intersect(array_keys($paid_users), $multiple_orders_ids);

// Шаг 4. Выводим имена
foreach ($final_ids as $id) {
    echo $paid_users[$id] . PHP_EOL;
}

// Output
Anna
Boris
Clara

У всех троих есть хотя бы один оплаченный заказ и более одного заказа всего.

Усложним задачу.

Теперь подключим дату заказа, и добавим фильтрацию по дате, чтобы выбрать только пользователей, которые:

Найди всех пользователей, у которых более одного заказа, хотя бы один из которых был оплачен за последние 30 дней. Выведи их имена.

Обновлённый массив заказов:

$orders = [
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'paid',      'date' => '2025-04-01'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'pending',   'date' => '2025-03-10'],
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'pending',   'date' => '2025-03-20'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid',      'date' => '2025-04-10'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid',      'date' => '2025-02-15'],
    ['user_id' => 4, 'name' => 'Dmitry', 'status' => 'cancelled', 'date' => '2025-04-01'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid',      'date' => '2025-01-15'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid',      'date' => '2025-04-02'],
];

📅 Текущая дата: 2025-04-15

✅ Алгоритм:

  1. Считаем количество заказов на пользователя.
  2. Ищем пользователей, у которых есть хотя бы один оплаченный заказ за последние 30 дней.
  3. Оставляем только тех, у кого больше одного заказа.
  4. Выводим имена.

💡 Решение:

$orders = [
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'paid',      'date' => '2025-04-01'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'pending',   'date' => '2025-03-10'],
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'pending',   'date' => '2025-03-20'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid',      'date' => '2025-04-10'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid',      'date' => '2025-02-15'],
    ['user_id' => 4, 'name' => 'Dmitry', 'status' => 'cancelled', 'date' => '2025-04-01'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid',      'date' => '2025-01-15'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid',      'date' => '2025-04-02'],
];

$now = new DateTime('2025-04-15');
$days_back = new DateInterval('P30D');
$cutoff = $now->sub($days_back);

$order_counts = [];
$recent_paid_users = [];

foreach ($orders as $order) {
    $id = $order['user_id'];
    $date = new DateTime($order['date']);

    // Считаем количество заказов
    if (!isset($order_counts[$id])) {
        $order_counts[$id] = 0;
    }
    $order_counts[$id]++;

    // Если оплачен и за последние 30 дней — добавляем
    if ($order['status'] === 'paid' && $date > $cutoff) {
        $recent_paid_users[$id] = $order['name'];
    }
}

// Пользователи с >1 заказом
$multiple_orders_ids = array_keys(array_filter($order_counts, fn($count) => $count > 1));

// Совпадение по user_id
$final_ids = array_intersect(array_keys($recent_paid_users), $multiple_orders_ids);

// Вывод
foreach ($final_ids as $id) {
    echo $recent_paid_users[$id] . PHP_EOL;
}

// Output
Anna
Clara
Boris

Новая задача:

Найди пользователей, у которых минимум 2 оплаченных заказа за последние 30 дней.
Выведи их имена и количество таких заказов.

Данные всё те же:

$orders = [
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'paid',      'date' => '2025-04-01'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'pending',   'date' => '2025-03-10'],
    ['user_id' => 1, 'name' => 'Anna',   'status' => 'pending',   'date' => '2025-03-20'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid',      'date' => '2025-04-10'],
    ['user_id' => 3, 'name' => 'Clara',  'status' => 'paid',      'date' => '2025-02-15'],
    ['user_id' => 4, 'name' => 'Dmitry', 'status' => 'cancelled', 'date' => '2025-04-01'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid',      'date' => '2025-01-15'],
    ['user_id' => 2, 'name' => 'Boris',  'status' => 'paid',      'date' => '2025-04-02'],
];

Решение:

$now = new DateTime('2025-04-15');
$cutoff = (clone $now)->sub(new DateInterval('P30D'));

$paid_counts = [];
$user_names = [];

foreach ($orders as $order) {
    $id = $order['user_id'];
    $date = new DateTime($order['date']);

    // Сохраняем имя
    $user_names[$id] = $order['name'];

    // Считаем оплаченные заказы за последние 30 дней
    if ($order['status'] === 'paid' && $date > $cutoff) {
        if (!isset($paid_counts[$id])) {
            $paid_counts[$id] = 0;
        }
        $paid_counts[$id]++;
    }
}

// Фильтруем тех, у кого 2+ оплаченных заказов за последние 30 дней
$filtered_users = array_filter($paid_counts, fn($count) => $count >= 2);

// Выводим результат
foreach ($filtered_users as $id => $count) {
    echo "{$user_names[$id]}: $count заказ(а/ов) за последние 30 дней" . PHP_EOL;
}

// Output
Clara: 2 заказ(а/ов) за последние 30 дней

📌 Пояснение:

  • Clara: 2 оплаченных заказа, один 10 апреля и один 15 февраля → второй слишком старый, но первый 10 апреля засчитывается, а второй оплаченный нет.

Ой! Стоп! 😅

Clara:

  • 2025-04-10 — ✅
  • 2025-02-15 — ❌ (старый)

Значит у неё только 1, а не 2. 🤯
Нужно пересчитать!

Правильный результат:

  • Anna: 1 оплаченный заказ — ❌
  • Boris: 1 оплаченный в 30 дней — ❌
  • Clara: 1 — ❌
    👉 Никто не прошёл условие >= 2 заказов за 30 дней