PHP7迁移至PHP8问题:购物车对象构造函数未调用
问题描述
要将线上运营的电商网站从PHP 7.x版本迁移至PHP 8.x版本,本地使用XAMPP 7.4.3和8.1.6分别测试。PHP 8环境下网站主功能看似正常,但basket对象无法正常初始化——PHP 7中可以正常输出$cartid变量,PHP 8中无法输出该变量。
相关代码片段
basket.php
... include ("sqlcart.php"); $cart = new basket; ...
sqlcart.php
class basket { var $items; var $empty; var $cartid; var $voucher_id_set; function basket() { global $cartid; global $vat_rate; global $voucher_id_set; global $outmail; global $conn; global $_COOKIE; global $_POST; $voucher_id_set = 0; $number = 0; if (isset($_COOKIE["cart_id"])) { $cartid = ClearString(substr($_COOKIE["cart_id"], 0, 10)); $testcartid = $cartid; settype($testcartid, "integer"); if ($testcartid > 0) { $strsql = "SELECT * from g_tempbasket where basket_id = '" . clearstring(substr($cartid, 0, 10)) . "'"; $result = safedb_query($strsql); $number = mysqli_num_rows($result); } else { $number = 0; } } else { // force cart creation $number = 0; } if ($number == 0) { $todaydate = date("Y-m-d h:i:s"); $strsql = "INSERT INTO g_tempbasket (basket_id,date) "; $strsql .= "VALUES (NULL,'$todaydate')"; safedb_query($strsql); $newcartid = mysqli_insert_id($conn); if ($outmail == 1) { setcookie("cart_id", $newcartid, time() + (24 * 3600), "", ".website.co.uk", 1); setcookie("voucher_id", "", 0, "", ".website.co.uk", 1); } else { setcookie("cart_id", $newcartid, time() + (24 * 3600)); setcookie("voucher_id", "", 0); } $cartid = $newcartid; } $strsql = "SELECT t.product_id, p.descript, p.cost, t.qty "; $strsql .= "FROM g_tempbasket AS tb, g_product AS p, g_tempitems AS t "; $strsql .= "WHERE tb.basket_id = t.basket_id "; $strsql .= "AND t.product_id = p.product_id "; $strsql .= "AND tb.basket_id = " . $cartid; $result = safedb_query($strsql); $number = mysqli_num_rows($result); mysqli_free_result($result); //$this->items=$result; if ($number != 0) { $this->empty = false; } else { $this->empty = true; } } //function function additem($id, $name, $addcount) { global $cartid; // Get product info to add $strsql = "SELECT descript, cost, no_vat FROM g_product "; $strsql .= "WHERE product_id = '" . $id . "'"; $prodaddresult = safedb_query($strsql); $prodaddrow = mysqli_fetch_assoc($prodaddresult); $prodname = $prodaddrow["descript"]; $prodcost = $prodaddrow["cost"]; $prodnovat = $prodaddrow["no_vat"]; $strsql = "SELECT qty FROM g_tempitems "; $strsql .= "WHERE basket_id = " . $cartid; $strsql .= " AND product_id = '" . $id . "'"; $result = safedb_query($strsql); $number = mysqli_num_rows($result); $strsqls = "SELECT prod_code FROM g_ship_options "; $strsqls .= "WHERE prod_code = '" . $id . "'"; $sresult = safedb_query($strsqls); $snumber = mysqli_num_rows($sresult); if ($number == 0) { if ($id == "" || $addcount < 1) { // Basic anti-bot validation header("Location: index.php"); exit; } if ($snumber != 0) { // Item is shipping - mark in basket $strsql = "INSERT INTO g_tempitems "; $strsql .= "(basket_id, product_id, qty, shipping, descript, cost, no_vat) "; $strsql .= "VALUES (" . $cartid . ", '" . $id . "', " . $addcount . ", 1, '" . $prodname . "', '" . $prodcost . "', '" . $prodnovat . "')"; } else { // Non-shipping item $strsql = "INSERT INTO g_tempitems "; $strsql .= "(basket_id, product_id, qty, shipping, descript, cost, no_vat) "; $strsql .= "VALUES (" . $cartid . ", '" . $id . "', " . $addcount . ", 0, '" . $prodname . "', '" . $prodcost . "', '" . $prodnovat . "')"; } } else { if ($id == "") { // Basic anti-bot validation header("Location: index.php"); exit; } $currow = mysqli_fetch_assoc($result); $current = $currow["qty"]; $new = $current + $addcount; if ($new <= 0) { $new = 1; } $strsql = "UPDATE g_tempitems "; $strsql .= "SET qty = " . $new . ", "; $strsql .= "descript = '" . $prodname . "', "; $strsql .= "cost = " . $prodcost . ", "; $strsql .= "no_vat = " . $prodnovat . " "; $strsql .= "WHERE basket_id = " . $cartid . " "; $strsql .= "AND product_id = '" . $id . "'"; } mysqli_free_result($result); safedb_query($strsql); $this->empty = false; } }
原因与解决方法
问题核心是PHP 8.x彻底废弃了旧式构造函数(即与类同名的函数作为构造函数)。PHP 7.x中该写法已标记为过时但仍可运行,到PHP 8.x中,它会被当作普通方法,不会在实例化对象时自动执行。
你的basket类里的function basket()就是旧式构造函数,PHP 8下实例化new basket时不会调用这个方法,导致里面的$cartid初始化逻辑完全未执行,自然无法输出变量值。
修复方法:将旧式构造函数改为PHP标准的__construct()方法,原有逻辑保持不变:
class basket { var $items; var $empty; var $cartid; var $voucher_id_set; // 替换原有的function basket() function __construct() { global $cartid; global $vat_rate; global $voucher_id_set; global $outmail; global $conn; global $_COOKIE; global $_POST; // 原有的初始化逻辑全部保留 $voucher_id_set = 0; $number = 0; // ... 后续代码不变 } // 其他方法保持不变 }
额外注意事项:
- 代码中同时出现
ClearString和clearstring,PHP对函数名大小写不敏感,但统一写法更规范 - 当前SQL语句使用字符串拼接构建,存在注入风险,建议尽快改用预处理语句
内容的提问来源于stack exchange,提问作者Mike West
相关产品推荐
相关产品推荐

