WooCommerce购物车图标切换代码报错求助:get_cart()调用空对象
问题背景
几年前在WordPress站点添加代码,实现商品加入购物车后将购物车图标切换为勾选图标,当时运行正常。近期站点出现严重错误,经排查定位到该代码,怀疑是WooCommerce版本更新引发的问题。
错误信息
Fatal error: Uncaught Error: Call to a member function get_cart() on null in /home/modjargo/public_html/wp-content/themes/ModjajiBooks/functions.php:159 Stack trace: #0 /home/modjargo/public_html/wp-content/themes/ModjajiBooks/functions.php(169): change_button_text(237520, '') #1 /home/modjargo/public_html/wp-includes/class-wp-hook.php(307): change_ajax_add_to_cart_button_text('', Object(WC_Product_Simple)) #2 /home/modjargo/public_html/wp-includes/plugin.php(191): WP_Hook->apply_filters('', Array) #3 /home/modjargo/public_html/wp-content/plugins/woocommerce/includes/class-wc-product-simple.php(62): apply_filters('woocommerce_pro...', 'Add to basket', Object(WC_Product_Simple)) #4 /home/modjargo/public_html/wp-content/plugins/woocommerce/templates/loop/add-to-cart.php(32): WC_Product_Simple->add_to_cart_text() #5 /home/modjargo/public_html/wp-content/plugins/woocommerce/includes/wc-core-functions.php(345): include('/home/modjargo/...') #6 /home/modjargo/public_html/wp-content/plugins/woocommerce/in in /home/modjargo/public_html/wp-content/themes/ModjajiBooks/functions.php on line 159
There has been a critical error on this website. Please check your site admin email inbox for instructions.
报错代码
function change_button_text( $product_id, $button_text ) { foreach( WC()->cart->get_cart() as $item ) { if( $product_id === $item['product_id'] ) { return __('N', 'woocommerce'); } } return $button_text; } add_filter( 'woocommerce_product_add_to_cart_text', 'change_ajax_add_to_cart_button_text', 10, 2 ); function change_ajax_add_to_cart_button_text( $button_text, $product ) { if ( $product->is_type('simple') ) { $button_text = change_button_text( $product->get_id(), $button_text ); } return $button_text; }
问题根源
错误核心是WC()->cart返回了null,直接调用get_cart()触发致命错误。在WooCommerce新版本中:
WC()->cart并非在所有场景下都能初始化,比如页面加载早期、后台预览、静态生成等非活跃用户会话场景- 原代码未做任何前置判断,强行调用购物车对象的方法,导致报错
修复代码
修改change_button_text函数,先验证购物车对象的可用性:
function change_button_text( $product_id, $button_text ) { // 先检查购物车对象是否存在且具备get_cart方法 if ( ! WC()->cart || ! method_exists( WC()->cart, 'get_cart' ) ) { return $button_text; } foreach( WC()->cart->get_cart() as $item ) { if( $product_id === $item['product_id'] ) { return __('N', 'woocommerce'); } } return $button_text; } add_filter( 'woocommerce_product_add_to_cart_text', 'change_ajax_add_to_cart_button_text', 10, 2 ); function change_ajax_add_to_cart_button_text( $button_text, $product ) { if ( $product->is_type('simple') ) { $button_text = change_button_text( $product->get_id(), $button_text ); } return $button_text; }
优化建议
- 若站点仅允许登录用户购物,可增加
is_user_logged_in()判断,进一步缩小逻辑执行范围 - 考虑改用
woocommerce_cart_item_added钩子来标记已加入购物车的商品,避免每次渲染按钮都遍历购物车,提升页面性能
内容的提问来源于stack exchange,提问作者RexTheRunt

