81phonk
@81phonk
php is dead?

Как трансформировать массив?

Всем привет! Подскажите, как реализовать логику для изменения массива `messages` в `messages2`.
Нужно сгруппировать элементы по значению `customer_id`, сохранив их порядок. В данном примере сначала нужно сгруппировать элементы с `id = 1` и `2`, затем `3` и `4`, и так далее.

Данные
"messages": [
	{
		"id": 1,
		"customer": "Dr. Kane Hill",
		"customer_id": 1,
		"created_at": "2024-11-19 11:18:57",
		"text": "Hello, how are you?"
	},
	{
		"id": 2,
		"customer": "Dr. Kane Hill",
		"customer_id": 1,
		"created_at": "2024-11-19 11:20:57",
		"text": "I am good, thanks! How about you?"
	},
	{
		"id": 3,
		"customer": "Prof. Samir McClure III",
		"customer_id": 2,
		"created_at": "2024-11-19 11:21:57",
		"text": "Hey, what time is it?"
	},
	{
		"id": 4,
		"customer": "Prof. Samir McClure III",
		"customer_id": 2,
		"created_at": "2024-11-19 11:22:57",
		"text": "It is 3 PM."
	},
	{
		"id": 5,
		"customer": "Shad Leffler",
		"customer_id": 3,
		"created_at": "2024-11-19 11:23:57",
		"text": "Did you finish the project?"
	},
	{
		"id": 6,
		"customer": "Shad Leffler",
		"customer_id": 3,
		"created_at": "2024-11-19 11:24:57",
		"text": "New mesh"
	},
	{
		"id": 7,
		"customer": "Prof. Samir McClure III",
		"customer_id": 2,
		"created_at": "2024-11-19 11:26:57",
		"text": "Not bed?"
	},
	{
		"id": 8,
		"customer": "Prof. Samir McClure III",
		"customer_id": 2,
		"created_at": "2024-11-19 11:27:57",
		"text": "Cool?"
	}
]

"messages2": [
	{
		"customer": "Dr. Kane Hill",
		"messages_id": 1,
		"customer_id": 1,
		"messages": [
			{
				"id": 1,
				"created_at": "2024-11-19 11:18:57",
				"text": "Hello, how are you?",
			},
			{
				"id": 2,
				"created_at": "2024-11-19 11:20:57",
				"text": "I am good, thanks! How about you?",
			}
		]
	},
	{
		"customer": "Prof. Samir McClure III",
		"messages_id": 2,
		"customer_id": 2,
		"messages": [
			{
				"id": 3,
				"created_at": "2024-11-19 11:21:57",
				"text": "Hey, what time is it?",
			},
			{
				"id": 4,
				"created_at": "2024-11-19 11:22:57",
				"text": "It is 3 PM."
			}
		]
	},
	{
		"customer": "Shad Leffler",
		"messages_id": 3,
		"customer_id": 3,
		"messages": [
			{
				"id": 4,
				"created_at": "2024-11-19 11:23:57",
				"text": "Did you finish the project?"
			},
			{
				"id": 5,
				"created_at": "2024-11-19 11:24:57",
				"text": "New mesh"
			}
		]
	},
	{
		"customer": "Prof. Samir McClure III",
		"messages_id": 4,
		"customer_id": 2,
		"messages": [
			{
				"id": 6,
				"created_at": "2024-11-19 11:26:57",
				"text": "Not bed?"
			},
			{
				"id": 7,
				"created_at": "2024-11-19 11:27:57",
				"text": "Cool?"
			},

		]
	},
]


У меня получается какой-то монстр.

