如何从相同的输入名称保存多个值

How would I save in multiple rows values from same input names.

For example, my php,html code from is:

<form action="functions.php" method="post" name="grades">
    <table>
        <thead>
            <tr>
                <th>Subject</th>
                <th>Grade</th>
            </tr>
        </thead>
        <tbody>
            <?php $unos = $baza->odradi("SELECT subject FROM subjects ORDER BY id ASC"); 
            if (!empty($unos)) { 
                foreach($unos as $row=>$value){ ?>
                    <tr>
                        <td><input type="hidden" name="subject_id[]" value="<?= $unos[$row]["id"]; ?>"> <?= $unos[$row]["subject"]; ?></td>
                        <td>
                            <select class="form-control input-xs" name="grade_id[]" required>
                                <option selected disabled>Select grade</option>
                                <option value="5">excelent</option>
                                <option value="4">very good</option>
                                <option value="3">good</option>
                                <option value="2">ok</option>
                                <option value="1">bad</option>
                            </select>
                        </td>
                    </tr>
        </tbody>
    </table>
    <input type="submit" name="grades" class="btn btn-success btn-lg" value="Submit grades">
</form>

And function which from where it needs to be saved looks like this:

if (isset($_POST['grades'])) {  
    foreach (array_combine($_POST['subject_id'], $_POST['grade_id']) as $i => $val){
        $subject = $_POST["subject_id"][$i];
        $grade = $_POST["grade_id"][$i];

        $sql = "INSERT INTO final_grade (subject_id,grade_id) VALUES ('$subject','$grade')";
        $u = mysqli_query($db, $sql);
    }

But it's all messed up,in first two rows there is no grade or subject saved, and all some rows are missing completely.

Because you are calling array_combine(), your loop is not passing the subarray indexes as $i anymore. It is passing the subject_id as $i and grade_id as $val. You could have just used $i and $val as the values to insert rather than trying to re-access the $_POST arrays with $i.

Cleaner scripting would be to use the ids as hardcoded element keys on each <select> instead of passing a hidden field.

<?php
$options = [
    5 => 'excellent',
    4 => 'very good',
    3 => 'good',
    2 => 'ok',
    1 => 'bad'
];
?>

<td><?= $unos[$row]["subject"]; ?></td>
<td><select class="form-control input-xs" name="grade[<?= $unos[$row]["id"]; ?>]" required>
    <option disabled>Select grade</option>
    <?php
    foreach ($options as $opt_id => $opt_val) {
        echo "<option value=\"{$opt_id}\">{$opt_val}</option>";
    }
    ?>
    </select>
 </td>

Then you can simply access the associative submission.

if (isset($_POST['grade'])) {  
    // use prepared statement and bind variables
    foreach ($_POST['grade'] as $id => $val) {
        // execute prepared statement with each iteration
    }
}

Alternatively, you could build up a single batch of results and do a single INSERT (I'd probably do it this way).

Untested suggestion:

$data = [];
foreach ($_POST['grade'] as $subject_id => $grade_id) {
    array_push($data, $subject_id, $grade_id);  // restructure as indexed 1-dim array for unpacking
}
$num_of_inserts = sizeof($data);
$placeholders = array_fill(0, $num_of_inserts, '(?,?)');
$value_types = str_repeat('i', $num_of_inserts * 2);  // i is because you are passing integer values

// execute single batch of inserts
$query = "INSERT INTO final_grade (subject_id,grade_id) VALUES " . implode(',', $placeholders);
$stmt = $conn->prepare($query); 
$stmt->bind_param($value_types, ...$data);
$stmt->execute();

The truth is, there are a number of ways that you can pass the data from your form and a number of ways that you can execute the INSERT query. I won't bother to write out all of the variations -- do what you like ...but definitely write stable/secure queries.