【问题标题】:php, jquery and ajax - populating select dropdown based on previous selected valuephp、jquery 和 ajax - 根据先前选择的值填充选择下拉列表
【发布时间】:2016-11-21 16:06:17
【问题描述】:

有人告诉我我之前的帖子不是很清楚,所以我将尝试以不同的方式提问。

我正在编写一本 OOP 食谱书。目前,我正在努力添加食谱。为此,我正在显示测量的下拉列表,当用户选择测量时,我想显示另一个下拉列表,其中包含为该测量 ID 找到的单位。

mysql 上的表是measurement,有id 和name 列,units,有id,name 和measurement_id 列(measurement_id 是units 表的外键)。多个单位将属于一个测量。

为此,我创建了一个测量 php 对象/类。

在 new_recipe.php 中,我包含一个表单,其余列用于添加食谱,我将仅包含我现在正在处理的问题:

注意:在 measure.php 上,Measurement php 对象/类具有以下方法: - display_measurements() --> 只需从测量表中选择所有测量。 - get_units_for_measurement($measurement_id) --> 选择所有具有相同measurement_id 的单位。

public function display_measurements() {
      include 'includes/db_connection.php';   
          try {

      $sql = "SELECT id, name FROM measurements";

      $results = $conn->prepare($sql);
      $results->execute();
     } catch(PDOException $e) {
        echo 'Error: ' . $e->getMessage() . '<br />';
        return array();
    }
      return $results->fetchAll(PDO::FETCH_ASSOC);
    }


   public function get_units_for_measurement($measurement_id = ':measurement_id') {
       include 'includes/db_connection.php';

       try { 
           $sql = "SELECT measurements.id, units.id, units.name "
               . "FROM measurements "
               . "JOIN units "
               . "ON measurements.id=units.measurement_id WHERE measurements.id=:measurement_id";
           $result = $conn->prepare($sql);
           $result->bindParam(':measurement_id', $measurement_id, PDO::PARAM_INT);
           $result->execute(); 
        } catch(PDOException $e) {
        echo 'Error: ' . $e->getMessage() . '<br />';
        return array();
    }
    return $result->fetchAll(PDO::FETCH_ASSOC);
    }

 <form id="newRecipe" method="POST" action="new_recipe.php">   
(...)
     <div class="input_group">
         <label for="name" class="required">Name</label>
         <input name="name" type="text" value="" />
    </div>
    <div class="input_group">
         <label for="measurements" class="required">Measurements</label>  
         <select name="measurements" class="selectMeasurement">
             <option disabled selected value=""> -- select a measurement -- </option>
<?php
$measurements = $measurementObj->display_measurements();
foreach ($measurements as $measurement) {
    echo '<option value="' . $measurement['id'] . '" ';
    echo '>' . $measurement['name'] . '</option>';
}
?>
       </select>        
   </div>
   <div class="input_group">
       <label for="units" class="required">Units</label>
       <select id="selectUnit" name="units">
           <option disabled selected value=""> -- select a unit -- </option>
             <?php
             if (isset($_POST['measurements'])) {
                 die('ddddd');
                // $units = $measurementObj->get_units_for_measurement($_POST['measurements']);
            //     foreach ($units as $unit) {
            //         echo '<option value="' . $unit['id'] . '" ';
            //         echo '>' . $unit['name'] . '</option>';
            //     }
             }
             ?>
       </select> 
   </div>
   (...)
   <button class="submit" type="submit" name="submit">Submit</button>
</form>

您可以在表单中看到两个选择下拉菜单;第一个是我显示测量值的地方,下一个是我有一些注释行的地方,我应该“过滤”在第一个下拉列表中选择的measurement_id以显示所属单位。要做它不会重新加载页面,建议我使用 ajax(我不太熟悉)。这个 ajax 调用一个 js 文件,链接到项目的页脚:

$(document).ready(function() {
    $('#newRecipe').on('change','.selectMeasurement', function(){
      var selectedMeasurementId = this.value;
        $.ajax({
            method: 'POST',
            url: 'classes/measurement.php',
            data: selectedMeasurementId
        });
        return true;
    });   
});    


$(文档).ready(函数() { $('#newRecipe').on('change','.selectMeasurement', function(){ var selectedMeasurementId = this.value; $.ajax({ 方法:'POST', url: 'classes/measurement.php', 数据:selectedMeasurementId, 成功:函数(){ 警报(selectedMeasurementId); } }); });
});

在js文件中,我想到的是关于成功,调用方法对象:

成功:$measurementObj->get_units_for_measurement($_POST['measurements']),我知道,如果我有 ajax 响应,我想获取给定测量的单位,但是,我不能调用PHP 对象在这里。

另外,我尝试在设置测量值时做一些事情。在选择我尝试做的测量之后:

 if (isset($_POST['measurements'])) {
  //then $measurementObbj->get_units_for_measurement|($_POST['measurements']), but it seems it does not "detect" the measurements has been set. 
}

所以我的问题是....我如何执行这个 $measurementObj->get_units_for_measurement(measurement_id selected in the first dropdown),以使 ajax 请求成功?

我希望现在更清楚一点。 谢谢

