我在注册和登录显示(未定义的偏移量)方面都遇到了问题,请看注册我的代码是否存在问题?这是注册形式的问题,尽管我写了一个事实,有时它仍保存了现有的电子邮件一种不提交我的data.txt
内部现有电子邮件的功能。很快这些功能将无法正常工作
<?php
if(isset($_POST['submit_reg'])){
$var=file("data.txt");
$userData = $_POST['email'] . " " . $_POST['password'] . "\r\n";
$lines=0;
$db = fopen("data.txt", "a+");
foreach($var as $key=>$value){
$user = (explode(' ', $value));
if ($_POST["password"] === $_POST["confirm_password"]) {
//print_r($value);
if (trim($user[0]) == $_POST['email']) {
$lines++;
}
break;
}
}
if($lines){
echo "The email is already exists ";
}else{
fwrite($db,$userData."\r\n");
fclose($db);
echo "you are registered successfully ";
}
}
?>
这是我的登录表单,登录问题是出现错误的未定义偏移量12
<?php
if (isset($_POST['submit_log'])) {
$email =isset($_POST['email']);
$password =isset($_POST['password']);
$file = explode( PHP_EOL, file_get_contents( "data.txt" ));
$auth = false;
foreach( $file as $line ) {
list($email, $password) = explode(" ", $line);
if ($_POST['email'] == $email && $_POST['password'] == $password) {
$auth =true;
break;
}
}
if($auth) {
echo "Login successfull!";
} else {
echo "Invalid username or password";
}
}
?>
答案 0 :(得分:1)
首先让我说一下,将纯文本密码存储在.txt
文件中可能不是构建longin系统的最佳方法。 (无论如何都是免责声明)。
未定义的偏移量(仅是猜测)
那表示我看到了一些可以改善您的代码的地方。我对错误没有更多细节的猜测是,您可能在文件末尾拉出一个空数组,通常在末尾留下一个挂起的行(最后一行没有其他任何内容的新行)。一旦您在空间['']
上第二次爆炸它,它可能会变成类似这样的东西。然后,您尝试使用list
来访问它,这将为您提供未定义的偏移量。
您可以使用array_filter
并可能进行修整,而不是这样做:
$file = explode( PHP_EOL, file_get_contents( "data.txt" ));
您可以尝试(已经使用此功能时应该知道)
$file = file( "data.txt", FILE_SKIP_EMPTY_LINES|FILE_IGNORE_NEW_LINES ));
文件功能,获取一个文件,并根据行返回将其分成一个数组。因此,这取代了explode和file_get_contents。
然后它有2个(按位)标志,您可以使用:
数组文件(字符串 $ filename [,int $ flags = 0 [,资源 $ context ]] ])
将整个文件读入数组。
FILE_IGNORE_NEW_LINES
在每个数组元素的末尾省略换行符
FILE_SKIP_EMPTY_LINES
跳过空行
http://php.net/manual/en/function.file.php
这些代替了为空行过滤数据(您没有做的事情)。当然,这是您创建的文件,但您永远不知道何时会出现错误的行返回。
非唯一条目
if(isset($_POST['submit_reg'])){
$var=file("data.txt");
$userData = $_POST['email'] . " " . $_POST['password'] . "\r\n";
$lines=0;
$db = fopen("data.txt", "a+");
foreach($var as $key=>$value){
$user = (explode(' ', $value));
if ($_POST["password"] === $_POST["confirm_password"]) {
//NOTE: the uniqueness check only happens when the confirm password matches
if (trim($user[0]) == $_POST['email']) {
$lines++;
}
break;
}
}
if($lines){
echo "The email is already exists ";
}else{
//NOTE:yet you save it no matter if that is the case
fwrite($db,$userData."\r\n");
fclose($db);
echo "you are registered successfully ";
}
}
您的唯一性检查仅在确认密码与密码匹配时起作用,但是当需要保存数据时,将不进行检查。与其将检查添加到保存位周围,不如将整个内容包装在此确认测试中,因为在检查文件之前,这两项都是已知的:
在这里我为您做了一些修改
if(isset($_POST['submit_reg'])){
if ($_POST["password"] === $_POST["confirm_password"]) {
//VERIFY AND SANITIZE user input, if you put junk in you get junk out
$password = trim($_POST['password']);
//again use something better then die
if(empty($password))die('Password cannot be empty');
//because you split on space, you cannot allow it in inputs
if(preg_match('/\s+/', $password)) die('Password cannot contain spaces');
$email = trim($_POST['email']);
if(empty($email))die('Email cannot be empty');
//you may want to validate using something better
if(preg_match('/\s+/', $email )) die('Email cannot contain spaces');
//Use the flags
$var=file("data.txt", FILE_SKIP_EMPTY_LINES|FILE_IGNORE_NEW_LINES);
//for duplication we only care if there is 1 previous entry
//which is enough to say its a duplicate
$exists=false;
foreach($var as $key=>$value){
$user = explode(' ', $value);
if (trim($user[0]) == $email) {
//we found a match this is enough to call it a duplicate
$exists = true;
break;
}
}
if($exists){
echo "The email is already exists ";
}else{
file_put_contants("data.txt", $email." ".$password.PHP_EOL, FILE_APPEND);
echo "you are registered successfully ";
}
}else{
echo "Confirm password must match password";
}
}
其他内容
这些也不正确:
$email =isset($_POST['email']);
$password =isset($_POST['password']);
Isset返回一个布尔值,因此您要为这两个变量分配true
或false
。没关系,因为您从不检查它们,并且在循环中您可以通过调用list()
来覆盖它们。但是,仅仅因为“无关紧要”并不意味着它是正确的。
这些确实应该是这样的:
if(!isset($_POST['email']))
die("no email"); //dont use die but do some kind of error message
if(isset($_POST['password']))
die("no password"); //dont use die but do some kind of error message
摘要
真的是一团糟。我的意思是,您使用了3种不同的方式来打开和访问文件数据。您在某些地方(而非全部)使用了PHP行常量。您有一些乱七八糟的代码,在需要它们之前就已经进行了设置,在某些情况下,您可能不需要它们,因此浪费了资源来设置它们。
请不要用力批评,因为我不是要冒犯。只需指出位置,就可以改善代码流并简化事情。重要的是不要灰心,要有效地进行编程,您必须具有不屈不挠的态度和不断自我完善的动力。即使经过9年的PHP编程,我仍然一直在学习新知识,但我还是在两天前学习了新知识(并围绕它编写了一个库)...
正如我在一开始所说的,老实说,数据库实际上会减少所需的代码量。刚开始使用数据库可能令人生畏,但是您会发现这样做比以前更容易。一个示例是检查唯一性,您可以将一个字段在数据库中设置为唯一,这样您就不必担心重复项了,只需捕获错误即可。
我建议调查PDO
和准备好的语句password_hash
和password_verify
。
最后的警告是我没有测试任何一个,所以请原谅我有错别字...
希望有帮助。