<

Go Premium for a chance to win a PS4. Enter to Win

x

A Simple Search Function Using PHP, JQuery and AJAX

Published on
18,055 Points
11,855 Views
2 Endorsements
Last Modified:

Overview

This article demonstrates a simple search form using AJAX. The purpose of the article is to demonstrate how to use the same code to render a page and javascript (JQuery) and AJAX to make subsequent calls to refine the results.

The principle behind the design of this code is to re-use the same code to generate the table of results for both the first render and subsequent AJAX search requests. In this way changes to the table structure and layout only have to be managed in one place.

The Container Page

We start with the container page that displays the initial view of the data we are interested in manipulating through AJAX. The code below gives a basic structure for us to work with
index.php
<!doctype html>
<html>
<head>
<title>AJAX Sample search page</title>
</head>
<body>
  <h2>Super Hero Contact List</h2>
  Search <input type="text" id="search" /> <input type="button" value="Search" id="search_button" /><br/>
  <table id="superheros">
    <thead>
      <tr>
        <th>Firstname</th><th>Surname</th><th>Age</th><th>Email</th>
      </tr>
    </thead>
    <?php require_once('data.php'); ?>
  </table>
</body>
</html>

Open in new window


Rendering the results

The above page draws our Superhero contact list by calling an external PHP file (data.php) to render the actual rows of the table. Lets look at what data.php could look like
data.php
<?php
/* 
   FIRST: DEFINE OUR TEST DATA. 
   FOR OTHER IMPLEMENTATIONS THIS ARRAY COULD BE
   POPULATED FROM A DATABASE OR ANY OTHER SOURCE
*/
$values = array(
  array('firstname' => 'Peter', 'surname' => 'Parker', 'age' =>'21', 'email' =>'peter@arachnaphopia.com'),
  array('firstname' => 'Clark', 'surname' => 'Kent', 'age' =>'36', 'email' =>'kal-el@krypton.com'),
  array('firstname' => 'Bruce', 'surname' => 'Banner', 'age' =>'28', 'email' =>'hulk@bigandgreen.com'),
  array('firstname' => 'Steven', 'surname' => 'RogersS', 'age' =>'95', 'email' =>'captain@merica.com'),
  array('firstname' => 'Bruce', 'surname' => 'Wayne', 'age' =>'32', 'email' =>'bruce@batcave.com')
);
/* LOOP THROUGH THE ARRAY AND CONSTRUCT OUR ROWS */
foreach($values as $v) :
 echo '<tr>
   <td>' . $v['firstname'] . '</td><td>' . $v['surname'] . '</td><td>' . $v['age'] . '</td><td>' . $v['email'] .'</td>
   </tr>';
endforeach;
?>

Open in new window

That's about it - the above code will generate the results for our table.

Adding Search

The next step is to add our search capability. To do the search we are going to search on all fields for the entered string. To simplify this process we are going to run the search against a string produced from concatenating all the fields of the row together.
$searchstr = implode(' ', $row);

Open in new window

With the above string we can now do a regular expression match on our search expression.
preg_match("/$pattern/", $searchstr);

Open in new window

If preg_match returns a value > 0 we have a match.
All that we need to do now to round off our data.php file is to put in the code to get the search expression from the AJAX call. If we assume that the value is posted to the script then it should be as simple as
$pattern = empty($_POST['search']) ? '' : $_POST['search'];

Open in new window

Putting it all together

<?php
$values = array(
  array('firstname' => 'Peter', 'surname' => 'Parker', 'age' =>'21', 'email' =>'peter@arachnaphopia.com'),
  array('firstname' => 'Clark', 'surname' => 'Kent', 'age' =>'36', 'email' =>'kal-el@krypton.com'),
  array('firstname' => 'Bruce', 'surname' => 'Banner', 'age' =>'28', 'email' =>'hulk@bigandgreen.com'),
  array('firstname' => 'Steven', 'surname' => 'RogersS', 'age' =>'95', 'email' =>'captain@merica.com'),
  array('firstname' => 'Bruce', 'surname' => 'Wayne', 'age' =>'32', 'email' =>'bruce@batcave.com')
);
/* 
   RETRIEVE THE SEARCH EXPRESSION 
   FROM THE POST. DEFAULT TO EMPTY
   STRING IF NOT PRESENT
*/
$expr = empty($_POST['search']) ? '' : $_POST['search'];

foreach($values as $v) {
  /* CREATE OUR SEARCH STRING */
  $searchstr = implode(" ", $v);
  
  /* LOOK FOR A PATTERN MATCH */
  $rv = preg_match("/$expr/", $searchstr);
  
  /* IF MATCHED OUTPUT ROW */
  if ($rv > 0) :
    echo '<tr>
   <td>' . $v['firstname'] . '</td><td>' . $v['surname'] . '</td><td>' . $v['age'] . '</td><td>' . $v['email'] .'</td>
   </tr>';
  endif;
}
?>

