亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用一個查詢的結果進行另一個查詢并填充 HTML 選擇

使用一個查詢的結果進行另一個查詢并填充 HTML 選擇

PHP
慕少森 2022-05-27 16:31:17
我對數據庫的結構沒有發言權或決定權,所以我必須使用我所擁有的。否則,正如大多數評論所說,通過規范化和清理表格,這個問題將大大簡化。我有一個數據庫表,其中包含汽車型號和一些“類別”(國產車、進口車、皮卡車、面包車等)。值得注意的是,這些類別以整數代碼表示。該表每行有 10 個類別列(Use1、Use2、Use3 等),因此每輛車最多可以有 10 個。然后我有另一個表,其中包含對應于每個類別代碼的描述(例如,國產車 = 1,進口車 = 2,等等)。我有一個包含兩個 HTML 選擇元素的表單,一個用于汽車,另一個用于類別。<div class="form-group row">    <label class="col-sm-2 form-control-label">Cars</label>    <div class="col-sm-6">        <select class="form-control" id="car_model" name="car_model" onchange="fetch_categories(this.value);">            <option>Car 1</option>            <option>Car 2</option>            <option>Car 3</option>        </select>    </div></div><div class="form-group row">    <label class="col-sm-2 form-control-label">Category</label>    <div class="col-sm-4">        <select class="form-control" name="category">            <option>Select a car first...</option>        </select>    </div></div>我需要根據汽車選擇的值填充類別選擇。這是通過使用 Ajax 完成的(按預期工作的部分可能與主題無關)。Ajax 函數將汽車數據發送到一個 php 腳本,該腳本通過查詢成功獲取所有相應的類別。我正在努力使用該查詢的結果來獲取通過另一個查詢來自它的所有類別的描述。我試過做一個 foreach 來迭代查詢 #1 的所有結果,然后執行查詢 #2 然后制定<option>標簽,但我沒有做對。<?php$car_model = $_POST['get_car'];$query = "SELECT CodUso1,                 CodUso2,                 CodUso3,                 CodUso4,                 CodUso5,                 CodUso6,                 CodUso7,                 CodUso8,                 CodUso9,                 CodUso10 AS categories FROM cars WHERE car_model = '$car_model'";$stmt = $pdo->prepare($query);$stmt->execute();$result = $stmt->fetchAll();foreach ($result['categories'] as $u):    if ($result['CodUso1'] != 0 ||         $result['CodUso2'] != 0 ||         $result['CodUso3'] != 0 ||         $result['CodUso4'] != 0 ||         $result['CodUso5'] != 0 ||         $result['CodUso6'] != 0 ||         $result['CodUso7'] != 0 ||         $result['CodUso8'] != 0 ||         $result['CodUso9'] != 0 || 結果<option>元素必須包含作為值的汽車代碼和作為“描述”的描述。如果解釋過于復雜,我深表歉意,如果您需要任何進一步的信息或澄清,請告訴我。
查看完整描述

2 回答

?
慕尼黑5688855

TA貢獻1848條經驗 獲得超2個贊

這里有很多錯誤,其中大部分可以通過檢查您的數據來解決。利用var_dump并print_r確保變量包含您認為的內容。


首先,如果您為數據庫列分配別名,則它只是一列。所以你最終得到數組索引CodUso1,CodUso2等到CodUso9,然后categories作為 . 的別名CodUso10。其次,您嘗試循環通過$result["categories"]which 不存在,因為fetchAll將返回一個索引數組。您可以通過使用print_r($result);并查看您正在使用的內容來實現這兩者。第三,您將用戶提供的數據直接傳遞到數據庫查詢中,這是讓您的數據庫受到攻擊的好方法。


試試這個。我們安全地準備一個語句來檢索所有十個類別列,然后一次循環遍歷它們,執行第二個準備好的語句以獲取結果。請注意,除了安全性之外,準備好的語句的好處之一是在重復執行相同的查詢時減少了開銷。最后,盡可能將代碼和演示文稿分開。在循環中間將 HTML 轉儲到屏幕是丑陋且難以使用的。您應該返回一個 JSON 對象,然后使用您的 Javascript 回調來構建元素。


