ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: PHP MySQL Search Class
Submitter: Stephen Bartholomew (other recipes)
Last Updated: 2003/10/28
Version no: 1.9
Category: Databases

 

5 stars 3 vote(s)


Approved

Description:

This class can perform a full text search over multiple columns of a MySQL database table, matching entries containing all search terms parsed to it.

Source: Text Source

<?
#############################################################
#
# -=[ MySQL Search Class ]=-
#
#      version 1.5
#
# (c) 2002 Stephen Bartholomew
#
# Functionality to search through a MySQL database, across
# all columns, for multiple keywords
#
# Usage:
#
#    Required:
#        $mysearch = new MysqlSearch;
#        $mysearch->setidentifier("MyPrimaryKey");
#        $mysearch->settable("MyTable");
#        $results_array = $mysearch->find($mysearchterms);
#
#    Optional:
#        This will force the columns that are searched
#        $mysearch->setsearchcolumns("Name, Description");
#
#             Set the ORDER BY attribute for SQL query
#            $mysearch->setorderby("Name"); 
#
##############################################################

class MysqlSearch
{
    function find($keywords)
    {
        # Create a keywords array
        $keywords_array = explode(" ",$keywords);

        # Select data query
        if(!$this->searchcolumns)
        {
            $this->searchcolumns = "*";
            $search_data_sql = "SELECT ".$this->searchcolumns." FROM ".$this->table;
        }
        else
        {
            $search_data_sql = "SELECT ".$this->entry_identifier.",".$this->searchcolumns." FROM ".$this->table;
        }

        # Run query, assigning ref
        $search_data_ref = mysql_query($search_data_sql);

        # Define $search_results_array, ready for population
        # with refined results
        $search_results_array = array();

        if($search_data_ref)
        {
            while($all_data_array = mysql_fetch_array($search_data_ref))
            {
                # Get an entry indentifier
                $my_ident = $all_data_array[$this->entry_identifier];

                # Cycle each value in the product entry
                foreach($all_data_array as $entry_key=>$entry_value)
                {
                    # Cycle each keyword in the keywords_array
                    foreach($keywords_array as $keyword)
                    {
                        # If the keyword exists...
                        if($keyword)
                        {
                            # Check if the entry_value contains the keyword
    
                            if(stristr($entry_value,$keyword))
                            {
                                # If it does, increment the keywords_found_[keyword] array value
                                # This array can also be used for relevence results
                                $keywords_found_array[$keyword]++;
                            }
                        }
                        else
                        {
                            # This is a fix for when a user enters a keyword with a space
                            # after it.  The trailing space will cause a NULL value to
                            # be entered into the array and will not be found.  If there
                            # is a NULL value, we increment the keywords_found value anyway.
                            $keywords_found_array[$keyword]++;
                        }
                        unset($keyword);
                    }
    
                    # Now we compare the value of $keywords_found against
                    # the number of elements in the keywords array.
                    # If the values do not match, then the entry does not
                    # contain all keywords so do not show it.
                    if(sizeof($keywords_found_array) == sizeof($keywords_array))
                    {
                        # If the entry contains the keywords, push the identifier onto an
                        # results array, then break out of the loop.  We're not searching for relevence,
                        # only the existence of the keywords, therefore we no longer need to continue searching
                        array_push($search_results_array,"$my_ident");
                        break;
                    }
                }
                unset($keywords_found_array);
                unset($entry_key);
                unset($entry_value);
            }
        }

        $this->numresults = sizeof($search_results_array);
        # Return the results array
        return $search_results_array;
    }
    
    function setidentifier($entry_identifier)
    {
        # Set the db entry identifier
        # This is the column that the user wants returned in
        # their results array.  Generally this should be the
        # primary key of the table.
        $this->entry_identifier = $entry_identifier;
    }

    function settable($table)
    {
        # Set which table we are searching
        $this->table = $table;
    }
    
    function setsearchcolumns($columns)
    {
        $this->searchcolumns = $columns;
    }
}

?>

Discussion:

$mysearch->find($searchterm) will return an array containing the primary key values for all entries containing the search terms parsed to it.

You can then use a foreach loop to unwind the array and print the primary key or use it in a database call.

To limited which columns are searched, use the setsearchcolumns() method.

example:
$mysearch->setsearchcolumn("Name,Description");

For more information, visit http://www.2404.co.uk/index.php?path=projects/php_mysql_search_class.php



Add comment

Number of comments: 8

Can't print the array to the browser, 2003/03/18
Thanks for this excellent class. I, however can't print_r array to the browser. It simply prints array() Can anyone explain why? Shantanu Oak shantanuo@yahoo.com http://www.shantanuoak.com
Add comment

found out the answer, Shantanu Oak, 2003/07/30
I did some debugging and found out that in line 43 of the script, the resulting SQL-Query would be "SELECT *,id FROM myTable" (if I set the identifier to 'id'). This brings up an empty result from mysql for me, hence 'print_r ($results_array);' puts out an empty array. I tried changing part of the line from "SELECT ".$this->entry_identifier.",".$this->searchcolumns." into "SELECT ".$this->searchcolumns." and it works for me now: the $results_array contains the correct id-values according to $mysearchterms.
Add comment

Bug Fixed, Stephen Bartholomew, 2003/10/28
Thanks for your help with that bug. I've revised the version available here and i'll make the changes to the newer versions. Taking your fix, I placed the SQL statement construction in an if/else block: if setsearchcolumns is not set, the statement is constructed with a '*' and the identifier column is not added. If it has been set, the columns + the id column are added. Let me know if there are any problems.
Add comment

Two things missing, Jeff Klawiter, 2003/11/21
There are two things missing and would make this a great class.
1. Support for boolean excludes ie castle -england
2. Support for quotes. "london england" tourist attractions
Add comment

How to use resulting array of keys to select rows in MySQL DB, Scott Emery, 2004/06/29
this *is* a great class... kudos to the author :) One thing I'm hoping that others could share though is an optimized way to use the resulting array of data that this class returns to select only those rows in the database that match the keys in the resulting array. Is there any way in SQL to select only those rows whose keys match the keys in the resulting array? Any help would be greatly appreciated.
Add comment

Comments, Jason Wilson, 2005/12/04
Hi, I had a few issues with the original class. Some of the arrays had to be initialized and the SQL was not as flexible as I needed. But the theory behind the search is good and with only a few minor modifications it worked great for my site. Thanks, Jason
Add comment

splitting keywords, sasa sasa, 2005/12/08
lol why not just use regex to split keywords so that you don't have to worry about null values?
http://us2.php.net/preg_split

I haven't tested it, but something like
$keywords=trim($keywords); //remove whitespace before and after keywords
$keywords=preg_split("/[\s,!\.\?]+/",$query); //split on any whitespace or punctuation

(I just used bugmenot to log in so that I could just comment on this, so don't try to email me on this account or nuttin)

Anyway, thanks for the code. I might modify and use it in my database project.
Add comment

MySQL tutorial, mike more, 2006/10/30
http://webdeveloper.pl/manual_mysql/ MySQL tutorial with advices
Add comment



Highest rated recipes:

1. Microsoft Access ...

2. main - python-like if ...

3. tinySendMail

4. Single Linked List

5. iPHP: Semi-interactive ...

6. DB_eSession PHP class ...

7. PHP MySQL Search Class

8. Pass Javascript arrays ...

9. Password generation

10. Microsoft Access ...




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.