Location: PHPKode > scripts > Ssearch > Ssearch.class.php
<?php
	/*	Sphinx Search for database driven websites
	 *	Copyright 2010, Richard Carson
	 *	
	 *	This search method uses a regular expression search of a character tree, and gives each object a weighted score. 
	 *	Scores are determined by string length, where matches of 1 char is 1 point, 2 chars are 10 points, 3 chars are 100 points, etc
	 *	A value of 1001, or 101 is a good starting point
	 *	Objects below the minimum score are dropped, and the rest are sorted by score.
	 *	Please note that depending on the minimum score, some queries may be too short. 
	 *	Use the GetShortestGood method to determine the minimum length a query string must have
	 *	The dataset must be in the form of:
	 *	Dataset(
	 *		object
	 *		(
	 *			string
	 *			string
	 *		}
	 *		object
	 *		(
	 *			string
	 *			string
	 *			string
	 *		)
	 *	)
	 *	
	 *	SetScore($score) //Set the minimum score
	 *	GetScore() //Get the current minimum score
	 *	SetData($Dataset, $checkit=true) //Set the dataset, verification of dataset formatting is optional, and on by default
	 *	GetData($index=-1) //Get the current dataset, or the object at index
	 *	Search($Query, $debug=false) //Perform a search, debug mode is available.
	 *	GetShortestGood() //Get the shortest query length that can return results
	 */
	
	class Ssearch
	{	
		private $Dataset=array();
		private $MinScore=0;
		
		function __construct()
		{

		}
		
		private function BuildQtree($query, $debug)
		{
			$query = strtolower($query);
			$Qtree = array();
			$Qtree["words"][0] = $query;
			$q = strlen($query) - 1;
			$i = 0;
			$cQ = &$Qtree;
			$ilim = 0;
			while ($q > 0)
			{
				$cur = array();
				$ilim = strlen($query) - $q;
				$i = 0;
				while ( $i <= $ilim)
				{
					$cur["words"][] = substr($query, $i, $q);
					$i++;
				}
				$q--;
				$cQ["child"] = $cur;
				$cQ = &$cQ["child"];
			}
			
			if ($debug) var_dump($Qtree);
			return $Qtree;
		}
		
		public function SetScore($score)
		{
			$this->MinScore = $score;
		}
		
		public function GetScore()
		{
			return $this->MinScore;
		}
		
		public function SetData($Data, $checkit=true)
		{
			//Check Dataset
			if ($checkit)
			{
				if (is_array($Data))
				{
					foreach($Data as $obj)
					{
						if (is_array($obj))
						{
							foreach($obj as $line)
							{
								if (is_array($line))
								{
									return false;
								}
							}
						}
						else
						{
							return false;
						}
					}
				}
				else
				{
					return false;
				}
			}
						
			$this->Dataset = $Data;
		}
		
		public function GetData($index=-1)
		{
			if ($index >= 0 && $index <count($this->Dataset))
			{
				return $this->Dataset[$index];
			}
			
			return $this->Dataset;
		}
		
		//Function by Fedak (http://php.net/manual/en/function.sort.php)
		private function array_sort($array, $on, $order='SORT_DESC')
		{
		  $new_array = array();
		  $sortable_array = array();

		  if (count($array) > 0) {
			  foreach ($array as $k => $v) {
				  if (is_array($v)) {
					  foreach ($v as $k2 => $v2) {
						  if ($k2 == $on) {
							  $sortable_array[$k] = $v2;
						  }
					  }
				  } else {
					  $sortable_array[$k] = $v;
				  }
			  }

			  switch($order)
			  {
				  case 'SORT_ASC':   
					  asort($sortable_array);
				  break;
				  case 'SORT_DESC':
					  arsort($sortable_array);
				  break;
			  }

			  foreach($sortable_array as $k => $v) {
				  $new_array[] = $array[$k];
			  }
		  }
		  return $new_array;
		} 
		
		//Compare a string to the query using REGEX
		private function QCompare($Qtree, $DataStr, $debug)
		{
			$DataStr = strtolower($DataStr);
			$Score = 0;
			$Levels = 0;
			$tmp = $Qtree;
			while (isset($tmp["child"]))
			{
				$Levels++;
				$tmp = $tmp["child"];
			}
			
			while ($Levels >= 0)
			{
				$set = false;
				foreach($Qtree["words"] as $word)
				{
					if (preg_match("/$word/", $DataStr))
					{
						if ($debug) echo "\n$DataStr - $word - $Score\n";
						$Score += pow(10, $Levels);
						$set = true;
					}
				}
				
				if ($debug && $set) echo "\n$DataStr - $Score\n";
				
				if ($set)
					return $Score;
				$Qtree = $Qtree["child"];
				$Levels--;
			}
			
			if ($debug) echo "\n$DataStr - $Score\n";
			return $Score;
		}

		//Evaluate a series of strings as one object, or set -- for multiple column support
		private function QEval($Qtree, $Row, $debug)
		{
			$Score = 0;
			foreach ($Row as $str)
			{
				$Score += $this->QCompare($Qtree, $str, $debug);
			}
			if ($debug) echo $Score . "\n";
			return $Score;
		}
				
		public function Search($Query, $debug=false)
		{
			$dataret = $this->Dataset;
			$Qret = $this->BuildQtree($Query, $debug);
			$Query = $Qret;
			$i = 0;foreach($dataret as $row)
			{
				if(isset($row['id'])) unset($row['id']);
				if(isset($row['ntp'])) unset($row['ntp']);
				
				$dataret[$i++]["score"] = $this->QEval($Query, $row, $debug);
				if ($dataret[$i-1]["score"] < $this->MinScore) unset($dataret[$i-1]);
			}
			$dataret = $this->array_sort($dataret, "score", 'SORT_DESC');
			
			return $dataret;
		}
		
		public function GetShortestGood()
		{
			$i = 1;
			while ($MinScore % pow(10,$i-1) > 0)
			{
				$i++;
			}
			
			return $i-1;
		}
	}
?>
Return current item: Ssearch