views:

64

answers:

5

Hi,

I need to implement the following functionality:

I have a name field which contains both name and surname. This is stored in a database and is in the order 'surname name'.

I am implementing a script which searches through these records. Currently, I managed to check if a string contains a space, if it contains a space it means it is a name and not an ID Card Number for instance. Here is the code:

$query = "John Doe";

$checkIfSpaceExists = strpos($query, " ");

if ($checkIfSpaceExists == "")
{
    //No Space therefore it is not a name
}
else
{
    //Contains space
   $queryExploded = explode(" ", $query);
   foreach ($queryExploded as $q)
   {
      //Here I need the functionality so that if someone entered John Doe
      //2 different strings are saved, which are
      //$string1 = John Doe
      //$string2 = Doe Johns

      //If the name consists of 3 parts, strings for every combination is saved
}

Then I will insert these strings in an SQL statement with the LIKE attribute and there will be a LIKE for both JOHN DOE and DOE JOHN. Hence, if the user can either enter John Doe or Doe John in order to find the result.

Any suggestions on how to do this?

Many thanks

chris

+1  A: 

What about using these exploded 3 strings in separate AND-combined LIKE-constraints?

Something like

"... WHERE name LIKE '%$name[0]%' AND name LIKE '%$name[1]%' AND name LIKE '%$name[2]%'"

You could build this String in a foreach loop.

Mulmoth
depends if you want to find "Johnathon Doe" and "John Henry Doe". It also won't make use of indices with a wildcard at the start of the string.
nickf
+2  A: 

Ok, from the start - be sure to read the manual carefully. strpos doesn't do exactly what you think it's doing. Here's how you should check for a space:

if (strpos($query, ' ') === false)  // the triple-equals is important!

After that, it's simply a matter of permutations and combinations. Here's another answer on Stack Overflow which shows you how to do it: algorithm that will take number or words and find all possible combinations

nickf
If I use it like you are stating, the script doesn't work well. If instead I use the original one, it works well. I will be updating my post because I implemented it successfully.
Chris
Can you tell me what is wrong with the way I am using it?thanks
Chris
The manual has a section highlighted in red with a very large warning sign, which reads: `This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE, such as 0 or "". Please read the section on Booleans for more information. Use the === operator for testing the return value of this function.`
nickf
A: 
echo preg_replace('/^(\w+) (\w+)$/', '$2 $1', "John Doe");

Doe John

r3zn1k
this doesn't handle multiple spaces (3 or more words)
nickf
preg_replace('/^(\w+) (\w+) (\w+)$/', '$3 $2 $1', "John Jay Doe");preg_replace('/^(\w+) (\w+) (\w+)$/', '$3 $1 $2', "Jay John Doe");Happy? 3 Parts, thats all he asked for...
r3zn1k
A: 

I guess you cannot split this field into name and surname? I suggest creating new table, tags in database. Tags will be any word - might be surname, may be name, may be ID number... Then make a connection record_tags with record_id and tag_id. Then the query will look like

SELECT record.* FROM record
INNER JOIN record_tags rt1 ON rt1.record_id = record.id
INNER JOIN tag t1 ON t1.id = rt1.tag_id
INNER JOIN record_tags rt2 ON rt2.record_id = record.id
INNER JOIN tag t2 ON t2.id = rt2.tag_id
WHERE
t1.name = "John"
AND t2.name = "Doe"

This will be better approach to searching, as you can then use any amount of words/tags. I think the SQL can be even easier. the multiple-like approach is I think much slower, especially as your database grows.

Tomasz Struczyński
No I cannot split the field. The database is updated every couple of months. It is an un-normalized table containing various personal information, such as name etc... When the database is updated, a new table is created with all the information. The previous tables are only there for backup purposes. The front-end program (implemented with ExtJs) only searches from the last table created. It ignores all the others. There are thousands of records and it is incredibly fast...
Chris
A: 

With some looping and string manipulation, I managed to implement this script.

Here is what I did:

I checked if the query contains a space using strpos. If it contains a space, then it means its a name with both name and surname so I enter a loop in order to output one string with 'name surname' and the other string with 'surname name'

Here is the code:

   $like = ""; //This is the LIKE sql command.
   foreach ($selectedFields as $field)
   {
            $checkIfSpaceExists = strpos($query," ");

 if ($checkIfSpaceExists != "")
 {
  $query1 = $query; //No space, so query1 is equal ta original query

  $queryExploded = explode(" ", $query);

  for ($i=0; $i<count($queryExploded); $i++) //First loop (name surname)
  {
   $tmp1 = $tmp1 . " " . $queryExploded[$i];
  }

  for ($i=count($queryExploded); $i>=0; $i--) //Second loop (surname name)
  {
   $tmp2 = $tmp2 . " " . $queryExploded[$i];

  }
  $query2 = $tmp2;
  $query2 = trim($query2);

  $like = $like . $field . " LIKE '%" . $query1 . "%' or " . $field . " LIKE '%" . $query2 . "%' or ";

I hope this helps someone else in need :)

Chris