PHP form-Search script to search text file, find match

Hi, very new to PHP and think I’m on the right track with this.

  • From my index.php form, a user will enter their name, and a number associated to them, both in input boxes.
  • They will then select from a drop down list a course they want to take.
  • Once they hit the submit button I need to take their name to see if they are already enrolled and if the class is at it’s max capacity.
  • The student info is in student.txt ie Mike Wazowski:PX-68-524 (student name and number).
  • The course info is in course.txt ie Animation Film Design:AFD-250:6 (course name and number and max capacity).
  • The search will be in enrollment.txt ie Buzz Lightyear:PX-34-121:Visual Effects:VE-298.
  • The code I have is towards the bottom of the PHP and before the HTML starting with $datafile = ‘student.txt’;

Thank you.

My code:

<php>
ini_set('display_errors', 1); 
error_reporting(E_ALL); 

// Define and set variables 
$msg            = '';   
$submit         = isset($_POST['submit']) ? $_POST['submit'] : NULL;
$student        = ''; 
$studentname    = isset($_POST['studentname'])   ? $_POST['studentname']   : NULL; 
$studentnumber  = isset($_POST['studentnumber']) ? $_POST['studentnumber'] : NULL;
$coursefile     = 'course.txt'; 
$enrollfile      = 'enrollment.txt';
$in             = fopen ($coursefile, 'r') or die ("course.txt cannot be opened for reading."); 

// Sanitization and Validation coding 
if($submit) 
{
    $student        = ''; 
    $studentfile    = 'student.txt'; 
    $course         = isset($_POST['course']) ? $_POST['course'] : NULL;
    $coursename     = ''; 
    $coursenumber   = ''; 
    $coursemax      = 0;


if ($submit) 
{ 
    $studentname   = $_POST['studentname']; 
    $studentnumber = $_POST['studentnumber']; 
} 

if ($studentname) 
{
    $studentname = strip_tags ($_POST['studentname']); 
    $studentname = htmlentities ($_POST['studentname']);
    $studentname = trim($_POST['studentname']);

}

if ($studentnumber) 
{
    $studentnumber = strip_tags ($_POST['studentnumber']);
    $studentnumber = htmlentities ($_POST['studentnumber']);
    $studentnumber = trim($_POST['studentnumber']);  
}

if ($course) 
{
    $course = strip_tags ($_POST['course']);
    $course = htmlentities ($_POST['course']); 
}

// Validate student name/number against text file  
function validateStudent($studentName, $studentNumber) 
{ 
    $found = false; 
    $fh = fopen('student.txt', 'r'); 
        while(($line = fgetcsv($fh, null, ':')) != false) { 
        if(count($line) > 1)
        { 
            if($line[0] == $studentName and $line[1] == $studentNumber)
          { 
            $found = true; 
            break; 
          } 
        } 
     } 
    return $found; 
 } 

// Validate course name/number against text file 
function validateCourse($courseName, $courseNumber, $courseMax) 
{ 
    $found = false; 
    $fh = fopen('course.txt', 'r'); 
        while(($line = fgetcsv($fh, null, ':')) != false) { 
        if(count($line) > 1) { 
            if($line[0] == $courseName and $line[1] == $courseNumber and $line[2] == $courseMax) { 
            $found = true; 
            break; 
          } 
        } 
      } 
      return $found; 
    } 
}//endif submit




//$file_handle = fopen('enrollment.txt', "r");
    //while (!feof($file_handle))
//{
    //$line_of_text = fgets($file_handle);
    //echo $line_of_text . "<BR>";
//}

//fclose($file_handle);



//$file = 'course.txt';
//$FH = fopen ($file, 'r') or die ("$file cannot be opened for reading.");
//while ($line = fgets ($FH)) {
    //echo $line;
    //echo "<br>\n";
    //}
//fclose ($FH);    


//THIS IS THE CODE AND PROCESS IN QUESTION
$datafile = 'student.txt';
// If selection has been made, find a match

 if (isset ($_POST['studentname'])) {
    $student = htmlentities ($_POST['studentname']);
    $DB = fopen ($datafile, 'r') or die ("$datafile cannot be opened for reading.");
    $found = FALSE;
    while ($record = fgets ($DB) and ! $found) {
       $field = explode (":", htmlentities (trim ($record)));
       $found = $student === $field[0];
    }
    fclose ($DB);
    if ($found) {
       echo "<p>$field[0] $field[1]</p>\n";
    }
 }

$DB = fopen ($enrollfile, 'r') or die ("$enrollfile cannot be opened for reading.");
while ($record = fgets ($DB) ) {
    $field = explode (":", htmlentities (trim ($record)));
    echo "<option value=\"$field[1]\">$field[0] $field[1] $field[2]</option>\n";
 }
 fclose ($DB);
 

 
