Modify search results page to table – code for loop?
-
The search results page looks horrible and I would like to modify to present a table since the search will mostly be used as a parts search. All inventory has been divided up into categories with 1 category being our Master Inventory list. Unfortunately, since the files are so large, I had to use the “Embed a document” plugin to create most of the pages of inventory.
After must research, I have found that I need to modify the look within the search.php file. My problem is that I am unsure what code to use to have it display correctly as a 6 column table (Part Number, NSN, Alt. P/N, description, condition and quantity) showing only the part number information searched. The data would have to be pulled from the data created from the “Embed a document” plugin. I am simply at a loss of how to create the needed loop to display this correctly so that just the part number search shows up instead of the whole long list of inventory.
As an example, try searching “50-8792-3”
The website is https://www.calportaviation.com.
Any help with the coding would be much appreciated!
Thank you!
-
This is what my search.php file looks like:
<?php /** * The template for displaying Search Results pages. * * @package implecode */ get_header(); ?> <section id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php if ( have_posts() ) : ?> <header class="page-header"> <h1 class="page-title"><?php printf( __( 'Search Results for: %s', 'catalog-me' ), '<span>' . get_search_query() . '</span>' ); ?></h1> </header><!-- .page-header --> <?php /* Start the Loop */ ?> <?php while ( have_posts() ) : the_post(); ?> <?php get_template_part( 'content', 'search' ); ?> <?php endwhile; ?> <?php implecode_paging_nav(); ?> <?php else : ?> <?php get_template_part( 'content', 'none' ); ?> <?php endif; ?> </main><!-- #main --> </section><!-- #primary --> <?php get_footer();
What’s the template used for the current search results, isn’t this the 6 column format you want? Before the loop, output the table tag and the header content. After the loop output the closing table tag. Inside the loop output the
<tr><td>content x 6</td> .... </tr>
It appears the problem is the search query just returns everything. The default search looks in the title and content for the provided search term. Neither of these probably has the part number that one is actually searching for. I’m not sure why everything is returned instead of nothing, but you likely need a custom search query anyway.
One way to do a completely custom SQL query is to hook the ‘posts_request’ filter. Your callback is passed both the request and the query object in a referenced array. Check the query vars for the ‘s’ query var being defined. If not, return the passed request, otherwise return the custom SQL query instead.
Thank you for the reply!
I am certainly not a developer and have been learning as I go. We are using the WordPress Catalog Me! Template. I think my main problem is that the wordpress search widget I am using does not bring up anything from my master inventory list which is the only reason I have that widget on there. The Inventory list consists of an excel file with 51,000 line items. I have separate categories for specific parts, but they do not include everything.
Creating a custom SQL query is a bit intimidating as I really don’t want to kill the website for some silly error. Can you tell me how to “hook the ‘posts_request’ filter”?
I did take a look at the query file and vars file, but can’t seem to find what you are talking about with the “‘s’ query var being defined”. I apologize for my lack of knowledge here. Any help with the coding would be incredibly helpful!
Let me know what file you need to view and I can link it into my response here.
Thanks again for your help!
Don’t worry about lack of knowledge. We all started by knowing nothing at some point. All that matters to me is your willingness to learn ??
This is a long post, but don’t be intimidated. Most of it has to do with workflow, the coding part is minimal.
The ‘posts_request’ filter is applied in query.php on line 3544 (v4.5). The SQL query string returned is used immediately to get the ID col or get results, depending on the value of
$q['fields']
(makes more sense if you look at the referenced code). You hook the filter like this:add_filter('posts_request', 'bc_part_query', 10, 2); function bc_part_query( $request, $query ) { $part_query = "SELECT * FROM wp_post WHERE...???"; if ( $query->is_main_query() && $query->get('s')) $request = $part_query; return $request; }
I haven’t completed the part query string because I don’t know how the part numbers are stored in relation to posts. The part query is only used when
$query->get('s')
returns a value (which is the user entered part number search string), which indicates the query is a search query. You also use$query->get('s')
to insert the part number in the SQL query string. We verify that the query is the main query because menu and widget queries also use this same filter. The filter hook code can go on your theme’s functions.php or in a custom plugin.If you want to alter theme code, you should create a child theme so your custom work is not overwritten when the theme is updated. Crashing the site is a real concern. Be sure to keep incremental backups of any file you are working on. Have your FTP client fired up and ready to quickly upload an unmodified, working version of any file you’re editing where an error could crash the site. Test your code frequently so you know exactly where things go wrong. If you’re going to be coding on your site on a regular basis, you should setup a local testing version of your site to play with and make mistakes. Then once you have flawless code, you can then upload it to the live site. XAMPP is a popular package to use to setup local installations.
You don’t need to worry about killing your site with bad SQL as long as you stick to getting information out with SELECT or COUNT and never try to alter the DB with UPDATE, INSERT, etc. To be safe, keep a current DB backup anyway.
You can get a head start with the proper SQL format by making a custom WP_Query (not a search query) for a particular part number. If you hook ‘posts_request’ and simply echo out the request, it’ll show up at the top of the page. It should be pretty close to the required part number search query, substituting
$query->get('s')
for the part number value.An easy way to test code and make a custom WP_Query is to create a custom page template that contains the code. Add a page based on this template, then view the page. Each time you edit the template, reload the page to see the results. Define WP_DEBUG as true on wp-config.php so PHP can tell you what mistakes you made right in your browser.
A lot of information! It’s worth it though, being able to code means you can get any site to submit to your will. It’s quite empowering ??
Wow, I really can’t thank you enough for all of the useful information and patience with me!
I have created a child theme as suggested since this may be getting a little tricky with recoding. Would I need to copy the query.php file to my child theme for these changes?
The ideal situation for the part search, would be to pull data only from the master inventory list (https://www.calportaviation.com/master-inventory/), but unfortunately, since I had to use the “Embed a Document” plugin, the search widget refuses to see any of that data. The inventory file is simply too large to add straight to the page using html code to have it show up as a table. However, it isn’t very helpful if the search feature can’t pull information from any document added using “Embed a Document”!
This may seem like a real newbie and silly question, but I am noticing everything is related to posts and not pages. We have zero actual “posts” as everything was added to “pages”. Will this create a problem?
Again, you have been so very helpful in creating such detailed explanations. I really appreciate that ??
No, query.php is a core file and is always loaded regardless of theme or child theme. You do not place any custom code in this file. Custom code should go on functions.php of your child theme. If there are any theme template files that you need to change, you can copy these to your child theme.
To be able to search for parts in the document, the data needs to be imported into the WP database somehow. What format is the original list in? If it’s a spreadsheet, exporting/importing shouldn’t be too difficult. Designing the best schema for storing the data is an important step. From what little I know about this list, I would suggest creating a custom post type, one post for each part. Some of the data can be part of the post itself, the rest can be saved as post meta. Any field that should be searchable should be part of the post object or saved as an individual meta value. Data that is informational that does not need to be searchable can all be stored as an array that is stored as a single meta value.
There is going to need to be some sort of custom import script to manage the conversion. This would only be run once for the existing data. This raises the question of how is this data maintained? How are new parts added, removed, edited? This needs to be accommodated. Ideally, the data in the WP database becomes the master list that is maintained directly. This means an additional user interface to facilitate edits, unless the custom fields meta box on the edit screen is adequate.
Pages instead of posts is not a huge problem, pages are just another post type. You’ll need to specify the correct post type when making queries, otherwise pages are handled mostly just like posts.
The original Master Inventory List is an Excel file (.xlsx). The file is listed on the “Master Inventory” page as [embeddoc url=”https://www.calportaviation.com/wp-content/uploads/2016/03/INVENTORY-032916.xlsx” viewer=”microsoft”].
I have been trying to find out how to have the search widget only pull data from this file. It would be too time consuming to add a separate post for each part as we have over 51,000 line items. We update this file about once a month by downloading a whole new complete inventory list to replace the old one.
From what I have found in my research,
add_query_arg( 'key', 'value', 'https://example.com' );
seems to be a possible solution? I tried adding the url to the part query string you provided, but obviously that didn’t work. I feel like I am missing something here.I also found this filter, but am not really sure how to use it:
function add_query_vars_filter( $vars ){ $vars[] = "my-var"; return $vars; } add_filter( 'query_vars', 'add_query_vars_filter' );
I guess I really just need to find out where to add the URL so that it is recognized by the search.
I feel like my head is starting to spin with all the different code I may have to add to have this work. Is it even possible to link the search to this file?
Thank you again for your help!
There is no WP function to search through .xlsx file.
add_query_arg()
and ‘query_vars’ merely add parameters to a link or query, it does not tell anything how to read an .xlsx file. While I’m unaware of such a thing, it’s conceivable there is a plugin that integrates .xlsx files to WP. Worth a search or two perhaps.Actually, adding 51k posts wouldn’t be that time consuming once a script is written to do it. The computer does all the work, it’d probably take 5-10 minutes. However, now that I know more, I advise getting a script to import the .xlsx file into a custom table. Does the Excel app have a export to SQL function? If not, there may be an add-on that does so. The database management app, phpMyAdmin, is capable of importing XML (the underlying .xlsx format) files. I’ve never used it, the file may need some manual tweaking to get the import to work right, but it’s worth investigating.
Since the file is actually in XML format, it’s conceivable to have a script that searches through the file itself, but the process would be incredibly slow. SQL would be many times faster. To search a custom table would of course require a custom query. This is done using the global
$wpdb
database interface object.Once the import process is nailed down, you would simply drop the old table when a new inventory becomes available and make a fresh one via the established process. It may just take a few minutes to do this.
Using the ‘posts_request’ filter like I suggested earlier is still valid, but you could not use the standard WP loop since there are no posts to loop through. You’d be better off with a simple search form that submits to a page based on a custom page template. The page template will take the entered search form text, construct a query, execute it, then display the results.
You are probably overwhelmed at this point with all the details that need attention. You’ll have to trust me when I say it’s not as bad as it sounds. If you break the project down into small parts and just focus on that, you’ll find each small part is manageable. Eventually you’ll get through all the parts and have everything working. Don’t get me wrong, it’s not going to be easy, but it is feasible to accomplish. If you feel it really is too much, you could bring in some hired help, it’s not that time consuming for a pro.
The big unknown now is how easily can the spreadsheet be imported into a mySQL table. Solve that and the rest is certainly attainable.
Hello again!
So I have done some heavy research on your suggestions. I just happened to find where our master inventory list was stored in the MySQL database and have succeeded in exporting that data which is now saved on my computer in sql format. It is labeled as Table: parts. Now my fear is that importing this data into our wordpress MySQL database will not integrate well. How do I know that the formatting is the same and it will not create a whole bunch of errors? I will of course need to update the inventory list eventually as it is very outdated, but first I wanted to make sure the old SQL file will work with wordpress.
The following is the script from the parts.sql file I am looking to import:
CREATE TABLE
parts` (
id
int(11) NOT NULL AUTO_INCREMENT,
PartNumber
varchar(200) DEFAULT NULL,
nsn
varchar(200) DEFAULT NULL,
nsn2
varchar(200) DEFAULT NULL,
Description
varchar(200) DEFAULT NULL,
Condition
varchar(200) DEFAULT NULL,
CVQuantity
varchar(200) DEFAULT NULL,
UNIQUE KEYid
(id
)
) ENGINE=MyISAM AUTO_INCREMENT=47027 DEFAULT CHARSET=latin1 AUTO_INCREMENT=47027 ;`Do I need to create another php file in wordpress to store this table in?
I am hopeful that the script created for this table will be sufficient for our current wordpress site, but I wanted to consult with you before I actually attempted the import.
Do you have any suggestions or advice before I make this big move?
Thank you!
It probably would not matter, but ideally the charset should match the one used by WordPress, usually UTF-8. I’m unsure of the best way to change the charset. It can be done after import, but it’s rather tedious. Not only does each table have an assigned charset, but every column does as well.
I suspect you could simply edit the SQL file with the new charset, but that has the potential to go wrong in so many ways!
Before you do anything, backup your WP database, just in case.
I’d suggest you create an abridged SQL file with just the create table part along with only a half dozen or so data records to add. Test the import with this abridged file before importing everything to identify any issues. It’s much easier to drop a bad table with 6 records than one with 51k records!
Other than the charset matching, there’s nothing to be concerned with about a compatible format. It’s not compatible with any existing WP data structure, but that’s OK, code can be adapted to work with whatever structure it is. For that matter, code can convert charsets as well, though it’d be better if they matched to begin with.
If updated data will continue to come in as latin1, it’s best to deal with it in a way that is as easy as possible. I suspect ignoring the difference may work out just fine, but I cannot be sure.
In the end, what you will end up with is a completely custom search results page template that takes the search term and creates an SQL query that is executed with a
$wpdb
method. The results returned are then stepped through, outputting each record in the appropriate table format. The only thing WordPress about this is the page will have the same header and footer as other pages, and the page itself is actually a WordPress page, but with a completely custom template that is able to query this parts table in it’s format as imported. The less converting that is done, the better.I successfully created an abridged SQL file with only 6 part records being displayed and imported that file into my WP database. However, I noticed that while all of the other files in MySQL begin with wp_xsoj, the imported file is simply labeled “parts”. So far I have no errors, but is there a way to rename it or should I just leave it the way it is?
I also created a results-page.php which contains the same data as my page.php file, but now I am unsure as to what code I need to place here to pull the data from my SQL table. I went back to our old website files and found a results.php file which contains the following data:
<?php /* $Id: privacy.php 1739 2007-12-20 00:52:16Z hpdl $ osCommerce, Open Source E-Commerce Solutions https://www.oscommerce.com Copyright (c) 2003 osCommerce Released under the GNU General Public License */ require('includes/application_top.php'); require(DIR_WS_LANGUAGES . $language . '/' . FILENAME_PRIVACY); $breadcrumb->add(NAVBAR_TITLE, tep_href_link(FILENAME_PRIVACY)); /* * *********************************************************************************************** */ if (isset($_POST['btnSearch']) || isset($_GET['pageNum_Parts'])) { $currentPage = $_SERVER["PHP_SELF"]; $maxRows_Parts = 25; //Max number of items displayed on each page $pageNum_Parts = 0; if (isset($_GET['pageNum_Parts']) && !isset($_POST['btnSearch'])) { $pageNum_Parts = $_GET['pageNum_Parts']; } $startRow_Parts = $pageNum_Parts * $maxRows_Parts; /* Get the Part Number either from the textbox from a post back or from the querystring if the page has NOT been posted back. */ if (empty($_POST['PartNum']) && (!empty($_GET['PartNum']) && !isset($_POST['btnSearch']) )) { $PartNum = trim($_GET['PartNum']); } else { $PartNum = trim($_POST['PartNum']); } /* * ******************************************************************** If user selects only a plane type get all products from that plane. * ******************************************************************** */ if ((!empty($_POST['PartNum']) || !empty($_GET['PartNum'])) || isset($_POST['btnSearch'])) { //If the page has been submited (posted) with a newly selected PlaneType(s) //then get PlaneTypes from the selected items from the listbox and build the querystring. //Otherwise user is going between pages, so use the previously selected items stored //in the querystring. $query_Parts = "SELECT * From <code>parts</code> WHERE parts.PartNumber LIKE '%$PartNum%' or parts.nsn LIKE '%$PartNum%'"; $query_limit_Parts = sprintf("%s LIMIT %d, %d", $query_Parts, $startRow_Parts, $maxRows_Parts); $Parts = mysql_query($query_limit_Parts) or die(mysql_error()); $row_Parts = mysql_fetch_assoc($Parts); $totalRows_Parts = mysql_num_rows($Parts); } /* * ****************************************************************************** SET UP PAGING OF PARTS * ****************************************************************************** */ if (isset($_GET['totalRows_Parts']) && !isset($_POST['btnSearch'])) { $totalRows_Parts = $_GET['totalRows_Parts']; } else { $all_Parts = mysql_query($query_Parts); $totalRows_Parts = mysql_num_rows($all_Parts); } $totalPages_Parts = ceil($totalRows_Parts / $maxRows_Parts) - 1; $queryString_Parts = ""; /* if (!empty($_SERVER['QUERY_STRING'])) { $params = explode("&", $_SERVER['QUERY_STRING']); $newParams = array(); foreach ($params as $param) { if (stristr($param, "pageNum_Parts") == false && stristr($param, "totalRows_Parts") == false && stristr($param, "PartName") == false && stristr($param, "PartType") == false) { array_push($newParams, $param); } } if (count($newParams) != 0) { $queryString_Parts = "&" . htmlentities(implode("&", $newParams)); } } */ $queryString_Parts = sprintf("&totalRows_Parts=%d%s", $totalRows_Parts, $queryString_Parts); //Parts being search by part number if (!empty($PartNum)) { if (!empty($_POST['PartNum']) && isset($_POST['btnSearch'])) { $queryString_Parts = sprintf("&PartNum=%s", $PartNum); } else { $queryString_Parts = sprintf("&PartNum=%s", $PartNum); } } } //end if error_reporting(0); ?> <!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"> <html <?php echo HTML_PARAMS; ?>> <head> <meta http-equiv="Content-Type" content="text/html; charset=<?php echo CHARSET; ?>"> <title><?php echo TITLE; ?></title> <base href="<?php echo (($request_type == 'SSL') ? HTTPS_SERVER : HTTP_SERVER) . DIR_WS_CATALOG; ?>"> <link rel="stylesheet" type="text/css" href="stylesheet.css"> </head> <body marginwidth="0" marginheight="0" topmargin="0" bottommargin="0" leftmargin="0" rightmargin="0"> <!-- header //--> <?php require(DIR_WS_INCLUDES . 'header.php'); ?> <!-- header_eof //--> <!-- body //--> <?php /*?><table border="0" width="100%" cellspacing="3" cellpadding="3"> <tr> <td width="<?php echo BOX_WIDTH; ?>" valign="top"><table border="0" width="<?php echo BOX_WIDTH; ?>" cellspacing="0" cellpadding="2"> <!-- left_navigation //--> <?php require(DIR_WS_INCLUDES . 'column_left.php'); ?> <!-- left_navigation_eof //--> </table></td><?php */?> <!-- body_text //--> <td width="100%" valign="top"><table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr> <td><table border="0" width="100%" cellspacing="0" cellpadding="0"> <tr> <td class="pageHeading">Search Results</td> <?php /*?><td class="pageHeading" align="right"><?php echo tep_image(DIR_WS_IMAGES . 'table_background_specials.gif', HEADING_TITLE, HEADING_IMAGE_WIDTH, HEADING_IMAGE_HEIGHT); ?></td><?php */?> </tr> </table></td> </tr> <tr> <td><?php echo tep_draw_separator('pixel_trans.gif', '100%', '10'); ?></td> </tr> <tr> <td><table border="0" width="100%" cellspacing="0" cellpadding="2"> <tr> <td class="main"> <form name="form" id="form" method="post" action="results.php"> <table style="border: 1px solid rgb(153, 153, 153);" border="0" cellpadding="5" cellspacing="0" width="270"> <tbody><tr class="stdtxt" > <td><table border="0" cellpadding="0" cellspacing="3" width="100%"> <tbody><tr> <td colspan="2" class="stdtxt"><strong>PRODUCT SEARCH </strong></td> </tr> <tr> <td colspan="2" class="stdtxt">Enter entire or part of a part number or NSN number.</td> </tr> <tr> <td class="stdtxt"><input name="PartNum" class="formFields1" id="PartNum2" size="30" type="text"></td> <td width="35%"><input id="btnSearch" name="btnSearch" value="Submit" type="hidden"> <a href="javascript:document.form.submit();"><img src="images/button_search.gif" border="0" height="22"></a></td> </tr> </tbody></table></td> </tr> </tbody></table> </form> <form name="form1" method="post" action="<?php $_SERVER["PHP_SELF"]; ?>"> <input id="PartNumSaved" name="PartNumSaved" type="hidden" value="<?php echo $_POST['PartNum']; ?>"> <?php $startAt = 0; $displayTo = 0; if (($startRow_Parts + 1) + $maxRows_Parts > $totalRows_Parts && $totalRows_Parts != 0) { //Total number of rows to display are less than the maximum number displayed on a page. (ex. last page) $startAt = $startRow_Parts + 1; $displayTo = ($totalRows_Parts - ($startRow_Parts + 1)) + ($startRow_Parts + 1); } elseif ($totalRows_Parts != 0) { $startAt = $startRow_Parts + 1; $displayTo = ($startRow_Parts + 1) + $maxRows_Parts; } //Display which part the user is looking for. if (!empty($PartNum)) { $ShowPartNum = "for a <b>" . strtoupper($PartNum) . "</b>"; } if ($totalRows_Parts > 0) { ?> Part No. containing: <b><?php echo $PartNum; ?></b><br/><br/> Showing <?php echo $startAt; ?> to <?php echo $displayTo; ?> of <?php echo $totalRows_Parts; ?> matches <?php } else { echo "No match could be found"; } ?> <table width="100%"> <tr><td align="right"> <?php if ($startAt != 1 && $totalRows_Parts != 0) { ?> <a href="<?php printf("%s?pageNum_Parts=%d%s", $currentPage, max(0, $pageNum_Parts - 1), $queryString_Parts); ?>" class="stdtxt" >Previous</a> <?php } ////end if if ($startAt + $maxRows_Parts < $totalRows_Parts) { ?> <a class="stdtxt" href="<?php printf("%s?pageNum_Parts=%d%s", $currentPage, min($totalPages_Parts, $pageNum_Parts + 1), $queryString_Parts); ?>" >Next</a> <?php } //end if ?> </td></tr></table> <table width="600"> <tr class="stdtxt"> <td>Part Number</td> <td>Description</td> <td align="center">Condition</td> <td align="center">CV Quantity</td> <td>NSN</td> </tr> <tr> <td colspan="5" ><img src="images/spacer.gif" width="1" height="4"></td> </tr> <tr> <td colspan="5" bgcolor="#9A0018"><img src="images/spacer.gif" width="1" height="1"></td> </tr> <tr> <td colspan="5" ><img src="images/spacer.gif" width="1" height="6"></td> </tr> <!--DISPLAY DATABASE RESULTS--> <?php if ($totalRows_Parts > 0) { $color1 = "#FFFFFF"; $color2 = "#F5F5F5"; $row_count = 1; do { $row_color = ($row_count % 2) ? $color1 : $color2; ?> <tr class="stdtxt" bgcolor="<?php echo $row_color; ?>" > <td><?php echo $row_Parts['PartNumber']; ?></td> <td><?php echo $row_Parts['Description']; ?></td> <td align="center"><?php echo $row_Parts['Condition']; ?></td> <td align="center"><?php echo $row_Parts['CVQuantity']; ?></td> <td><?php echo $row_Parts['nsn']; ?></td> </tr> <?php $row_count++; } while ($row_Parts = mysql_fetch_assoc($Parts)); } else { ?> <tr class="stdtxt" > <td colspan="5" align="center"> </td> </tr> <tr class="stdtxt" > <td colspan="5" align="center">Your search did not match any parts on file. <BR><BR> Make sure all keywords are spelled correctly.<BR> Try different or more general keywords. </td> </tr> <?php } //End if ?> <!--/DISPLAY DATABASE RESULTS--> </table> <table width="100%"><tr> <td align="right" class="stdtxt"> <?php if ($startAt != 1 && $totalRows_Parts != 0) { ?> <a href="<?php printf("%s?pageNum_Parts=%d%s", $currentPage, max(0, $pageNum_Parts - 1), $queryString_Parts); ?>" class="stdtxt" >Previous</a> <?php } //end if if ($startAt + $maxRows_Parts < $totalRows_Parts) { ?> <a class="stdtxt" href="<?php printf("%s?pageNum_Parts=%d%s", $currentPage, min($totalPages_Parts, $pageNum_Parts + 1), $queryString_Parts); ?>" >Next</a></td> <?php } //end if ?> </tr> </table></form> </td> </tr> <tr> <td class="main"><?php echo '<a href="' . tep_href_link('products_new.php', tep_get_all_get_params(array('sort', 'page')), 'NONSSL', true, false) . '">' . tep_image_button('button_back.gif', IMAGE_BUTTON_BACK) . '</a>'; ?></td> </tr> </table></td> </tr> <tr> <td><?php echo tep_draw_separator('pixel_trans.gif', '100%', '10'); ?></td> </tr> <?php /*?><tr> <td><table border="0" width="100%" cellspacing="1" cellpadding="2" class="infoBox"> <tr class="infoBoxContents"> <td><table border="0" width="100%" cellspacing="0" cellpadding="2"> <tr> <td width="10"><?php echo tep_draw_separator('pixel_trans.gif', '10', '1'); ?></td> <td align="right"><?php echo '<a href="' . tep_href_link(FILENAME_DEFAULT) . '">' . tep_image_button('button_continue.gif', IMAGE_BUTTON_CONTINUE) . '</a>'; ?></td> <td width="10"><?php echo tep_draw_separator('pixel_trans.gif', '10', '1'); ?></td> </tr> </table></td> </tr> </table></td> </tr><?php */?> </table></td> <!-- body_text_eof //--> <?php /*?><td width="<?php echo BOX_WIDTH; ?>" valign="top"><table border="0" width="<?php echo BOX_WIDTH; ?>" cellspacing="0" cellpadding="2"> <!-- right_navigation //--> <?php require(DIR_WS_INCLUDES . 'column_right.php'); ?> <!-- right_navigation_eof //--> </table></td><?php */?> </tr> </table> <!-- body_eof //--> <!-- footer //--> <?php require(DIR_WS_INCLUDES . 'footer.php'); ?> <!-- footer_eof //--> <br> </body> </html> <?php require(DIR_WS_INCLUDES . 'application_bottom.php'); ?>
Would I be able to copy this into my new WP results-page.php file?
Also, I added a page setting this results-page.php as the template. I am still not getting any results when searching for a specific part that was part of the 6 added in the abridged SQL file. I understand that this is probably due to lack of coding in one of the files. Do I need to somehow link this custom search results page to the wordpress search widget or do I need to create a custom search box? If so, how do I do that?
One last question for now, do I need to add any code to the functions.php file?
You have been so helpful thus far. Thank you for being so patient with me!
Sorry for the slow reply, I was taking a break from these forums. I’m still with you, I’m not giving up!
You can leave the table name as is. As long as whatever queries you make use the proper name it’s all good. If you’d rather have a different name anyway, you can use phpMyAdmin (or equal) to change the name.
I’d be reluctant to use that code page in its entirety, there’s some dependencies that may be difficult to resolve, and they may conflict with WP code. It also appears to be much more involved than is necessary. I also noted some deprecated functions used. Still, it can be a useful reference, in particular the query used:
$query_Parts = "SELECT * From parts WHERE parts.PartNumber LIKE '%$PartNum%' or parts.nsn LIKE '%$PartNum%'";
Note the “parts” table name. If you rename the table, adjust this query as well.$PartNum
will be the entered part number value from the search form. The ‘%’ on either side is the SQL wildcard character. The specifics of how to get that value depend on the search form. You can use the search widget, but it could be tricky getting it to send data to your results page. Or easy, it depends on the widget. Ideally, you would be able to easily alter the the form’s “action” attribute to go to your results page. Failing that, you could redirect where ever it does go over to your results page. How that is done depends on where it goes as is. Another possibility is to make your own search widget based on the current one, copying all the code and giving it a new name. The only code difference is the action attribute.Once the form data is directed to your results page, You need to collect the search string. If the input field name is ‘s’ and the form’s method is POST, use this:
$PartNum = $_POST['s'];
Adjust as needed for the actual form conditions. You must validate and sanitize the search string to prevent SQL injection attacks. See https://codex.www.ads-software.com/Data_Validation#Input_Validation and Validating Sanitizing and Escaping User Data.Once you’ve validated and sanitized the search string, you can query the parts table. The original code uses
mysql_query()
, but since your data is now in the WP database, there’s a better way. See https://codex.www.ads-software.com/Class_Reference/wpdb#SELECT_Generic_ResultsThe example provided in that link is pretty much all you need to do to get results, except you would use the parts query I suggested above, and the foreach loop would be adjusted to output part data instead of post titles. Of course, the foreach would loop through
$query_Parts
instead of$fivesdrafts
. There would certainly be other HTML output so the results are nicely formatted. For example, an over all div container to facilitate specific CSS, which contains a structured table could be implemented. Output the div and table HTML before entering the foreach loop. The loop would output one table row in its entirety for each part. Then after the loop concludes, close out the table and div tags.The only code I see possibly being added to functions.php is to modify how the search widget works. Whether this is needed depends on the widget. For example, if you need to create a new widget, all the code could go on functions.php. Or if there’s a filter to alter the form’s action, the filter hook could go here. Or the redirect code, if required, could go here. Most of your code is going to be on the results page template.
Thank you for the response. I completely understand wanting a break from this for a bit ??
You have provided some very useful information in your response. However, I am still having trouble getting the results page to work. When I perform a search now (with one of the 6 parts on my “parts” sql table), I get the error “Oops, That page can’t be found.”. I am not quite sure what I am doing wrong here. I guess my biggest hurdle at this point is figuring out exactly where to put the code that you gave me. Here is what I have so far search.php:
<?php /*Template Name: Search Results */ get_header(); ?> <section id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php if ( have_posts() ) : ?> <header class="page-header"> <h1 class="page-title"><?php printf(__( 'Search Results for: %s', 'catalog-me' ), '<span>' . get_search_query() . '</span>' ); ?></h1> </header><!-- .page-header --> <?php global $wpdb; $query_Parts = $wpdb->get_results( "SELECT * FROM 'parts' WHERE parts.PartNumber LIKE '%$PartNum%' or parts.nsn LIKE '%$PartNum%'"); $PartNum = $_POST['s]; $PartNum = sanitize_search_field( $_POST['s'] ); update_post_meta( $post->ID, 's', $PartNum ); //echo "<pre>"; print_r($query_Parts); echo "</pre>"; echo "ID"."PartNumber"."nsn"."nsn2"."Description"."Condition"."CVQuantity"."<br><br>"; foreach($query_Parts as $row) { echo $row->id." ".$row->PartNumber." ".$row->nsn." ".$row->nsn2." ".$row->Description." ".$row->Condition.".$row->CVQuantity."<br>"; } setup_postdata( $row ); ?> <h2> <a href="<?php the_permalink(); ?>" rel="bookmark" title="Permalink: <?php the_title(); ?>"> <?php the_title(); ?> </a> </h2> <?php } } else { ?> <h2>Not Found</h2> <?php } ?> <?php endif; ?> </main><!-- #main --> </section><!-- #primary --> </div> <?php get_footer();
As you can see, it looks pretty choppy. I know that there has to be a problem with connecting to the mysql database or else I would be able to pull up one of the parts in the table. Is there anything else I need to put in searchform.php? This is what I currently have:
<form role="search" method="post" class="searchform" action="https://www.calportaviation.com/search-results/"> <div><label class="screen-reader-text" for="s">Search for:</label> <input type="search" value="" placeholder="Part Number or NSN" name="s" id="s" /> <input type="submit" id="searchsubmit" value="Search" /> </div> </form>
I have found myself at a major roadblock here. Any suggestions?
Thanks as always!
The page can’t be found error is because the search form submits to a page with the slug “search-results”, but a normal WP search that uses search.php submits to the domain root. Because a normal PHP search will not be useful, I think submitting to “search-results” makes more sense. Either way can be made to work, I think a custom results page is better.
To work as a custom results page, the search form needs some minor adjustments. Change the name and ID for the input field from “s” to something else, like “term”. Using “s” for custom results pages results in a 404 error. “s” is only for default WP searches.
Copy your search results page into the same theme folder, giving it a new name. search-results.php will work as long as no other file has that name. The Template Name comment header is fine for search-results.php, but remove it from search.php.
Create a new page based on this Search Results template. Give it the title Search Results, confirming the slug assigned is search-results. You can change the actual title after the slug is assigned if you like. No need for content. If you get a slug like search-results2, adjust the search form’s action attribute accordingly.
On search-results.php, change any reference to
$_POST['s']
to$_POST['term']
or whatever name you used on the search form for the field name. Move the$query_Parts
line with the SQL query to below where$PartNum
is assigned.I think with these adjustments you should see some sort of results. More work will be required to get the results looking right, but for now any proper results = victory!
Just in case, if you haven’t already, define WP_DEBUG on wp-options.php as true so you can see any PHP errors or warnings as they occur, along with what the error is and where it was detected.
IT WORKS!! After defining WP_DEBUG as true, I was able to fix all of the syntax errors. However, I noticed that all of the errors that came up were in reference to my search.php and not search-results.php that I created to link to me Search Results page. Not a big deal since I am actually showing results…certainly not pretty results, but results!! I can’t thank you enough for all of your expertise and helpful information.
Now, the fun begins with trying to make it look presentable in a table kind of format. I have done some research as to how to do this, but everything I have seen so far shows alterations to functions.php as well as some added CSS. I don’t have a problem with CSS as I have the Custom CSS plugin installed which has done wonders. Is there an easier way to make the results display as a table?
Do I simply need to add <table> somewhere? If so, where exactly would I put that within the code? My updated code in search.php is this:
<?php get_header(); ?> <section id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php if ( have_posts() ) : ?> <header class="page-header"> <h1 class="page-title"><?php printf(__( 'Search Results for: %s', 'catalog-me' ), '<span>' . get_search_query() . '</span>' ); ?></h1> </header><!-- .page-header --> <?php global $wpdb; $PartNum = $_POST['term']; $PartNum = sanitize_text_field( $_POST['term'] ); update_post_meta( $post->ID, 'term', $PartNum ); $query_Parts = $wpdb->get_results( "SELECT * FROM parts WHERE parts.PartNumber LIKE '%$PartNum%' or parts.nsn LIKE '%$PartNum%'"); //echo "<pre>"; print_r($query_Parts); echo "</pre>"; echo "ID"; foreach($query_Parts as $row) { echo $row->PartNumber; echo $row->nsn; echo $row->nsn2; echo $row->Description; echo $row->Condition; echo $row->CVQuantity; } setup_postdata( $row ); ?> <h2> <a href="<?php the_permalink(); ?>" rel="bookmark" title="Permalink: <?php the_title(); ?>"> <?php the_title(); ?> </a> </h2> <?php else : ?> <h2>Not Found</h2> <?php ?> <?php endif; ?> </main><!-- #main --> </section><!-- #primary --> </div> <?php get_footer();
I can’t tell you how thrilled I am that we finally got the search to work!
I am certainly looking forward to your suggestions for the results display.
- The topic ‘Modify search results page to table – code for loop?’ is closed to new replies.