Код
public function toArray(Request $request): array
    {
        $messages = $this->whenLoaded('messages')->sortBy('id');

        $messagesGroupedByCustomer = [];
        $messagesIdCounter = 1;
        $currentCustomerId = null;
        $currentCustomerMessages = [];

        foreach ($messages as $message) {
            if ($currentCustomerId !== $message['customer_id']) {
                if ($currentCustomerId !== null) {
                    $messagesGroupedByCustomer[] = [
                        'customer' => $currentCustomerMessages[0]['customer']->full_name,
                        'messages' => array_map(function ($msg) {
                            return [
                                'id' => $msg['id'],
                                'created_at' => $msg['created_at']->toDateTimeString(),
                                'text' => $msg['text'],
                            ];
                        }, $currentCustomerMessages),
                    ];
                    $messagesIdCounter++;
                }

                $currentCustomerId = $message['customer_id'];
                $currentCustomerMessages = [];
            }

            $currentCustomerMessages[] = $message;
        }

        if ($currentCustomerId !== null) {
            $messagesGroupedByCustomer[] = [
                'customer' => $currentCustomerMessages[0]['customer']->full_name,
                'messages' => array_map(function ($msg) {
                    return [
                        'id' => $msg['id'],
                        'created_at' => $msg['created_at']->toDateTimeString(),
                        'text' => $msg['text'],
                    ];
                }, $currentCustomerMessages),
            ];
        }
        $data['date'] = "Сегодня";
        $data['item'] = $messagesGroupedByCustomer;

        return $data;
    }
  • Вопрос задан
  • 144 просмотра
Пригласить эксперта
Ответы на вопрос 1
nokimaro
@nokimaro
Меня невозможно остановить, если я смогу начать.
Делается одним проходом в цикле
Ключем выставляем поле по которому делать группировку и внутрь уже ложим нужные данные
В конце array_values() чтобы переиндексировать результат и сбросить ключи

https://3v4l.org/mZQIN#v8.3.14

<?php
error_reporting(-1);
ini_set('display_errors', 1);

$json_data = <<<JSON
{"messages": [
	{
		"id": 1,
		"customer": "Dr. Kane Hill",
		"customer_id": 1,
		"created_at": "2024-11-19 11:18:57",
		"text": "Hello, how are you?"
	},
	{
		"id": 2,
		"customer": "Dr. Kane Hill",
		"customer_id": 1,
		"created_at": "2024-11-19 11:20:57",
		"text": "I am good, thanks! How about you?"
	},
	{
		"id": 3,
		"customer": "Prof. Samir McClure III",
		"customer_id": 2,
		"created_at": "2024-11-19 11:21:57",
		"text": "Hey, what time is it?"
	},
	{
		"id": 4,
		"customer": "Prof. Samir McClure III",
		"customer_id": 2,
		"created_at": "2024-11-19 11:22:57",
		"text": "It is 3 PM."
	},
	{
		"id": 5,
		"customer": "Shad Leffler",
		"customer_id": 3,
		"created_at": "2024-11-19 11:23:57",
		"text": "Did you finish the project?"
	},
	{
		"id": 6,
		"customer": "Shad Leffler",
		"customer_id": 3,
		"created_at": "2024-11-19 11:24:57",
		"text": "New mesh"
	},
	{
		"id": 7,
		"customer": "Prof. Samir McClure III",
		"customer_id": 2,
		"created_at": "2024-11-19 11:26:57",
		"text": "Not bed?"
	},
	{
		"id": 8,
		"customer": "Prof. Samir McClure III",
		"customer_id": 2,
		"created_at": "2024-11-19 11:27:57",
		"text": "Cool?"
	}
]}
JSON;

$messages = json_decode($json_data, true)['messages'];

$messages2 = [];
$messageCounter = 0;
foreach($messages as $row) {
    
    $key = $row['customer_id'];
    
    if(!isset($messages2[$key])) {
        $messages2[$key] = [
            'customer' => $row['customer'],
            'message_id' => (++$messageCounter),
            'customer_id' => $row['customer_id'],
            'messages' => [],
        ];
    }

    
    $messages2[$key]['messages'][] = [
        'id' => $row['id'],
        'created_at' => $row['created_at'],
        'text' => $row['text'],
    ];
}

$messages2 = array_values($messages2);

echo json_encode($messages2, JSON_PRETTY_PRINT);


upd: подправил ответ, так как по всей видимости message_id в сгруппированном результате должен быть счётчиком
upd2: по совету. Adamos обновил ответ убрав не нужные присваивания при каждом проходе цикла
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы