PDA

View Full Version : Searching a flat text database


Alex Piotto
08-17-2002, 07:50 AM
Hi everybody!
This is my first time at PHP forum, and I would like to thanks CodingForums for the opportunity. THANKS!!!!

Now, my problem...

First of all, I can't use MySQL on my server...

I have a flat text database that looks like this:

id;author;title;usdprice;
0;Agatha Cristie;Evil under the sun;50;
1;Arthur Conan Doyle;A study in Scarlet;75;
2;Raymond Chandler;Farewell my Lovely;28;
3;Stefano Benny;Hearth;35;

etc. etc.

I need to search this db... the user just type a keyword/s in a text box (either the name of the author or the title of the book, or both, or just the first word of the title... or even the price etc.) so I need to search all fields of the db, find the results, sort them by ID number (the newest on top) and finally, I need to print the results on the page.
As I sayd I can't use MySQL, so what can be the solution?

I am a newbie at PHP, and at this point I am stucked...

Can somebody help me out on this?
Thanks in advance
Alex

:(

mordred
08-17-2002, 06:01 PM
Assuming that the file will look roughly like a .csv file, you can make use of Regular Expressions to construct a search pattern and use that with the function fgetcsv(). The following code is an example for a simple OR search upon a file called test.csv. You will have to pass the filename of your flat file you want to search upon.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<title>search the csv file</title>
</head>
<body>

<?php
// global variables
$searchPattern = ''; // contains the searchPattern

function search_csv($file, $searchString)
{
// check if the search string contains nothing
if (empty($searchString)) {
return false;
}

global $searchPattern;
$results = array();

/* Construct the search pattern for the preg_match */

// prepare search pattern
$keywords = preg_split('/[\s]+/', trim($searchString));

// remove duplicate entries
$keywords = array_values(array_unique($keywords));

// escape preg specific characters
for ($k = 0; $k < count($keywords); $k++) {
$keywords[$k] = preg_quote($keywords[$k], '/');
}

// build the search pattern. Observe that the "i" modifier
// stands for a case-insensitive pattern.
$searchPattern = '/(' . implode('|', $keywords) . ')/i';


/* go through the .csv file */

$fp = fopen($file, "r");

// advance the file pointer to the next line
while ( ($str = fread($fp, 1)) != "\n" ) {
// empty statement
}

// iterate through each line and
while ($fields = fgetcsv ($fp, 1000, ";")) {

// search in the author field
if (preg_match($searchPattern, $fields[1] . ' ' . $fields[2])) {
$results[] = $fields;
}
}

fclose ($fp);

return $results;
}

// call the function if form has been submitted
if (isset($_POST['submitted']) && $_POST['submitted'] = 'done') {
$results = search_csv("test.csv", $_POST['keyword']);

/* write the results */

echo "<div style='font-family:verdana; font-size:9pt; color:#000000;'>\n";

if (!$results || count($results) == 0) {
echo "<b>No results found.</b>\n";
} else {
echo "<b>Found results:</b><br />\n";

// iterate throught the results array
for ($i = 0; $i < count($results); $i++) {
echo preg_replace($searchPattern, "<span style='color:red;'>\\1</span>", $results[$i][1]) . ": ";
echo preg_replace($searchPattern, "<span style='color:red;'>\\1</span>", $results[$i][2]) . "<br />\n";
}
}
echo "</div>";
}
?>

<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
<input type="hidden" name="submitted" value="done" />
Keywords: <input type="text" name="keyword" />
<input type="submit" value="search" name="submit" />
</form>

</body>
</html>


As a note to your other post about this puszkin flat file database, you see for yourself what it means to rely on workaround soultions. Your task would've been much simpler to fulfill with a MySQL database and a simple Regex/Like sql statement.

Alex Piotto
08-18-2002, 09:19 AM
Thank you, mordred ! You are the man!

I'll work on your code right now... it will be for me a real lesson of PHP. I will study it throughly...

Actually I know that MySQL is the real solution, but I can't use it... my server doesn't suppot it.

Thank you again

Alex :)

Alex Piotto
08-18-2002, 10:18 AM
Well..... I cant get it to work...
I have got no errors, but no results also!

I am using the table I posted in the first message, and I saved it as test.csv.

What's wrong? I didn't modified the script...

Alex:confused:

mordred
08-18-2002, 04:37 PM
Does you server run PHP in a version >= 4.1? Because I used the recently introduced superglobals $_SERVER and $_POST. Look at your initial output, if there is the correct file written into the action attribute of the form tag.

If you need this to run on an older PHP version, change all $_POST to $HTTP_POST_VARS, and $_SERVER to $HTTP_SERVER_VARS. You will also have to make $HTTP_POST_VARS visible in the function by using the global keyword, like

global $searchPattern, $HTTP_POST_VARS;