<?php

$car_model = $_POST['get_car'];


// prepare the first query    

$query = "SELECT CodUso1, CodUso2, CodUso3, CodUso4, CodUso5,

        CodUso6, CodUso7, CodUso8, CodUso9, CodUso10

    FROM cars WHERE car_model = ? LIMIT 1";

$stmt = $pdo->prepare($query);

$stmt->execute([$car_model]);

// there's only one item, no loop needed

$categories = $stmt->fetch(\PDO::FETCH_ASSOC);


// here we prepare the second query

$query = "SELECT description FROM categories WHERE code = ?";

$stmt = $pdo->prepare($query);

// bind the variable to the ? parameter

$stmt->bindParam(1, $c);


$options = [];

foreach ($categories as $c) {

    if ($c == 0) {

        continue;

    }

    $stmt->execute();

    // we can fetch the single column directly

    $description = $stmt->fetchColumn();

    $options[] = ["id"=>$c, "description"=>$description];

}


header("Content-Type: application/json");

echo json_encode($options);

然后在你的 Javascript 回調中,做這樣的事情。我假設您使用的是 jQuery:


...

success: function(data, status, xhr) {

    // erase existing values

    $("select[name='category']").html("");

    // jQuery will turn this into an object automatically

    // loop through it and append an option element for each item

    data.each(function(v) {

        var sel = $("<option>").val(v.id).html(v.description);

        $("select[name='category']").append(sel);

    });

}


查看完整回答
反對 回復 2022-05-27
?
慕慕森

TA貢獻1856條經驗 獲得超17個贊

不工作的原因foreach是因為$result['categories']它不是一個數組。您的查詢select子句只是重命名CodUse10為categories.


SELECT CodUso1, 

            CodUso2, 

            CodUso3, 

            CodUso4, 

            CodUso5, 

            CodUso6, 

            CodUso7, 

            CodUso8, 

            CodUso9, 

           CodUso10 AS categories

但真正的問題遠不止于此。它回到你的表模式。任何時候你有諸如 field1、field2、field3 之類的東西……你幾乎可以肯定有一個未規范化的表。正確的架構看起來像這樣:


Car    Car_Category   Category 

id     car_id         id 

model  category_id    description

當您想獲取某輛車的類別列表時,只需查詢連接表:


select c.model, cat.id, cat.description

from car c

inner join car_category cc on c.id=cc.car_id

inner join category cat on cc.category_id=cat.id

where car.id=?

我不完全理解您是否嘗試顯示可用選項或選定選項,但無論哪種方式,都將使用相同類型的多對多連接。因此,car_category您可能有一個名為的表available_options和另一個名為selected_options.


...但是我不能更改數據庫!

在這種情況下,將沒有“正確”的解決方案;只是一些創造性的方法來解決它。目標應該是盡量減少產生的技術債務??赡茏畲蟮牟糠质菍⒛P停ㄟ壿嫞┡c視圖(html)分開。這樣,如果/當架構被更正時,您不必在更改訪問方法時深入視圖并破壞事物;您所要做的就是插入一個不同的類或函數來獲取信息并以相同的方式輸出。


定義視圖期望如何接收模型的數據

在開始使用模型之前,我需要知道視圖將如何使用它。對于我自己的應用程序,我有一個類可以為我格式化輸入、下拉菜單和復選框,ala ruby on rails:


<div class="form-group">

  <label for="category">Category</label>

  <?= FormDecorator::showAsDropDown($optionList, $defaultOption,['id'=>'category','name'=>'category','class'=>'form-control', etc...]) ?>

</div>

要使用它,我將提供一個關聯數組,其中 options = array('value'=>'description')。關鍵是我需要模型來提供該數組,但是它可能會獲取信息。但模型不負責創建任何html。


使用相同的計劃,您的輸出可能看起來像


<div class="form-group row">

    <label class="col-sm-2 form-control-label">Category</label>

    <div class="col-sm-4">

        <select class="form-control" name="category">

            <option disabled selected hidden>Select a car first...</option>

            <?php foreach($options as $value => $description): ?>

              <option value="<?= $value ?>"><?= $description ?></option>

            <?php endforeach; ?>

        </select>

    </div>

