I am trying to write a program in which the user will type a word into a search bar, submit it, and the program will search the contents of an array of files for that word and echo the contents of the files that contain the word into a text area. This is my code so far.

<!DOCTYPE html>
<html>

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<link rel="stylesheet" type="text/css" href="style.css"> 
<title>Untitled 1</title>
</head>

<body>
<header>
    <img src="search-star-jpg-1.jpg" alt="SearchStar Logo" />
</header>
    <form action="" method="post">
    <div>
        <input type="text" name="search" size="25" />
        <input type="submit" name="submit" value="Search" onclick="checkFiles()"/>
    </div>
    </form>
<?php
$matchedFiles = 0;
$files = scandir("files"); 
$filesContain = array();
$exclusion = file_get_contents("exclusion/exclusion.txt");

function checkFiles() {
    extract($_POST);
    $word = $search;
    global $filesContain;
    global $files;
    global $matchedFiles;
        for ($i = 0; $i < count($files); $i++) {
            $temp = file_get_contents($files[i]);
            if (strpos($temp, $word !== false)) {
                $filesContain[$matchedFiles] = $files[i];
                $matchedFiles++;
            }
        }
}

function fileContent() {
    global $word;
    global $filesContain;
    global $files;
        if (isset($word)) {
            ini_set('fastcgi.impersonate', 1); 
            readfile($filesContain[0]);
        }
}
?>
    <form>
        <textarea rows="30" cols="100"><?php echo fileContent(); ?></textarea>
    </form>
</body>

</html>

Now what I can't figure out is how to get the word from the search bar. Right now, I'm trying to use a form to post the word to the same page, then extract the word from post and use it. However, when I type something in and submit it, nothing happens. I currently have it set to call the checkFiles() function on the click of the submit button, but I suspect this is the problem since whenever I have tried to echo the $word variable, I have gotten an uninitialized variable error, both before submitting a word, and afterward. But I don't know how else to call this function after submitting a word. Any help would be much appreciated.

Recommended Answers

All 16 Replies

Well first off, you should put all php functions before html. Second, you didn't define an action in your form. Third, the "onclick" attached to your submit button makes a call to a javascript function, not a php function.

On line 44, you have global $word; but have not actually defined $word globally. Also, checkFiles() is never being called. I noticed you have on line 17 onclick="checkfiles()" which is an attempt to call a Javascript function checkFiles(), NOT the PHP function.

Defining action as empty was based on an online example that was somewhat similar to what I was doing. So I take it that was wrong.

So if the onClick attribute only accepts JavaScript functions, the how can I call a php function when the form is submitted. Does all php code execute when a php page is submitted? Because although the word is now being accepted into the variable, none of the rest of the code appears to execute. Here is my updated code.

<?php
$matchedFiles = 0;
$files = scandir("files"); 
$filesContain = array();
$exclusion = file_get_contents("exclusion/exclusion.txt");
extract($_POST);
$word = $search;

function checkFiles() {
    global $filesContain;
    global $files;
    global $matchedFiles;
        for ($i = 0; $i < count($files); $i++) {
            $temp = file_get_contents($files[i]);
            if (strpos($temp, $word !== false)) {
                array_push($filesContain, $files[i]);
                $matchedFiles++;
            }
        }
}

function fileContent() {
    global $word;
    global $filesContain;
    global $files;
        if (isset($word)) {
            ini_set('fastcgi.impersonate', 1); 
            readfile($filesContain[0]);
        }
}
?>

<!DOCTYPE html>
<html>

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<link rel="stylesheet" type="text/css" href="style.css"> 
<title>Untitled 1</title>
</head>

<body>
<header>
    <img src="search-star-jpg-1.jpg" alt="SearchStar Logo" />
</header>
    <form action="index.php" method="post">
    <div>
        <input type="text" name="search" size="25" />
        <input type="submit" name="submit" value="Search" />
    </div>
    </form>
    <div>
        <textarea rows="30" cols="100"><?php echo fileContent(); ?></textarea>
    </div>
</body>

</html>

PHP is a server side language, so YES, all PHP code is processed first when a page is loaded before HTML. I'll try my best to help you rewrite the code, but there are many mistakes and many changes that need to be made. For starters, when you echo a function like on line 53:

<textarea rows="30" cols="100"><?php echo fileContent(); ?></textarea>

you have to have the function return some data like this:

function fileContent() {
    global $word;
    global $filesContain;
    global $files;
    if (isset($word)) {
        ini_set('fastcgi.impersonate', 1);
        readfile($filesContain[0]);
    }
    return $whatever_the_data_is_you_want_to_return;
}

Second, try to avoid using global variables in functions. Instead, supply the variables to the function like this:

function fileContent($word, $filesContain, $files) {
}

echo fileContent('some_text', 'text', 'files')

In the "fileContent" function, you should define the files in the function instead of outside the function.

What is the purpose of the $matchedFiles variable?

I see no need to extract the $_POST data because you only have one piece of data you need from it, so call that data like this:

$word = $_POST['search'];

I hope this is all a good starting point, but more will need to be done to fix this code.

PHP is executed server side so you can't directly call a function from the client side. The simple solution in your case is not to use functions or if you must define them as functions, make sure to call them. I can see many basic errors in your code so I would recommend going slowly through tutorials and perhaps getting a book to guide you through it. With regards to your code above, I would recommend starting with something like this:

<?php

