Didn't know exactly what to call this.. Anyways:
I have a text-file consisting of:
something;something2;something3;something4
I use a regular html-form for userinput. Userinput = $search. I send this to my search-function:
function search($search) {
$lin = file('text.txt');
$lines = array_map('strtolower', $lin);
$found = false;
foreach($lines as $line) {
if(strpos($line, $search) !== false) {
$found = true;
$line = explode(";",$line);
$line[1] = ucwords($line[1]);
$line[2] = ucwords($line[2]);
$line[3] = strtoupper($line[3]);
echo "$hit[0] $hit[1] etc";
}
}
if(!$found) {
echo "No matches";
}
}
This works fine if the user only inputs one words. Let's say the content of the file is: foo;bar;chuck;hank;
I would like the user to be able to search "foo chuck" and still get a result. Even if only one word match, the line should be echoed (ex "foo carl" still outputs the entire line).
But then again, if there is a "foo;bar" and a "foo;carl", I don't want foo bar to show if the user searches for "foo carl"..
Any tips?
use explode to put your string into an array, then loop over the array and check for a hit .... or better yet, use in_array:
$string='something;something2;something3;something4';
$array=explode(';',$string);
if(in_array('test',$array) || in_array('othertest',$array) || in_array('thirdval',$array)){
;//there's a match
}
You could take the user input, split it into words, normalize them in the same manner as you normalize the file contents and put them into an array $input
.
Then, for each row in the file contents follow the exact same procedure again ending up with an array $line
.
Based on your description a search hit occurs when all the words inside $input
are also present inside $line
, which could be expressed as:
$hit = count(array_intersect($input, $line)) == count($input);
Don't forget to "trim" $input
and $line
using array_unique
to cover the case where a search term appears more than once.
Example code:
function search($search) {
// break input into words and normalize
// explode() is maybe not going to cut it in production, but it's OK here
$search = array_unique(explode(' ', strtolower($search)));
$terms = count($search);
$lines = file('text.txt');
$found = false;
foreach($lines as $line) {
// same treatment as for input
$line = array_unique(explode(' ', strtolower($line)));
if(count(array_intersect($search, $line)) == $terms) {
$found = true;
$line = explode(";",$line);
$line[1] = ucwords($line[1]);
$line[2] = ucwords($line[2]);
$line[3] = strtoupper($line[3]);
echo "$hit[0] $hit[1] etc";
}
}
}
if you are dealing with large fie using file
might not be the best approach because Reads entire file into an array and putting it into memory. Your file also looks like CSV so you can use fgetcsv
all you need to change is the delimiter
Try
$file = "large_file.txt";
$search = "something2";
var_dump(search($file, $search));
Other Usage
search($file, $search,true); // Multiple Result
search($file, $search,true,","); // File has , has delimiter Instead of ;
Function
function search($file, $search, $multiple = false, $delimiter = ";") {
$handle = fopen($file, "r");
$list = array();
while ( ($data = fgetcsv($handle, 1024, $delimiter)) !== FALSE ) {
if (in_array($search, $data)) {
if ($multiple)
$list[] = $data;
else
return $data;
}
}
fclose($handle);
return $list;
}