Прежде всего, позвольте мне сказать, что сохранение паролей в виде простого текста в файле .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
Summery
На самом деле это довольно беспорядок. Под этим я подразумеваю, что вы использовали 3 разных способа открыть и получить доступ к данным файла. Вы использовали строковую константу PHP в некоторых местах, но не во всех. У вас был какой-то случайный код, где вы устанавливали вещи задолго до того, как они вам понадобились, а в некоторых случаях они вам могли и не понадобиться, поэтому вы тратили ресурсы на их установку.
Пожалуйста, не принимайте критику усердно, поскольку я не пытаюсь обидеть. Просто указав места, вы можете улучшить поток кода и упростить вещи. Главное, не унывать, чтобы эффективно программировать, нужно иметь не совсем спокойное отношение и стремление к постоянному самосовершенствованию. Даже после 9 лет программирования на PHP я все еще узнаю что-то новое, я узнал (и написал библиотеку вокруг него) что-то новое всего 2 дня назад ...
Как я сказал в начале, и, честно говоря, база данных фактически уменьшит объем кода, который вам нужен. Вначале может быть пугающим использование базы данных, но вы поймете, что это проще, чем делать это. Например, вы проверяете уникальность, вы можете установить уникальность поля в базе данных, тогда вам никогда не придется беспокоиться о дубликатах, а только обнаруживать ошибки для них.
Я бы предложил посмотреть PDO
и подготовленные заявления password_hash
и password_verify
.
Последнее предупреждение: я не проверял ничего из этого, так что прости меня, если есть какие-либо опечатки ...
Надеюсь, это поможет.