Open in new window

That's all we need to do on the data.php side. If no POST parameter is supplied all results will be returned as the preg_match will work against an empty string. In theory we could make the code a bit more efficient by putting a test for an empty expression around the preg_match - this is left to the reader to implement if required.
Additional search functionality can be implemented by experimenting with the preg_match search parameters to produce richer search functionality. Again this is left to the reader.

The AJAX
The final step is the AJAX component in the container page. As you will have deduced by now the results returned by the data.php script is plain html as opposed to JSON. This makes for a much simpler implementation on the AJAX side as the HTML can be loaded directly into the target container without having to run through a returned JSON object to create each of the elements in the result set. It also allows us to consistently define the format of the results in one central location.

Here is the JQuery we need to add to our container page.
index.php
/* FIRST UP INCLUDE JQUERY */
<script src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
$(function() {
  /* 
  CREATE AN EVENT HANDLER FOR 
  THE SEARCH BUTTON
  /*
  
  $('#search_button').click(function(e) {
    
    /* DISABLE DEFAULT BEHAVIOUR FOR THE BUTTON */
    e.preventDefault();
  
    /* POST THE SEARCH TERM TO OUR data.php  SCRIPT */
    $.post('data.php', {search: $('#search').val()}, function(html) {

    /* 
    LOAD THE RETURNED HTML TO THE 
    BODY OF THE RESULTS TABLE 
    */
      $('#superheros tbody').html(html);
    });
  });
});
</script>

Open in new window

And that should be that. Here is a full listing of the final container file
<!doctype html>
<html>
<head>
<title>Test</title>
<script src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
$(function() {
  $('#search_button').click(function(e) {
    e.preventDefault();
    $.post('data.php', {search: $('#search').val()}, function(html) {
      $('#superheros tbody').html(html);
    });
  });
});

</script>
<style type="text/css">
</style>
</head>
<body>
  <h2>Super Hero Contact List</h2>
  Search <input type="text" id="search" /> <input type="button" value="Search" id="search_button" /><br/>
  <table id="superheros">
    <thead>
      <tr>
        <th>Firstname</th><th>Surname</th><th>Age</th><th>Email</th>
      </tr>
    </thead>
    <?php require_once('data.php'); ?>
  </table>
</body>
</html>

Open in new window

Testing and Refining

Try entering different substrings to see what is returned
Example
bru

You will notice that you only get one result back. This is because our search is performing a case sensitive search. To make it case insensitive is as simple as adding an 'i' to the regular expression pattern in the data.php file
$rv = preg_match("/$expr/i", $searchstr);

Open in new window

And there it is. A very simple but fairly versatile AJAX search function with a common script to render the results for both AJAX and non-AJAX requests.
index.php
data.php
2
Comment
  • 4
  • 2
6 Comments
 
LVL 1

Expert Comment

by:RationalRabbit
I love this. Kudos!
0
 
LVL 1

Expert Comment

by:RationalRabbit
Of course, one should make this a non-case-sensitive search, but I find it interesting that typing in the lowercase "bruce" provides a result, but only the last row containing "Bruce" - not both rows. Seems to be the only column that does this. Others return no result if the case is not correct.
0
 
LVL 60

Author Comment

by:Julian Hansen
Thanks RationalRabbit,

Regarding the case insensitivity did you try with the recommendation at the end of the article
You will notice that you only get one result back. This is because our search is performing a case sensitive search. To make it case insensitive is as simple as adding an 'i' to the regular expression pattern in the data.php file
$rv = preg_match("/$expr/i", $searchstr);

Open in new window

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 1

Expert Comment

by:RationalRabbit
I just thought that was curious and couldn't figure out why that would occur in one field and not another. I guess it has something to do with the first letter in the row string, but I still don't understand why that would be and how it would affect results when one does want to do a case-sensitive search.

Of course, that will go away using a case insensitive search, but I was curious as to what seems like an oddity. Is it a weakness in preg_match? For instance, If there are matching surnames, using the same pattern (all lower case when surnames are capitalized), will produce no results, as it should.
0
 
LVL 60

Author Comment

by:Julian Hansen
I suspect it is because it is finding 'bruce' in the email address. The search works by imploding the row - which includes the email. Bruce Wayne and Peter Parker both have their first name (lower case) in the email - while the others do not.

I suspect you should get the same result for Peter as for Bruce.
0
 
LVL 1

Expert Comment

by:RationalRabbit
duh ... sure :0)
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Join & Write a Comment

Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month