@artishok
кратко

Не получается правильно перегнать данные из базы в массив

Есть пара таблиц: страны и города. Структура самая простая id, name. Для примера.
$sql = 'SELECT * FROM city, country 
		WHERE city.country_id=country.id 
		GROUP BY city.id 
		ORDER BY country.id ASC, city.id ASC';

Нужно вытащить все данные из базы и загнать в массив вида
spoiler
return array(
        array (
                'country' => 'Russia',
                'country_id' => '17',
                'cities' => array (
                        array (
                                'city' => 'Moscow',
                                'city_id' => '23',
                                'extra' => array (),
                        ),
						array (
                                'city' => 'Saint Petersburg',
                                'city_id' => '32',
                                'extra' => array (),
                        ),
                ),
        ),
		array (
                'country' => 'Ukraine',
                'country_id' => '34',
                'cities' => array (
                        array (
                                'city' => 'Kiev',
                                'city_id' => '51',
                                'extra' => array (),
                        ),
						array (
                                'city' => 'Odessa',
                                'city_id' => '68',
                                'extra' => array (),
                        ),
                ),
        ),
);


есть простой код
<?php
while($data = @mysql_fetch_assoc($result_sql)) {

	$cities[$data['country_id']][] = array(
		'city' => ''.$data['city_name'].'',
		'city_id' => $data['city_id'],
		'extra' => array()
	);
	
	if($country_id != $data['country_id']) {
		$country_name[] = array(
			'country' => ''.$data['country_name'].'',
			'country_id' => $data['country_id'],
			'cities' => $cities[$data['country_id']]
		);	
	}
	
	$country_id = $data['country_id'];

}


Он делает то что нужно, но со смещением на 1 страну, т.е. для второй страны показывает города из первой, для третьей - из второй, для четвертой - из пятой и т.д....

Если же поставить просто отображение названий стран и городов в них - все правильно.

Что-то голова совсем не варит(
  • Вопрос задан
  • 2682 просмотра
Решения вопроса 1
omun
@omun
Нужно исправить на 'cities' => $cities[$country_id]
Вы добавляете страну по факту смены id, подразумевая, что все города уже будут внесены для неё.
1. Вы должны продублировать код после цикла, иначе последняя группа вообще не будет внесена в результирующий массив
2. В вашем же случае он вытаскивает из справочника значение для $data['country_id'], то есть для новой страны, в то время, когда надо записывать значение для прежней страны

Поправил бы следующим образом:
$country_id = null;
$last_country_index = -1;
while($data = @mysql_fetch_assoc($result_sql)) {
    if ($country_id !== $data['country_id']) {
        $country_name[] = array(
            'country' => ''.$data['country_name'].'',
            'country_id' => $data['country_id'],
            'cities' => array()
        );
        $country_id = $data['country_id'];
        $last_country_index++;
    }
    $country_name[$last_country_index]['cities'][] = array(
        'city' => ''.$data['city_name'].'',
        'city_id' => $data['city_id'],
        'extra' => array()
    );
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Например вот так

<?php

$rows = array(
	array(
		'country_id' => 1,
		'country_name' => 'Country1',
		'city_id' => 1,
		'city_name' => 'City1'
	),
	array(
		'country_id' => 1,
		'country_name' => 'Country1',
		'city_id' => 2,
		'city_name' => 'City11'
	),
	array(
		'country_id' => 2,
		'country_name' => 'Country2',
		'city_id' => 2,
		'city_name' => 'City2'
	),
	array(
		'country_id' => 3,
		'country_name' => 'Country3',
		'city_id' => 3,
		'city_name' => 'City3'
	),
);

$result = array();
$prevId = -1;

foreach($rows as $row) {
	if ($row['country_id'] != $prevId) {
            $result[] = array(
                'country_id' => $row['country_id'],
                'country' => $row['country_name'],
                'cities' => array_filter($rows, function($val) use ($row) {
                     return $row['country_id'] == $val['country_id'];
                 })
             );
	}

	$prevId = $row['country_id'];	
}

var_dump($result);
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы