AngularJS $http提交表单数据失败,PHP提示索引未定义求助
咱们来一步步拆解你遇到的核心问题,然后逐个解决:
1. $http请求的数据格式与PHP接收不兼容
你用$('#formProfil').serialize()生成了urlencoded格式的字符串,但AngularJS的$http服务默认会把data参数序列化为JSON,并且设置请求头Content-Type: application/json。而PHP的$_POST超全局变量只能解析application/x-www-form-urlencoded或multipart/form-data格式的请求体,所以自然拿不到你发送的数据,就会出现Undefined index的错误。
2. 表单序列化时机错误
你的config对象是在控制器初始化时就执行了serialize(),这时候Angular还没完成视图的数据绑定,表单里的{{loginProfil}}这些插值表达式还没替换成$scope里的实际值,所以序列化得到的是空的或者无效的字符串,发送过去自然没有正确的字段。
3. PHP代码中的SQL错误与安全风险
- 你执行
$rep = $db->query('SELECT id FROM utilisateur WHERE login='.$_SESSION['login']);后,$rep是一个PDOStatement对象,不是用户ID,直接把它拼到UPDATE语句里会导致SQL语法错误。 - 直接把
$_SESSION['login']拼到SQL语句里存在SQL注入风险,必须用预处理语句。
修复步骤
第一步:修正AngularJS的$http请求
不要用jQuery的serialize,而是直接用$scope里的变量构建请求数据,同时确保请求格式符合PHP的要求:
app.controller('ctrlProfil', function($scope, $http){ $scope.loginProfil = "<?= $_SESSION['login']?>"; $scope.mdpProfil = "<?= $_SESSION['mdp']?>"; $scope.emailProfil = "<?= $_SESSION['email']?>"; $scope.submit = function(){ // 直接用$scope的变量构建请求数据 var postData = { loginProfil: $scope.loginProfil, mdpProfil: $scope.mdpProfil, emailProfil: $scope.emailProfil }; $http({ method: 'POST', url: 'modifProfil.php', data: postData, // 设置正确的Content-Type,让PHP能解析到$_POST headers: {'Content-Type': 'application/x-www-form-urlencoded'}, // 把JSON数据转为urlencoded格式 transformRequest: function(obj) { var str = []; for(var p in obj) str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); return str.join("&"); } }).then(function(response){ console.log(response.data); }, function(error){ console.error('请求失败:', error); }); } });
或者更简单的方式:在PHP里直接读取原始请求体并解析JSON,这样AngularJS可以直接发送JSON数据,不用修改请求头:
// 在PHP文件开头添加这段代码,解析JSON格式的请求体 $postData = json_decode(file_get_contents('php://input'), true); // 之后用$postData['loginProfil']代替$_POST['loginProfil']
第二步:修正PHP的SQL逻辑与安全问题
session_start(); // 别忘了开启Session,否则$_SESSION无法获取值 try { $db = new PDO('mysql:host=localhost;dbname=monprojet;charset=UTF8', 'root', 'root'); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 开启错误模式,方便调试 } catch(Exception $e) { die('Erreur : '.$e->getMessage()); } // 用$_POST或上面的$postData获取参数,添加空值判断避免报错 $login = $_POST['loginProfil'] ?? ''; $mdp = $_POST['mdpProfil'] ?? ''; $email = $_POST['emailProfil'] ?? ''; // 用预处理语句查询用户ID,彻底避免SQL注入 $stmt = $db->prepare('SELECT id FROM utilisateur WHERE login = :login'); $stmt->execute([':login' => $_SESSION['login']]); $user = $stmt->fetch(PDO::FETCH_ASSOC); if($user) { // 同样用预处理语句执行更新操作 $updateStmt = $db->prepare('UPDATE utilisateur SET login= :login, mdp= :mdp, email= :email WHERE id = :id'); $updateStmt->execute([ ':login' => $login, ':mdp' => $mdp, ':email' => $email, ':id' => $user['id'] ]); // 返回成功信息(UPDATE语句没有结果集,不需要fetchAll) echo json_encode(['success' => true, 'message' => 'Profil mis à jour']); } else { echo json_encode(['success' => false, 'message' => 'Utilisateur non trouvé']); }
额外优化建议
尽量避免在AngularJS代码里混用jQuery,用Angular原生的ng-model做双向绑定更符合框架设计思想,还能简化代码:
<form id="formProfil" ng-submit="submit()"> <p><span>Bonjour </span><input type="text" name="loginProfil" ng-model="loginProfil"/></p> <p>Mon mot de passe: <input type="text" name="mdpProfil" ng-model="mdpProfil"/></p> <p> Email: <input type="email" name="emailProfil" ng-model="emailProfil"/></p> <input class="btn btn-primary" type="submit" value="Enregistrer"/> </form>
这样你不需要在控制器里手动赋值初始值,ng-model会自动把表单值同步到$scope里,初始值可以通过Angular服务或后端接口获取,代码更规范。
内容的提问来源于stack exchange,提问作者IZAD