</div>

創建模型以提供該數據

通常,我會使用一個對象,因為我使用自己的 MVC 框架。但為了簡單起見,我將使用一個普通的舊函數(但我強烈建議使用類,因為它們更加靈活,并且方法名稱在類的范圍內,而不是全局范圍內)


一次查找描述

您想要遍歷 10 個不同字段的結果,所有字段都命名為CodUso{$number}.


首先,創建一個函數來檢索原始數據:


function getCategoriesFor($car_model) {

    global $pdo; // ick, a class would avoid globals.

    $query =<<<CATEGORYQUERY

SELECT CodUso1, CodUso2, CodUso3, CodUso4, CodUso5, 

       CodUso6, CodUso7, CodUso8, CodUso9, CodUso10

FROM cars 

WHERE car_model = ?


CATEGORYQUERY;

    $stmt = $pdo->prepare($query);

    $stmt->execute($car_model);

    return stmt->fetch(\PDO::FETCH_ASSOC);

 }      

現在,創建一個函數來獲取類別的描述:


// if this were an object, I would call it $Category->find($id)

function getCategoryDescriptionOf($code) {

    global $pdo;

    $query = "select * from categories where code=?";

    $stmt = $pdo->prepare($query);

    $stmt->execute($id);

    return $stmt->fetchAll();

}

然后創建一個函數來遍歷可用的選項:


function getCategoryOptionsByModel($car_model) {


    // get the row containing CodUso1 ... CodUso10

    $categoryRow = getCategoriesFor($car_model);


    // always initialize output before generating its contents

    $out = [];


    // 10 fields, iterate through them.  This is the hacky part...

    for($i=1; $i <= 10; $i++) {


        // generate the field name

        $field = 'CodUso' . $i;


        // get the code from the car_model table row 

        $code = $categoryRow[$field];


        // format the array we will use in the view

        $out[$code] = getCategoryDescriptionOf($code);

    }

    return $out;  // [code => description]

}

哇!現在剩下的就是在視圖中使用它:


<?php

$car_model = $_GET['car_model']; // or however it is assigned...


?>

<html> 

  ... snip ...


<div class="form-group row">

    <label class="col-sm-2 form-control-label">Category</label>

    <div class="col-sm-4">

        <select class="form-control" name="category">

            <option disabled selected hidden>Select a car first...</option>

            <?php foreach( getCategoryOptionsByModel($car_model) as $value => $description): ?>

              <option value="<?= $value ?>"><?= $description ?></option>

            <?php endforeach; ?>

        </select>

    </div>

</div>

歡呼!我標準化了表格!

如果您對表進行規范化,只需編寫一個新函數來替換當前getCategoriesFor()函數(根據需要替換真實字段名稱)并在視圖中使用它,而不是getCategoryOptionsByModel($car_model)或者只是更改 getCategoryOptionsByModel($car_model) 以返回 getCategoriesFor($car_model):


function getCategoriesFor($car_model) {

    global $pdo;

    $query =<<<THISISHOWITSHOULDBEDONEQUERY


select cat.code, cat.description

from cars c

inner join car_category cc on c.id=cc.car_id

inner join category cat on cc.category_id=cat.id

where cars.car_model=?


THISISHOWITSHOULDBEDONEQUERY;


    $stmt = $pdo->prepare($query)->execute($car_model);

    $out = [];

    foreach($stmt as $row) {

        $code = $row['code'];

        $description = $row['description'];

        $out[$code] = $description;

    }

    return $out;

}

好處

通過將邏輯與表示分離,并確保每個函數只做一件小事,您現在可以更輕松地更改數據的編譯方式。除了命名不同的數據源之外,您不必對視圖進行任何更改。如果你之后的下一個程序員是一個知道你住在哪里的殺人狂,你會安全得多!


免責聲明

這一切都在我的腦海中。雖然我推薦 PDO,但我既不使用 MySQL 也不使用 PDO,我的用法可能需要更正。


查看完整回答
反對 回復 2022-05-27
  • 2 回答
  • 0 關注
  • 193 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號