PHP сортировка многомерных массивов на основе значений, но получение неожиданных результатов - PullRequest
0 голосов
/ 22 октября 2018

, так что я некоторое время ломал голову об этом и почти уже там, но все еще получаю неожиданные результаты.

Итак, у меня есть база данных, содержащая следующие данные

username |  level1    |  level2    |  level3
user1    |  39.76072  |  79.41869  |  151.2955
user2    |  39.80072  |  80.73846  |  270.6498
user3    |  39.84072  |  80.81845  |  83.41801
user4    |  39.85321  |  80.90525  |  88.31719
user5    |  Zero      |  Zero      |  Zero

Я пытался поместить их в многомерный массив по порядку от низшего к высшему, но действительно боролся.Это в основном уровни времени, и я пытаюсь создать таблицу лидеров.

Я предполагаю, что проблема заключается в том, что столбцы уровня не INT, а скорее CHAR

В настоящее время я пробую следующее

function order_by_time($a, $b) {
    return $b["Level".$_POST["level"]] < $a["Level".$_POST["level"]] ? 1 : -1;
}


$query = mysqli_query($con, "SELECT userName, Level".$_POST["level"]." FROM table");
$results = array();
$unranked = array();
while($line = mysqli_fetch_array($query, MYSQLI_ASSOC)){
    if($line["Level".$_POST["level"]] == "Zero"){
        $unranked[] = $line;
    } else{
        $results[] = $line;
    }
}
usort($results, "order_by_time");
$results = array_merge($results, $unranked);

Это работает для уровня 1 и для уровня 2, но не для уровня 3.Уровень 1 отображается так же, как и в примере с базой данных aboce, и уровень 2, но проблема в том, что уровень 3 так и не в правильном порядке.

похоже, что это связано с количеством символов додесятичное число.

Любой совет, как я могу решить эту проблему, не касаясь базы данных?это не совсем вариант, так как он уже используется.

Я бы очень признателен за помощь в этом: -)

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

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

Если выпросто повторяя их в HTML, вы, вероятно, не увидите пробелы, но вы увидите их, если вы var_dump переменную.Обычное поведение PHP - сравнивать числовые строки как числа, но это не сработает, если есть лишние пробелы.

$test = '151.2955' > '83.41801';
var_dump($test); // true
$test = '151.2955 ' > '83.41801 ';
var_dump($test); // false

Попробуйте обрезать значения.

$query = mysqli_query($con, "SELECT userName, TRIM(Level3) AS userValue FROM table");

Выражение является псевдонимом, поэтому обращайтесь к нему в своем PHP-коде как $row['userValue'] вместо использования значения из $_POST.Если это работает, это также может позволить вам использовать ORDER BY в MySQL.Я не совсем уверен, есть ли у пробелов тот же результат, что и в PHP.Я думаю, вам нужно привести столбец к числовому типу, чтобы он мог правильно сортироваться независимо от пробелов.К сожалению, вы не можете изменить таблицу, чтобы сохранить номер как число.

0 голосов
/ 22 октября 2018

Во-первых, не вставляйте что-либо из $_POST непосредственно в запрос SQL.Вот как сайты взламываются.В этом конкретном случае я бы порекомендовал установить переменную с приведенным параметром в целочисленное значение, а также проверить ее значение:

$level = (int)$_POST["level"];
if ($level > 0 && $level < 4) {
    $query = $con->query("SELECT userName, Level$level FROM table");
} else {
    die();
}

Что касается вашего вопроса, простое решение здесь заключается в сортировке в базе данных.,ORDER BY Level$level и все готово.

$level = (int)$_POST["level"];
if ($level > 0 && $level < 4) {
    $query = $con->query("SELECT userName, Level$level FROM table ORDER BY Level$level");
} else {
    die();
}
$results = $query->fetch_all(MYSQLI_ASSOC);

Если это невозможно по какой-то причине, то, что у вас есть, должно работать нормально, согласно моему тестированию.Но это довольно забавно, особенно перетаскивая информацию из $_POST в пользовательскую функцию.Вместо этого просто используйте встроенные возможности PHP для работы с многомерными массивами.

$level = (int)$_POST["level"];
if ($level > 0 && $level < 4) {
    $query = $con->query("SELECT userName, Level$level FROM table");
} else {
    die();
}
$results = $query->fetch_all(MYSQLI_ASSOC);
$usernames = array_column($results, "username");
$times = array_column($results, "Level$level");
array_multisort($times, SORT_ASC, $results);
...