【问题讨论】:

  • 嗯.. 只是理解你的问题很令人困惑。
  • 你有一些混合在一起的东西。首先你在这个文件中有什么:classes/measurement.php?是_测量类_还是负责获取ajax请求并发回ajax请求的数据的文件?
  • ohm.... 它是 _measurement 类。我应该以其他方式重命名文件吗?我实际上是在寻找用大写来命名文件是否很常见,作为类,但我没有找到任何东西,所以我只是用类名命名。目前,负责 ajax 请求的文件位于页脚 ^^

标签: php mysql ajax


【解决方案1】:

免责声明:这只是一个粗略且未经测试的草图。

正如您提到的 OOP,我将首先重构您访问数据库的方式,使其更加面向对象。我将使用 DAO 模式的简化版本。如果您关注certain conventions,它将非常易于使用。这种模式几乎没有缺点,但在大多数情况下,它使您的代码更有条理。

首先,我将创建两个类MeasurementDAOUnitDAO,它们将分别用于访问每个表的数据。 (如果对你更方便,你可以只使用一个类。)

类/MeasurementDAO.php

class MeasurementDAO
{
    protected $conn;

    public function __construct(PDO $conn) {
        $this->conn = $conn;
    }

    public function getMeasurements() {
        try {
            // no need to use prepare() if you are not using any placeholders e.g. :name or ?
            // query() and prepare() do not return results, but a (st)atement (h)andler
            $sth = $this->conn->query("SELECT id, name FROM measurements");
            return $sth->fetchAll(PDO::FETCH_OBJ);
        } catch (PDOException $e) {
            echo 'Error: ' . $e->getMessage() . '<br />';
        }
    }
}

classes/UnitDAO.php

class UnitDAO
{
    protected $conn;

    public function __construct(PDO $conn) {
        $this->conn = $conn;
    }

    public function getUnitsByMeasurement($measurementId) {
        try { 
            // if I am not mistaken, this query should be shorter and equivalent to your initial one
            $sth = $this->conn->prepare("SELECT * FROM units WHERE measurement_id = ?");
            // I have never seen any reason to use bindParam() as you can just pass your values in execute()
            $sth->execute(array($measurementId));
            return $sth->fetchAll(PDO::FETCH_OBJ);
        } catch (PDOException $e) {
            echo 'Error: ' . $e->getMessage() . '<br />';
        }
    }
}

(您可能还需要一个 RecipeDAO.php,其中包含 getRecipes()addRecipe($recipe)updateRecipe($recipe)deleteRecipe($id) 等方法。)

接下来,当您向脚本发出 AJAX 请求时,您不想直接调用该类。相反,您想调用一个使用该类的脚本。

ajaxHandler.php

// this will hold the data to be sent back as our response
$res = array();
// initialize connection
$conn = new PDO(/*...*/);
// determine what action to take
if ($_GET['action'] === 'get_units') {
    // get units
    $res['units'] = (new UnitDAO($conn))->getUnitsByMeasurement($_GET['measurement']);
}
header('Content-Type: application/json');
// last line: send response (it should be the only thing that gets outputted)
echo json_encode($res);

你可以从你的 JavaScript 调用脚本,例如: ajaxHandler.php?action=get_units&amp;measurement=123.

接下来,我们将使用我们的新方法进行测量。 (我个人觉得一开始就做所有数据库的东西更好、更干净——而不是在输出 HTML 时这样做。)

new_recipe.php

<?php
// initialize connection
$conn = new PDO(/*...*/);
// get measurements
$measurements = (new MeasurementDAO($conn))->getMeasurements();
?>

<form id="newRecipe" method="POST" action="new_recipe.php">
    <!-- etc -->
    <div class="input_group">
        <!-- sidenote: label's FOR attribute attaches itself to the inputs's ID attribute, not NAME attribute --> 
        <label for="measurements" class="required">Measurements</label>  
        <select name="measurements" class="selectMeasurement">
            <option disabled selected value=""> -- select a measurement -- </option>
            <?php if ($measurements) : ?>
                <?php foreach ($measurements as $measurement) : ?>
                    <option value="<?php echo $measurement->id ?>"><?php echo $measurement->name ?></option>
                <?php endforeach ?>
            <?php endif ?>
        </select>
    </div>
    <div class="input_group">
        <label for="units" class="required">Units</label>
        <select name="units" id="selectUnit">
            <option disabled selected value=""> -- select a unit -- </option>
        </select> 
    </div>
    <!-- etc -->
</form>

最后,让我们调用 ajax 处理脚本并构建选项列表。

// shorter syntax for $(document).ready
$(function() {
    $('#newRecipe').on('change', '[name=measurements]', function () {
        console.log('send request with ', this.value);
        // we'll use a $.getJSON() which is a shortened version of $.ajax() 
        // make a GET request to ajaxHandler.php?action=get_units&measurement={this.value}
        $.getJSON('ajaxHandler.php', { action: 'get_units', measurement: this.value }, function (res) {
            console.log('got response', res);
            var html = '';
            // build list of options if any
            if (!$.isEmptyObject(res.units)) {
                $.each(res.units, function (unit) {
                    html += '<option>' + unit.name + '</option>';
                });
            }
            // set list of options
            $('[name=units]').html(html);
        });
    });   
});

应该是这样的。您需要添加缺少的部分,例如包含 PHP 文件。

(如果您想保留当前设置,只需遵循 ajaxHandler.php 中的所有内容并进行必要的调整。)

【讨论】:

    猜你喜欢
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-08
    • 1970-01-01
    • 2011-09-15
    • 2011-11-05
    相关资源
    最近更新 更多