// ND
if( isset( $studentname, $studentnumber)) {
    $valid = validateStudent($studentname, $studentnumber);
    if($valid){
       $msg = '<p style="color: black; text-align: left; font-size: 15px; font-weight: bold;">Thank you.</p>';
    } else {
       $msg = '<p style="color: red; text-align: left; font-size: 15px; font-weight: bold;">**The information you have entered is not valid.  Please enter your information again.**</p>';
    }
} 



      
?> 
<html> 
<head> 
    <title>Registration Form</title> 
    <style> 
        body{background-color: #ffffe6; width:610px;} 
        h1 {color: #29a3a3;} 
        .inputbox {padding: 7px; border: #FF9966 1px solid; border-radius: 4px;} 
        .btn {padding: 10px; background-color: #29a3a3; border: solid 1px #FF9966; border-radius: 4px; color: #FFFFFF; font-weight: bolder; cursor: pointer;} 
    </style> 
</head> 
<body> 
<h1>Course Registration</h1> 
<form method="post" action="index.php"> 
    <fieldset><legend><strong>Student Information</strong></legend> 
        <dl> 
            <dt>Student Name:</dt> 
            <dd><input class="inputbox" name="studentname" type="text" id="studentname" value='<?php echo htmlentities($studentname) ?>' required autofocus placeholder="Please enter your first & last name using this format: Dash Parr" tabindex="10" size="50"></dd> 
            <br> 
            <br> 
            <dt>Student Number:</dt> 
            <dd><input class="inputbox" name="studentnumber" type="text" id="studentnumber" value='<?php echo htmlentities($studentnumber) ?>' required placeholder="Please enter using this format: PX-03-046" tabindex="20" size="50"></dd> 
            <br>
            <?php echo $msg; ?>
        </dl> 
        <br> 
    </fieldset> 
    <br> 
    <fieldset><legend><strong>Course Selection</strong></legend> 
        <br> 
        Select a Course:<select name="course" tabindex="30">\n"; 
            <option value="-1" >Available Courses...</option> 
                <?php 
                while(($fields = fgetcsv($in, null, ':')) != false) { 
                    if (count($fields) > 1) { 
                        echo " 
                            <option value=\"$fields[1]\">$fields[0] $fields[1]</option>"; 
                    } 
                } 
                ?> 
        </select> 
        <br> 
        <br> 
        <br> 
        <br> 
        <br> 
        <br> 
    </fieldset> 
    <div> 
        <p> 
            <input name="reset" type="reset" tabindex="40" value="Clear Form" class="btn"> 
            <input name="submit" type="submit" tabindex="50" value="Submit Form" class="btn"> 
        </p> 
    </div> 
</form> 
</body> 
</html>
</php>

Your code is looking good.

A couple of points which may be useful:

That’s a bad idea - you should make sure all errors are fixed - not suppressed.

The original script showed the following unhelpful error message on the screen if and only if the “fileName.txt” could not be opened:

die ( ‘fileName.txt’ ." cannot be opened for reading

I thought it was better to display the web-page with a more friendly error message.

There are always other methods that can be used, preferably try {…} catch{…}* which I thought was a bit complicated when just starting with PHP.

Have you any other suggestions for a PHP beginner?

Your idea on error reporting, although extremely popular among PHP folks, is completely wrong.

To make things straight you need to distinguish a developer from a site user. Most PHP users consider themselves the sole site users and thus their idea on error reporting.

Some flaws in your logic:

1. A friendly" error message.

die ( ‘fileName.txt’ ." cannot be opened for reading

Come on. A site user is not a developer. They have absolutely no idea what ‘fileName.txt’ is about and quite vague idea on what they have to do with opening it. There is nothing “friendly” in this message. If you look at the big sites error pages, you will see that they never show anything particular about the error, but just a generalized error page saying something like “The site is undergo a maintenance” or “Server error but we’re already working on it”, asking a user to come back later. This would be a friendly error message indeed.

2. Depriving the developer from the error message

At the same time you are leaving the developer without an explanation of the error source at all: first, they will just have no idea that the error occurred - mind they are not a user who is getting the error! And second - if they happen to be the user who is getting the error, they’ll unable to make any use of it, as you changed the error message to a meaningless one. There could be billions reasons for the file not to be opened - a wrong path, a permission problem, accidental file deletion, you name it. All these explanations that otherwise would have been reported you are simply throwing away.

Look, with your code you just spoiled the experience for both a developer and a site user.

3. Confusing error reporting with error handling

try {...} catch{...} is used to handle errors. While the question is error reporting. You may find this reading useful: The (im)proper use of try…catch.

OK I agree with all the points you made.

I was just trying to separate the PHP script (that no doubt has been copied and pasted) to highlight that the error message was bad user experience.

Error reporting is a minefield and the link you supplied did not have any reference to handling a fopen(…) failure.

I am intrigued as to how you would handle the fopen(…) failure. Perhaps re-setting error_reporting(0) and then reinstating the original error_reporting status? I cannot think of an easy solution without involving a vast amount of script whereas a simple @ does the job with a minimum amount of additional script.

Edit:

I just checked on the user manul:

PHP fopen

Yup, I forgot one more issue.

4. Do not confuse error reporting with displaying errors

Errors have to be always reported.

While the user experience on a live server is handled with single configuration setting,

display_errors=0

it will handle all errors, including fopen() problems. Without the need of putting a @ in every line. This setting will handle them all errors at once.

And if you want not just a white screen shown to the user, it’s better to set up an error page for the web-server (ErrorDocument for Apache and error_page for Nginx). If you have no access to the server config, then you can use set_error_handler() to show a custom error page to a user on a live site

Two actually :smile:

I am intrigued as to how you would handle the fopen(…) failure.

Did you check the edit to my previous post about what the PHP Manual suggested?

Edit
Off for a late lunch and hope someone can supply an ideal solution.

Yes, I did. this suggestion is apparently following the wrong practice I explained above. After all, php manual is written by the php users all the same. As I said above, the wrong idea on error reporting is shared by too many users. It is not an excuse for the wrong practice anyway.

Using @ for the fopen makes no sense. I thought my posts above explained it well.

2 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.