Ajax 链接下拉菜单在 LIVE 服务器上 loading/working 不正确

Ajax chained dropdown not loading/working correctly on the LIVE server

我有一个国家、州和城市链接下拉列表,它根据国家加载州,并根据州加载城市。该代码在我的本地服务器上运行良好,但是当推送到实时服务器时,下拉菜单无法正常运行,例如在某些情况下它对所有 3 个都运行良好但在某些情况下它只是不加载任何内容并且在控制台中我我看到的是一个简单的错误,没有别的。

这是JS:

$(document).ready(function() {    
    var country_id = localStorage.getItem("select2CountryValue");
    var state_id = localStorage.getItem("select2StateValue");
    var page_load = true; //added this 

    // Triggering the deleteLocalStorage function in case the client is not 
    // created and the back button is clicked
    $('.del-ls').click(function() {
        deleteLocalStorage();
    });

    // This function is also called by PHP using script tags when the create
    // client form is successfully submitted
    function deleteLocalStorage() {
        var country_id = localStorage.getItem("select2CountryValue");
        var state_id = localStorage.getItem("select2StateValue");

        localStorage.removeItem('select2CountryValue');
        localStorage.removeItem('select2StateValue');
    }

    //$('.csc-select').select2(); 
    $('#country').select2({
        placeholder: 'Select Country'
    });

    $('#state').select2({
        placeholder: 'Select State/Region'
    });

    $('#city').select2({
        placeholder: 'Select City'
    });

    $('select[name="country"]').on('change',function() {
        var country_id= $(this).val();
        localStorage.setItem("select2CountryValue", country_id);
        if (country_id) {
            $.ajax({
                url: "/src/Pages/world/getStates.php",
                type: "GET",
                data: {'country_id':country_id},
                dataType: "json",
                success: function(data) {
                    console.log(data);
                    $('select[name="state"]').empty();
                    $('select[name="state"]').append('<option value="">Select State</option>');
                    $.each(JSON.parse(data), function(key,value) {
                        $('select[name="state"]').append('<option value="'+value.id+'">'+value.name+'</option>');
                    });
                    //check if the change is called on page load
                    if (page_load == true) {
                        $('#state').val(state_id).trigger('change'); //assign slected value after element option is added in dom
                        page_load = false; //adding this so that next time this doesn't get execute
                    }
                }
            });
        } else {
            $('select[name="state"]').empty();
       }
    });
    
    $('#country').val(country_id).trigger('change');

    $('select[name="state"]').on('change',function() {
        var country_id = $('#country').val();
        var state_id = $(this).val();
        localStorage.setItem("select2StateValue", state_id);
        if (state_id) {
            $.ajax({
                url: "/src/Pages/world/getCities.php",
                type: "GET",
                data: {'country_id': country_id, 'state_id': state_id},
                dataType: "json",
                success: function(data) {
                    console.log(data);
                    $('select[name="city"]').empty();
                    $('select[name="city"]').append('<option value="">Select City</option>');
                    $.each(JSON.parse(data),function(key,value) {
                        $('select[name="city"]').append('<option value="'+value.id+'">'+value.name+'</option>');
                    });
                }
            });
        } else {
            $('select[name="city"]').empty();
        }
    });
});

这是 HTML 和一些简单的 PHP 来加载工作正常的国家:

<p>
    <span>Country</span>
    <select class="csc-select" name="country" id="country">
        <option value="">Select Country</option>
        <?php foreach($countries as $country) { ?>
        <option value="<?php echo $country[$columnName['COLUMN_NAME']]; ?>"
        >
            <?php echo $country['name']; ?>
        </option>
        <?php } ?>
    </select>
</p>
<p>
    <span>State</span>
    <select class="csc-select" name="state" id="state">
        <option value="">Select State</option>
    </select>
</p>
<p>
    <span>City</span>
    <select class="csc-select" name="city" id="city">
        <option value="">Select City</option>
    </select>
</p>

我现在有点无能为力,因为它在本地运行良好,但在实时服务器上,它不适用于您选择的每个选项,我重新检查了国家、州和城市数据库,所有信息都在那里,所以它不是缺少,数据库与我在本地版本中使用的数据库相同。如果有人有任何想法或建议,我将不胜感激。

这是有时出现的控制台日志错误:

> Uncaught SyntaxError: Unexpected end of JSON input
>     at JSON.parse (<anonymous>)
>     at Object.success (add:977:29)
>     at c (jquery-3.6.0.min.js:2:28327)
>     at Object.fireWith [as resolveWith] (jquery-3.6.0.min.js:2:29072)
>     at l (jquery-3.6.0.min.js:2:79901)
>     at XMLHttpRequest.<anonymous> (jquery-3.6.0.min.js:2:82355)

现在我正在添加 console.log 的屏幕截图,当我选择美国国家/地区加利福尼亚州时会发生这种情况,因此它不会显示加利福尼亚州的任何内容,但它应该:

这里是 getStates.php 文件代码:

<?php 

use App\Session;
use App\Login;
use App\Location;

require_once("../../../vendor/autoload.php");

$objSession = new Session();
if(!$objSession->isLogged()) {
    Login::redirectTo("/login");
}

$country_id = $_GET['country_id'];

if(isset($_GET['country_id'])) {
    $objLocation = new Location();
    echo json_encode($getStates = $objLocation->getStates($country_id));
}

这里是 getCities.php 文件代码:

<?php 