// Only proceed if the form has been submitted.
if (isset($_POST["submit"])) 
{
    $word = $_POST["word"];

    // Do something with $word here
}

?>
commented: I agree. No functions are necessary. +1

If I understand correctly what you are trying to do, this is what I've come up with:

<?php
if (isset($_POST)) {
    $files = scandir("files");
    $exclusion = file_get_contents("exclusion/exclusion.txt");
    $word = $_POST['search'];
    $result = "";
    foreach ($files as $file) {
        $temp = file_get_contents($file);
        if (strpos($temp, $word)) {
            $result .= $temp;
        }
    }
}
?>
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<link rel="stylesheet" type="text/css" href="style.css">
<title>Untitled 1</title>
</head>
<body>
    <header>
        <img src="search-star-jpg-1.jpg" alt="SearchStar Logo" />
    </header>
    <form action="index.php" method="post">
        <div>
            <input type="text" name="search" size="25" />
            <input type="submit" name="submit" value="Search" />
        </div>
    </form>
    <div>
        <textarea rows="30" cols="100"><?php echo $result ?></textarea>
    </div>
</body>
</html>

You were making it more complicated then it had to be. Plus, you never defined what the exclusion was supposed to do, so it's still just sitting there.

I was doing a lot of set up for later. The final goal is for the user to be able to enter a word, and every text file containing that word would be returned, but only one would be displayed in the text area at a time. So there would also have to be a function to cycle through the results (both back and forth) and it would cycle through the array of results. Exclusion was intended to be a bunch of words that the search engine would ignore as the words are so common, they would likely cause every document to be returned. matchedFiles was intended to contain a count of how many results there were so I could know what the maximum result that could be cycled though was.

My plan was to create two arrays. One that holds all the files, and one that holds the files that the word is found in. Then I would create functions (using JavaScript) that allowed for changing which result was displayed. I think my plan is good it's just the execution that I am failing on.

On a side note I tried the code you supplied and I get the following error when it tries to get the files.

Warning: file_get_contents(.): failed to open stream: Permission denied in ...\SearchStar\index2.php on line 8

Warning: file_get_contents(..): failed to open stream: Permission denied in ...\SearchStar\index2.php on line 8

Which in turn causes a long list of errors of the like:

Warning: file_get_contents(CanadaLine.txt): failed to open stream: No such file or directory in ...\SearchStar\index2.php on line 8

Except CanadaLine.txt is one of the existing files, as are all the other ones it comes up with an error on.

scandir returns an array of all files and directories. You'll need to verify the file is a file and not a directory as it stands right now you're trying to file_get_contents on directories which will fail.

Personally I would recommend the use of PHP's glob() function:

foreach (glob("*.txt") as $filename) {
         $temp = file_get_contents($filename);

         if (strpos($temp, $word)) {
           $result .= $temp;
         }
}

I've tried both checking for a file during the foreach (with is_file) and the glob() function. In both cases, nothing happens. The errors don't come up anymore, but when I type a word and submit, it just returns the empty $result string that was declared at initialization. It does nothing inside the loop.

Can you re-post your modified code?

Ok this is my code using the glob() function

<?php
if (isset($_POST['submit'])) {
    $files = scandir("files");
    $exclusion = file_get_contents("exclusion/exclusion.txt");
    $word = $_POST['search'];
    $result = "";
    foreach (glob("files/*.txt") as $file) {
        $temp = file_get_contents($file);
        if (strpos($temp, $word)) {
            $result .= $temp;
        }
    }
}
?>

and this is my code using the is_file check

<?php
if (isset($_POST['submit'])) {
    $files = scandir("files");
    $exclusion = file_get_contents("exclusion/exclusion.txt");
    $word = $_POST['search'];
    $result = "";
    foreach ($files as $file) {
        if (is_file($file)) {
            $temp = file_get_contents($file);
            if (strpos($temp, $word)) {
                $result .= $temp;
            }
        }
    }
}
?>

and the textarea code

<textarea rows="30" cols="100">
<?php 
if (isset($_POST['submit'])) {
    echo $result; } ?>
</textarea>

try this:

<?php

if (isset($_POST['submit'])) {
  $exclusion = file_get_contents("exclusion/exclusion.txt");
  $word = $_POST['search'];
  $result = "";
  foreach (glob("files/*.txt") as $file) {
    if($temp = file_get_contents($file)) {
      if (preg_match("/" . $word . "/i", $temp)) {
        $result .= $temp;       
      }
    }
    else
    {
      $result .= "Unable to read file: $file";
    }
  }
}

?>

Ok that worked. Now I made a change to your code that instead of returning the combined result of all text files that contained the word, it puts each text file in an array which I then use readfile and feed it an array position. It's works, but how could I increment the array to display results other than the first. I know I have to use JavaScript and I think it might work if I create some functions that increment and decrement results and I could feed the current result to the readfile, but I'm not sure how to incorporate the JavaScript into the PHP and how I would update the textarea.

Few different options, I'll place them in the order I would use them:

1) Most user friendly way would be to use AJAX. Send an AJAX request to obtain the contents of the file and display them in the text area

2) Make your Previous and Next options do a page refresh and send the file via a POST and load the data into the text area

3) Load the contents of all the files at the same time and convert them into a JS Array, than load the value of the JS array into the text area as needed

If you want to avoid having to use Javascript or AJAX, you could always store the names of the files into a session variable. You could then use option 2 above to call the file from the session and load the contents into the textarea.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.