Alex Piotto
08-18-2002, 06:07 PM
Sorry to bother again...
I am using php ver 4.0.6... so I changed the lines you suggest. The script works but do strange things... please, test it....
here is the page

<html>
<head>
<title>search the csv file</title>
</head>
<body>
<form method="post" action="<?php echo $HTTP_SERVER_VARS['PHP_SELF'];?>">
<input type="hidden" name="submitted" value="done" />
Keywords: <input type="text" name="keyword" />
<input type="submit" value="search" name="submit" />
</form>

<?
// global variables

global $searchPattern, $HTTP_POST_VARS;

$searchPattern = ''; // contains the searchPattern

function search_csv($file, $searchString)
{
// check if the search string contains nothing
if (empty($searchString)) {
return false;
}

global $searchPattern;
$results = array();

/* Construct the search pattern for the preg_match */

// prepare search pattern
$keywords = preg_split('/[s]+/', trim($searchString));

// remove duplicate entries
$keywords = array_values(array_unique($keywords));

// escape preg specific characters
for ($k = 0; $k < count($keywords); $k++) {
$keywords[$k] = preg_quote($keywords[$k], '/');
}

// build the search pattern. Observe that the "i" modifier
// stands for a case-insensitive pattern.
$searchPattern = '/(' . implode('|', $keywords) . ')/i';


/* go through the .csv file */

$fp = fopen($file, "r");

// advance the file pointer to the next line
while ( ($str = fread($fp, 1)) != "\n" ) {
// empty statement
}

// iterate through each line and
while ($fields = fgetcsv ($fp, 1000, ";")) {

// search in the author field
if (preg_match($searchPattern, $fields[1] . ' ' . $fields[2])) {
$results[] = $fields;
}
}

fclose ($fp);

return $results;
}

// call the function if form has been submitted
if (isset($HTTP_POST_VARS['submitted']) && $HTTP_POST_VARS['submitted'] = 'done') {
$results = search_csv("test.csv", $HTTP_POST_VARS['keyword']);

/* write the results */

echo "<div style='font-family:verdana; font-size:9pt; color:#000000;'>\n";

if (!$results || count($results) == 0) {
echo "<b>No results found.</b>\n";
} else {
echo "<b>Found results:</b><br />\n";

// iterate throught the results array
for ($i = 0; $i < count($results); $i++) {
echo preg_replace($searchPattern, "<span style='color:red;'>\1</span>", $results[$i][1]) . ": ";
echo preg_replace($searchPattern, "<span style='color:red;'>\1</span>", $results[$i][2]) . "<br />\n";
}
}
echo "</div>";
}
?>

</body>
</html>

And a final question: why you search only the the author field?
alex

mordred
08-18-2002, 09:50 PM
Originally posted by Alex Piotto
I am using php ver 4.0.6...


Definitely consider doing an upgrade to a more recent version.


so I changed the lines you suggest. The script works but do strange things... please, test it....


Unfotunately you've changed the wrong lines. ;)
I wrote that you have to make $HTTP_POST_VARS visible in the function, so you should've rather done

global $searchPattern, $HTTP_POST_VARS;
$results = array();

within the function, not outside of it. The function works alright when you do that.

It looks to me that you don't know exactly what the global keyword stands for - perhaps you should look that up in the manual, it's pretty well described somewhere under "variables scope".


And a final question: why you search only the the author field?


My bad: I forgot to update the comment. I had initially a preg_match() function call for each field (author and title), but I later decided to put them together into one statement, only that I missed to change the comment line. The function does search in both fields.
Also, don't consider this code to be the silver bullet. It's just a quick hack I scrambled together to show how it could be done. Sure it can be modified to suit your needs even more.

Alex Piotto
08-19-2002, 08:53 AM
You are right, I need to study more...
but thanks for your patience anyway!

You know, before to update to a newer version of php I should convince my ISP to do the same... but here in Maputo, Mozambique (south africa) we only have 5-6 servers... and only a couple support php. We are at the beginning of the internet era down here, and everything is quite primitive, technologically speaking. But this is slowly increasing...

Africa is a strange place.... really out of balance... while most of the people fight to survive, others can connet the net by wireless service!

This service just appeared on the market here, and is the big issue of the year! Imagine that, apart a few programmer at my ISP (the wireless one, of course) I donīt know others, locally, that use PHP to program their pages!

Forum like this and people like you represent more than a a lot for me... thanks again!

Alex:o

mordred
08-19-2002, 09:11 AM
Oh, I didn't realize you're based in Mozambique. :eek: I'm quite surprised to hear that there is an Internet connection at all in a country which (to my current knowledge) is considered one of the poorest in the world.

Anyway, the code above should also work in PHP 4.0.6, if you run into more problems, just post the questions that come to mind.

Good luck! :)