use App\Session;
use App\Login;
use App\Location;

require_once("../../../vendor/autoload.php");

$objSession = new Session();
if(!$objSession->isLogged()) {
    Login::redirectTo("/login");
}

$state_id = $_GET['state_id'];
$country_id = $_GET['country_id'];

if(isset($_GET['state_id']) && isset($_GET['country_id'])) {
    $objLocation = new Location();
    echo json_encode($getCities = $objLocation->getCities($state_id, $country_id));
}

这是获取数据的位置 class 中的代码:

public function getStates(string $id): ?string
    {

        $sql = "SELECT `id`, `name` FROM {$this->table_3}
                WHERE `country_id` = '". $this->escape($id) ."'
                ORDER BY `name` ASC";
                $result = $this->fetchAll($sql);
                return json_encode($result);

    }

    public function getCities(string $state, string $country): bool|string
    {

        $sql = "SELECT `id`, `name` FROM {$this->table_4}
                WHERE `state_id` = '". $this->escape($state) ."'
                AND `country_id` = '". $this->escape($country) ."'
                ORDER BY `name` ASC";
                $result = $this->fetchAll($sql);
                return json_encode($result);

    }

您好,我认为这可能是 $.ajax 和 echo json_decode 问题....

我制作了自己的 AJAX 功能,并在 github https://github.com/jintor/stubajax

中分享
async function stubajax (divid,phphat,postix = [],pend = 'html') {

    var pcache = (Math.floor(Math.random() * 100000000) + 1);
    
    postix["preventcache"] = pcache; // prevent browser caching
    postix["divid"] = encodeURIComponent(divid);
    postix["mojax_height"] = encodeURIComponent($(window).height());
    postix["mojax_width"] = encodeURIComponent($(window).width());

    // if you need to send cookies
    postix["cookies"] = decodeURIComponent(document.cookie); 
    
    // if you need to send localStorage or sessionStorage stuff
    for (var i = 0; i < localStorage.length; i++){ postix[localStorage.key(i)] = localStorage.getItem(localStorage.key(i)); }
    for (var i = 0; i < sessionStorage.length; i++){ postix[sessionStorage.key(i)] = sessionStorage.getItem(sessionStorage.key(i)); }
        
    await fetch(phphat+"?pcache="+pcache, {
      method: "POST", body: JSON.stringify(Object.assign({}, postix)), headers: {"Content-type": "application/json; charset=UTF-8"}
    }).then( response => { return response.text(); }).then( html => { 
        switch ( pend ){
            case 'append' : $("#"+divid).append(html); break;
            case 'prepend' : $("#"+divid).prepend(html); break;
            default : $("#"+divid).html(html); break;
        }
    }).catch( err => console.log(err) );
      
}

你可以像这样使用它

<input onchange="stubajax (\'div_id_that_will_reseive_the_ajax_message\',\'/path/to_php.php\',{\'extra1\':this.value},'html');

PHP 方面: a 最后简单地回显 (WITHOUT json_encode).....

所以,我已经询问了评论并且你提供了......这是我认为正在发生的......以及我认为你应该做的事情。

您在 Location::class 上的方法 getCities 是 return 布尔值...有时是字符串...

json_encode 只会 return false 失败,这意味着 json_encode 编码你的 sql 结果失败...

您可以使用 json_last_error()json_last_error_msg() 来调试 json_encode() 问题

您可以找到文档 here

您可以在本地调试您的问题,但是,请确保您的本地计算机与实时服务器上的 运行 相同,以复制错误...

  1. PHP版本
  2. 数据库数据
  3. MySql版本(不过我觉得没必要)
  4. 浏览器(但仅用于测试,应用程序应适用于所有浏览器)

如果您无法重现错误,则需要现场重现。 (请小心,这应该是你最后的选择)

我无法提供具体答案,因为我不知道 $this->fetchAll() 是否只是 return 一个数组,或者有时它 return 是一个错误消息...

我已经为您提供了这个答案,因为您对这个问题的主要关注是为什么您的程序 returning 一个简单的 false 值...

for example in some cases it works fine for all 3 but for some cases it just does not load anything and in the console I am seeing a simple false and nothing else.

所以我添加了@SeanReyes 引导我找到的解决方案。

实际上它引导我找到了 2 个解决方案,它们是:

解决方案 1. 我可以简单地在我的 Location::class 中做一个 if 条件来检查 json_encode 是否正常工作,如果不正常,只需像这样添加一个 JSON 标志(JSON_INVALID_UTF8_IGNORE 或 JSON_INVALID_UTF8_SUBSTITUTE):

   public function getStates(string $id): ?string
    {

        $sql = "SELECT `id`, `name` FROM {$this->table_3}
                WHERE `country_id` = '". $this->escape($id) ."'
                ORDER BY `name` ASC";
                $result = $this->fetchAll($sql);
                if(json_encode($result)) {
                    return json_encode($result);
                } else {
                    return json_encode($result, JSON_INVALID_UTF8_IGNORE);
                }

    }

并对 getCities 方法执行相同的操作。

解决方案 2。虽然这确实解决了问题,但它显示的拉丁字符不正确,因此我找到了另一个简单的解决方案,只需向我的 mysqli 连接添加一个字符集,如下所示:

        $this->db->set_charset("utf8mb4");

就像魔法一样,一切都完美无缺,但这对我来说是一个新手错误,因为无论如何都应该设置它,感谢大家给我指明正确的方向。