Jump to content

Search Application Design


Go to solution Solved by dave1950,

Recommended Posts

I am creating a php search application on a mysql db with three php files:

 

  • advanced_search.php
  • search_results.php
  • sectiontext.php

 

It works but is awkward, since they open up as separate pages.

 

advanced_search.php contains a form with this code:

 

<form  method="post" action="search_results.php?go" id="searchform">

 

This opens up search_results.php with a list of a summary of search results (document numbers) that are links to the full document text in sectiontext.php, like this:

 

echo '<a href="\ecr/sectiontext.php?ID=' . $FullDocumentID . '">' . $full_doc_number . '</a><br />';

 

As noted, this all works but is awkward since it changes pages.  It would be preferable to have all of this on one page so that the user can easily choose another document or change the search parameters.  I am thinking along two lines, but am open to other options if anyone has suggestions:

 

1. Display all three php files on one web page (i.e., index.php) with includes.  I have created the page with the includes, and they are there, but they don’t link to each other when I do the search.  They keep opening up new web pages instead of staying on the same index.php page.  I am a newbie to php, so still learning about includes.

 

2.  Just put all the code into one php page in different divs and find a way to transfer the variables between steps in the process.  This is easy for steps 1 and 2 (form data) but is more difficult for me (as a newbie) for step three (which seems to be more of a master-detail relationship between the search_results list and the sectiontext table.  Maybe some javascript to link the selected item on the list to the full document text in step 3?

 

This is just a simple application for myself (not for production), but I would like to make it as good as I can and learn by doing.  Any thoughts on how to approach this project?

Link to comment
https://forums.phpfreaks.com/topic/287749-search-application-design/
Share on other sites

you would use a simple page controller to combine and control what the code does on one page. a key to organizing your code to make this easier is to separate your 'business logic' from your 'presentation logic'. see the following example - 

<?php

// the following is the business logic that determines what to do for any page request and gets whatever data is needed

$search = isset($_GET['search']) ? $_GET['search'] : '';
if($search){
    // get the data to produce the document links
    
    // your action code making use of the submitted search term would go here or be included here...
    
    // some made up data as an example
    $links[] = array('id'=>123,'full_document_number'=>'doc 134566');
    $links[] = array('id'=>567,'full_document_number'=>'doc 745745');
}

$id = isset($_GET['id']) ? $_GET['id'] : 0;
if($id){
    // get the data/file for the requested document id
    
    // your action code making use of the submitted document id would go here or be included here...

    // some made up data as an example
    $doc = "some document contents or document link from wherever and however you are storing it";

}


// the following is the presentation logic that takes the data from the above business logic and produces a (correctly formatted) html page

// the search form
if(!$search){
    echo 'Enter search term: ';
}
?>
<form  method="get" action="">
search: <input type='text' name='search' value='<?php echo $search;?>'>
<input type='submit'>
</form>

<?php

// the document links
if($search){
    if(isset($links)){
        // output document links
        echo 'Select a document to view:<br>';
        foreach($links as $link){
            $_GET['id'] = $link['id']; // add document id to (any) existing get parameters
            $qs = http_build_query($_GET, '', '&'); // build the current url query string
            echo "<a href='?$qs'>{$link['full_document_number']}</a><br>";
        }
    } else {
        echo 'No matching documents found.';
    }
}

// the document display
if(isset($doc)){
    echo 'The requested document:<br>';
    
    echo $doc;

}

a point about your search form. it determines what will be shown, i.e. gotten, on the page and should use method='get'.

Thanks for your feedback and suggestions.  This is just the kind of specific information I need at this early point in the project (and my continuing education).  Based on you advice:

 

1.  I have chosed to use a single page for the application.

2.  Use the GET method to pass data.

 

I have been doing some research on the "business logic" and "application logic" and I think I understand the rationale and overall concept, but am not sure how to do it with this specific application.  Here is the code that I have created based on two of your suggestions (single page with GET method):

 

<HTML>
<HEAD>
</HEAD>
<BODY>

<h1>Search Form</h1>

<form method="get" action="search.php?go" id="searchform">
Search Term <input type="text" id="" name="searchterm">
Document Type <select name="doctype">
         <option value="1">Text</option>
         <option value="3">Background</option>
         <option value="2">Reports</option>
         <option value="4">Index</option>
     </select>    
<input type="submit" name="submit" value="Submit">
</form>

<h1>Search Results</h1>
<?
$searchterm=$_GET['searchterm'];
$doctype=$_GET['doctype'];    
?>

<p>for: <span style="font-size: 14px; font-weight: bold; color: red;"><? echo $searchterm; ?></span> </p>

<?
mysql_connect("xx", "xx", "xx") or die(    mysql_error());
mysql_select_db("xx") or die(mysql_error());

$result1 = mysql_query(
"SELECT
SectionText,
FullDocumentID,
ReadingNo,
SectionTypeID,
CONCAT(ReadingNo, '-', SequenceNo) AS full_doc_number
FROM Full_Documents
WHERE SectionText LIKE '%
$searchterm%' AND SectionTypeID = '$doctype'
Order By FullDocumentID"
);
$num_records = mysql_num_rows($result1);
?>

<p>documents found: <span style="font-size: 14px; font-weight: bold; color: red;"><? echo $num_records; ?></span></p>

<?
while ($row = mysql_fetch_array($result1, MYSQL_ASSOC)) {
$full_doc_number=$row ['full_doc_number'];
$FullDocumentID=$row ['FullDocumentID'];
echo '<a href="\ecr/search.php?ID=' . $FullDocumentID . '">' . $full_doc_number . '</a><br />';
}
?>

<h1>Document Display</h1>

<?
$result2 = mysql_query(
"SELECT
SectionText,
FullDocumentID
FROM Full_Documents
WHERE FullDocumentID = "
. $_GET['ID']);;

echo "<table border='0' width='800px'>
     <tr class=\"style3\">
     "
;
     while($row = mysql_fetch_array($result2))
     {
     echo "<tr class=\"style2\">";
     echo "<td style=\"width: 800px;\"><p>" . preg_replace("/\r\n|\r|\n/", "</p><p>", $row['SectionText']) . "</p></td>";
echo "</tr>";
     }
     echo "</table>";
?>

</BODY>
</HTML>

 

The code does work crudely, but presents two immediate issues:

 

ISSUE 1.  When I click on the document number links in the SEARCH RESULTS list, it passes the $FullDocumentID through a GET method to the DOCUMENTS TEXT section by reloading the page and erasing the data in the SEARCH RESULTS list.  I would like the list data to remain visible (without having to resort to the browser Back button to reload the search results).

 

ISSUE 2.  When the page loads for the first time (before any search or search results are available), there is no $FullDocumentID for the third step, therefore an error message is displayed:

 

“Warning: mysql_fetch_array() expects parameter 1 to be resource, Boolean …”

 

Of course this warning goes away once a link in the SEARCH RESULTS is clicked and the page is reloaded with the document ID in the URL – the GET allows the passing of the ID for the final db query that loads the document text. I would like for the warning statement not to be visible during the first two steps of the search and display process.  Just a blank space or perhaps a default document could be loaded when the application starts?

 

Would these two issues be solved by using the business logic/presentation logic model as you have outlined it?  Thanks again for your helpful suggestions.  Any further guidance is appreciated.

the example code i posted contains logic to test if there is a submitted search term before trying to use it and if there is a submitted document id before trying to use it, thereby preventing the errors you are getting.

 

the example also propagates the search term in the document links.

 

i recommend studying the example code again (it's standalone, functional, code that you can run by itself to see how it works.)

Thanks, I really appreciate your patience.  Yes, when the example is run as standalone code, with the hardcoded sample data, it does work just fine.  I can begin to grasp the concept behind the design principle you are suggesting.

 

In the implementation, I have tried to replace the hardcoded sample data with the working code from my previous efforts as follows:

 

<?php
//BUSINESS LOGIC SECTION

// get the data to produce the document links
$search=$_GET['search'];
$doctype=$_GET['doctype'];
$search = isset($_GET['search']) ? $_GET['search'] : '';

if($search){
mysql_connect("xx", "xx", "xx") or die(    mysql_error());
    mysql_select_db("xx") or die(mysql_error());

$links = mysql_query(
"SELECT
SectionText,
FullDocumentID,
ReadingNo,
SectionTypeID,
CONCAT(ReadingNo, '-', SequenceNo) AS full_doc_number
FROM Full_Documents
WHERE SectionText LIKE '%
$search%' AND SectionTypeID = '$doctype'
Order By FullDocumentID"
);
}

$id = isset($_GET['Full_Document_ID']) ? $_GET['Full_Document_ID'] : 0;
if($id){
// get the data/file for the requested document id

$doc = mysql_query(
"SELECT
SectionText,
FullDocumentID
FROM Full_Documents
WHERE FullDocumentID = "
. $_GET[$id]);;
}

// PRESENTATION LOGIC SECTION

// the search form

if(!$search){
echo 'Enter search term: ';
}
?>

<form method="get" action="" id="search_criteria">
Search Term <input type="text" id="" name="search"></br>
     Document Type <select name="doctype"></br>
<option value="1">Text</option>
         <option value="3">Background</option>
         <option value="2">Reports</option>
         <option value="4">Index</option>
     </select></br>    
<input type="submit" name="submit" value="Submit">
</form>

<?php

// the document links

if($search){
if(isset($links)){
// output document links
echo 'Select a document to view:<br>';
foreach($links as $link){
$_GET['Full_Document_ID'] = $link['Full_Document_ID']; // add document id to (any) existing get parameters
$qs = http_build_query($_GET, '', '&'); // build the current url query string
echo "<a href='?$qs'>{$link['full_document_number']}</a><br>";
}
} else {
echo 'No matching documents found.';
}
}

// the document display

if(isset($doc)){
echo 'The requested document:<br>';
echo $doc;
}
?>

 

I get an error message:

 

"Warning: Invalid argument supplied for foreach() in /home/content/36/10807936/html/ecr/test2.php on line 66"

 

Line 66 is:

 

foreach($links as $link){

 

I think trying to Get "id" or "$id" from the "FullDocumentID" may be the problem, but don't see any way to fix it based on my current knowledge. Do you see anything obvious that I have missed or distorted?

 

I really do like the way this approach passes the data between the sections without destroying it - it remains visible in the search box and results list - and no Warning message at the beginning of the document display before the search term is provided.  So, again, I am thankful for your guidance with this specific project and the way this kind of approach can transfer to future projects once I master it.

after your run the search query, you must loop over the result set and build the $links array from the fetched data. the $links variable in your posted code is the result resource from the query, not the 'generic' data that the presentation logic needs.

 

you should only SELECT the fields you need in that or any query. you are only using FullDocumentID and full_doc_number. these are the only things you should have in the SELECT list in the search query.

 

you would just fetch and store each row to the $links array -

    // this code expects the result resource from the query to be in $result
    if(mysql_num_rows($result) > 0){
        $links = array();
        while ($row = mysql_fetch_assoc($result)){
            $links[] = $row;
        }
    }

btw - Please use the forum's


[/nobbc] bbcode tags (the edit form's <> button) when posting code. i would edit your posts, the that generally messes up copy/pasted code that wasn't originally posted in [nobbc]

bbcode tags.

 

also, the mysql_ database functions are currently depreciated and will be removed in a future version of php. you should be learning and using either the mysqli or PDO database functions so that you don't need to go through all your code changing the database functions when the mysql_ functions get removed.
 

Edited by mac_gyver

Thanks, I put the additional code in the Business Logic section after the first query and I changed it back to $result since that is what is referenced in the new code. When I run the file I get this error message along with the "No matching documents found."

 

Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in /home/content/36/10807936/html/ecr/test2.php on line 24

Search Term 
Document Type              Text     Background     Reports     Index     
 

No matching documents found.

 

Here is my latest code.  I hope I used the bbcode tags correctly.  I have removed the unnecessary fields from the Select statement and will look into PDO.  Thanks again for your help. 

<?php
//BUSINESS LOGIC SECTION
    
    // get the data to produce the document links
    $search=$_GET['search'];
    $doctype=$_GET['doctype'];
    $search = isset($_GET['search']) ? $_GET['search'] : '';
    
    if($search){
    mysql_connect("xx", "xx", "xx") or die(mysql_error());
   	mysql_select_db("xx") or die(mysql_error());

    $result = mysql_query(
	"SELECT 
	FullDocumentID
    CONCAT(ReadingNo, '-', SequenceNo) AS full_doc_number
    FROM Full_Documents
	WHERE SectionText LIKE '%$search%' AND SectionTypeID = '$doctype'
    Order By FullDocumentID");
    }

    // this code expects the result resource from the query to be in $result
    if(mysql_num_rows($result) > 0){
        $links = array();
        while ($row = mysql_fetch_assoc($result)){
            $links[] = $row;
        }
    }

     $id = isset($_GET['Full_Document_ID']) ? $_GET['Full_Document_ID'] : 0;
    if($id){
    // get the data/file for the requested document id
    
        $doc = mysql_query(
	    "SELECT 
	    SectionText
        FROM Full_Documents
	    WHERE FullDocumentID = " . $_GET[$id]);;
    }

// PRESENTATION LOGIC SECTION
    
    // the search form

    if(!$search){
    echo 'Enter search term: ';
    }
    ?>

    <form  method="get" action="" id="search_criteria"> 
        Search Term <input type="text" id="" name="search"></br> 
	    Document Type <select name="doctype"></br>
            <option value="1">Text</option>
		    <option value="3">Background</option>
		    <option value="2">Reports</option>
 		    <option value="4">Index</option>
	    </select></br>	
        <input type="submit" name="submit" value="Submit">
    </form>

    <?php

    // the document links
    
    if($search){
    if(isset($links)){
        // output document links
        echo 'Select a document to view:<br>';
        foreach($links as $link){
            $_GET['Full_Document_ID'] = $link['Full_Document_ID']; // add document id to (any) existing get parameters
            $qs = http_build_query($_GET, '', '&'); // build the current url query string
            echo "<a href='?$qs'>{$link['full_document_number']}</a><br>";
        }
    } else {
        echo 'No matching documents found.';
    }
    }

    // the document display
    
    if(isset($doc)){
    echo 'The requested document:<br>';
    echo $doc;
    }
?>

the error message is because your query failed due to an error (you removed the comma between the two remaining items in the SELECT list.)

 

you also don't have any error checking logic for your queries, so you are getting follow-on errors when they fail due to an error in them.

I inserted a comma in the Select statement like this:

 

$result = mysql_query(
"SELECT
FullDocumentID,
CONCAT(ReadingNo, '-', SequenceNo) AS full_doc_number
FROM Full_Documents
WHERE SectionText LIKE '%
$search%' AND SectionTypeID = '$doctype'
Order By FullDocumentID"
);
}

 

but got the same error message as before when the page loads.  Interestingly, if I type in and submit a search term that I know to be in the documents, the error message goes away and the text below the form reads: "Select a document to view:"  No error message, but no items in the list either.

 

The search term was "migraine" (it's a medical database) and the end of the url after submitting the form was "... test.php?search=migraine&doctype=1&submit=Submit"  So apparently the passing of the variables via Get is working.  Any further thoughts?

at this point, these problems are logic, copy/paste, and typo errors on your part. you need to debug what your code is doing and try and solve these yourself.

 

it would probably help if you set php's error_reporting to E_ALL and display_errors to ON to get php to report and display all the errors it detects.

  • Solution

Thanks for helping me create a solid conceptual design foundation that I can work with moving forward. I will now focus on learning about debugging and error reporting, and once this basic phase is working add refinements such as pagination, highlighting text, etc. 

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.