SESSION变量刷新后值异常,移动端导航栏加载错误求助
视口识别导航加载异常问题排查
我正在开发一个视口识别功能,逻辑如下:用户首次访问网站时,通过检测屏幕宽度判断设备类型(≤768px为移动端,否则为PC端),将数据存入带隐藏输入框的表单,再通过fetch把FormData提交到PHP文件。PHP文件需要完成:
- 通过POST获取表单数据
- 处理首次加载标识与移动端标识数据
- 将数据存入SESSION变量
- 转换为JSON格式返回
前端JS接收JSON后设置对应文本框的值,但目前导航栏出现异常:首次加载无导航栏,刷新后无论设备类型均显示移动端导航栏。
相关代码
前端代码
<?php session_start(); ?> <script> window.addEventListener("load", async function(){ if (typeof isMobileJSVar == "undefined" || isMobileJSVar == null){ function determineIfIsMobile(){ let screenWidth = screen.width; let isMobileDevice; //避免重复提交表单弹窗 if ( window.history.replaceState ) { window.history.replaceState( null, null, window.location.href ); } //判断视口宽度 switch(screenWidth){ case (screenWidth <= 768) : isMobileDevice = true; return isMobileDevice; break; case (screenWidth > 768) : isMobileDevice = false; return isMobileDevice; break; default : isMobileDevice = false; return isMobileDevice; break; } } //初始化元素 let isSubmitted = false; let isMobileHelperURL = "./wp-content/themes/almondotheme/template_parts/outsourcedPHP/isMobileHelper.php"; let isMobileMiddleManTextElement = document.getElementById("isMobileMiddleManText"); let isFirstLoadHelperELement = document.getElementById("isFirstLoadHelper"); let mobileMiddleManFormElement = document.getElementById("mobileMiddleManForm"); let isUserMobile = determineIfIsMobile(); //通过Fetch与PHP通信 function isMobile(){ isMobileMiddleManTextElement.value = isUserMobile; fetch(isMobileHelperURL,{ method: 'POST', body: new FormData(document.getElementById('mobileMiddleManForm')), }) .then(returnedisMobileJSON=>{ return returnedisMobileJSON.json(); }) .then(parsedisMobileJSON=>{ var setHelperInputsFunction= function() { document.getElementById("isFirstLoadHelper").value = parsedisMobileJSON.isFirstLoad; document.getElementById("isMobileMiddleManText").value = parsedisMobileJSON.isMobile; }() }) let isFirstLoadJSVar = document.getElementById("isFirstLoadHelper").value; let isMobileJSVar = document.getElementById("isMobileMiddleManText").value; alert(isMobileJSVar); }; isMobile(); } }) </script>
PHP处理文件代码
<?php session_start(); $isMobileArray = array(); if(isset($_SESSION["isFirstLoad"])){ $_SESSION["isFirstLoad"] = false; $isMobileArray["isFirstLoad"] = $_SESSION["isFirstLoad"]; } else{ $_SESSION["isFirstLoad"] = true; $isMobileArray["isFirstLoad"] = $_SESSION["isFirstLoad"]; } if(!(isset($isMobileArray["isMobile"]))){ $_SESSION["isMobile"] = $_POST["isMobileMiddleManText"]; $isMobileArray["isMobile"] = $_POST["isMobileMiddleManText"]; } else{ $_SESSION["isMobile"] = $_POST["isMobileMiddleManText"]; $isMobileArray["isMobile"] = $_POST["isMobileMiddleManText"]; } $JSONToReturn = json_encode($isMobileArray); echo $JSONToReturn; ?>
导航栏代码
<?php //检查是否为移动设备 if(isset($_SESSION["isMobile"])){ if ($_SESSION["isMobile"] == true){ get_template_part("./template_parts/navigation_mobile"); } else{ get_template_part("./template_parts/navbar_pc.php"); } } else{ get_template_part("./template_parts/navbar_pc.php"); } ?>
问题根源与修复方案
1. 前端设备判断逻辑错误
原代码用switch做范围判断是错误的(switch是严格值匹配,不是条件判断),导致永远走default分支返回false。替换为if-else:
function determineIfIsMobile(){ let screenWidth = screen.width; //避免重复提交表单弹窗 if ( window.history.replaceState ) { window.history.replaceState( null, null, window.location.href ); } return screenWidth <= 768; }
2. PHP类型比较逻辑错误
PHP中字符串"false"与true用==比较时会被转换为布尔值true(非空字符串均为true),导致无论提交什么值都加载移动端导航。修复方式:
- 转换POST值为布尔类型再存入SESSION
- 用严格比较
===判断值
修改PHP处理文件:
<?php session_start(); $isMobileArray = []; //处理首次加载标识 if(isset($_SESSION["isFirstLoad"])){ $_SESSION["isFirstLoad"] = false; } else { $_SESSION["isFirstLoad"] = true; } $isMobileArray["isFirstLoad"] = $_SESSION["isFirstLoad"]; //处理移动端标识:转换为布尔类型 $isMobile = filter_input(INPUT_POST, 'isMobileMiddleManText', FILTER_VALIDATE_BOOLEAN); $_SESSION["isMobile"] = $isMobile; $isMobileArray["isMobile"] = $isMobile; echo json_encode($isMobileArray); ?>
修改导航栏代码的判断:
if ($_SESSION["isMobile"] === true){ get_template_part("./template_parts/navigation_mobile"); }
3. 前端异步回调的变量赋值问题
原代码中isFirstLoadJSVar和isMobileJSVar在fetch回调外定义,此时请求未完成,无法获取最新值,需移至回调内部:
function isMobile(){ isMobileMiddleManTextElement.value = isUserMobile; fetch(isMobileHelperURL,{ method: 'POST', body: new FormData(document.getElementById('mobileMiddleManForm')), }) .then(returnedisMobileJSON => returnedisMobileJSON.json()) .then(parsedisMobileJSON => { document.getElementById("isFirstLoadHelper").value = parsedisMobileJSON.isFirstLoad; document.getElementById("isMobileMiddleManText").value = parsedisMobileJSON.isMobile; //变量赋值移至回调内,确保拿到最新值 let isFirstLoadJSVar = document.getElementById("isFirstLoadHelper").value; let isMobileJSVar = document.getElementById("isMobileMiddleManText").value; alert(isMobileJSVar); }) };
4. 首次加载SESSION未设置问题
前端fetch是异步操作,首次页面渲染时SESSION还未被设置,可通过两种方式优化:
- 用PHP的
$_SERVER['HTTP_USER_AGENT']做设备判断作为兜底,首次加载直接渲染对应导航 - 前端页面加载后先通过JS动态渲染导航,再通过
fetch更新SESSION供后续刷新使用
内容的提问来源于stack exchange,提问作者Alwin Schneider
相关产品推荐
相关产品推荐

