Вопрос

I have a custom table in the WP database called wp_products. It has columns titled ID, SKU, Details and Page. I'm trying to search this table via the default search box, so I've replaced my search.php file with the code below. This isn't working and I don't know enough PHP to fix it. Can anyone help me out with this?

<?php
/**
 * Author:          
 * Created on:      
 *
 * @package Neve
 */

function search_it() {
    if ( is_search() && isset( $_GET['s'] ) ) {
        global $wpdb;
        $address_table = $wpdb->prefix . "wp_products";
        $search = $_GET['s'];
        $search = "%{$search}%";
        $where = $wpdb->prepare( 'WHERE SKU LIKE %s OR Details LIKE %s OR Page LIKE %s', $search, $search, $search );
        $results = $wpdb->get_results( "SELECT * FROM {$address_table} {$where}" );
        return $product;
    }
    return array();
}

$container_class = apply_filters( 'neve_container_class_filter', 'container', 'blog-archive' );

get_header();

$cities = search_it();
if ( ! empty( $cities ) ) {
    echo '<h1>Catalogue Search Results:</h1>';
    foreach( $cities AS $city ) {
            echo "<table width='100%' align='center' border='3px solid grey'>";
            echo "<tr>";
            echo "<th style='background: #B9C9FE;'>Part Number</th>";
            echo "<th style='background: #B9C9FE;'>Description</th>";
            echo "<th style='background: #B9C9FE;'>Page</th>";
            echo "</tr>";
            echo "<tbody>";


            for ($i=$start;$i < $end ;++$i ) {
            $results = $results[$i];

            echo "<tr>";
            echo "<td>$city->SKU</td>";
            echo "<td>$city->description</td>";
            echo "<td>$city->Page</td>";
            echo "</tr>";
            }
            echo "</tbody>";
            echo "</table>"; 
    }
}

get_search_form();

?>

<?php
get_footer();

Here's the updated code:

<?php
/*
Template Name: Search Page
*/
function search_it() {

    $search = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );

    if ( ! is_search() || empty( $search ) ) {
        return array();
    }

    global $wpdb;

    $address_table = $wpdb->prefix . 'products';

    $search = $wpdb->esc_like( $search );
    $search = "%{$search}%";

    $query = "SELECT * FROM {$wpdb->prefix}products WHERE SKU LIKE %s OR Details LIKE %s OR Page Like %s";
    $query = $wpdb->prepare( $query, $search, $search, $search );
    return $wpdb->get_results();
}

get_header();

$cities = search_it();
if ( ! empty( $cities ) ) {
    echo '<h1>Catalogue Search Results:</h1>';
    echo "<table width='100%' align='center' border='3px solid grey'>";
    echo "<tr>";
    echo "<th style='background: #B9C9FE;'>Part Number</th>";
    echo "<th style='background: #B9C9FE;'>Description</th>";
    echo "<th style='background: #B9C9FE;'>Page</th>";
    echo "</tr>";
    echo "<tbody>";


    foreach( $cities AS $city ) {
        echo "<tr>";
        echo "<td>{$city->SKU}</td>";
        echo "<td>{$city->Details}</td>";
        echo "<td>{$city->Page}</td>";
        echo "</tr>";
    }

    echo "</tbody>";
    echo "</table>"; 
} else {
    echo "<h1 class='page-title'>";
    printf( __( 'There are no search results for: %s', 'shape' ), '<span>' . get_search_query() . '</span>' );
    echo ".</h1>";
    $query;
}

get_search_form();

get_footer();

Here's the print_r( $wpdb->prepare( $query, $search, $search, $search ) ); die; output:

SELECT * FROM wp_products WHERE SKU LIKE '{feeb191b44038789f6b0c639a9f2fe6ff48090427c92513c8582b33a4cbf1c42}GASKET{feeb191b44038789f6b0c639a9f2fe6ff48090427c92513c8582b33a4cbf1c42}' OR Details LIKE '{feeb191b44038789f6b0c639a9f2fe6ff48090427c92513c8582b33a4cbf1c42}GASKET{feeb191b44038789f6b0c639a9f2fe6ff48090427c92513c8582b33a4cbf1c42}' OR Page Like '{feeb191b44038789f6b0c639a9f2fe6ff48090427c92513c8582b33a4cbf1c42}GASKET{feeb191b44038789f6b0c639a9f2fe6ff48090427c92513c8582b33a4cbf1c42}'

The above is the output I get when I run this query:

$query = "SELECT * FROM {$wpdb->prefix}products WHERE SKU LIKE %s OR Details LIKE %s OR Page Like %s";
Это было полезно?

Решение

There's a lot going on in the code, so I rewrote your main function with some comments. Overview of notes:

$address_table is superfluous, and also probably not what you wanted

You only use this variable once, so it's safe to just in-line it in your query. Also, your use of $wpdb->prefix expands $address_table to the value "wp_wp_products", probably not what you want. I left it in the code with some notes, but you don't need any of that in your final method, just use what's in the $query.

Early Return

Returning when your conditions fail, instead of doing logic when they pass (the is_search() && isset( $_GET['s'] ) block), makes your code more readable.

Escaping input

I know you were using $wpdb->prepare eventually, but it doesn't hurt to sanitize input as soon as you plan to use it. This way, if you pass $search somewhere else later, it will hopefully be safer than it was when it came to your function. Also note the use of $wpdb->esc_like() to prepare your search for use in a LIKE clause.

function search_it() {

    // Sanitize user input early, especially if assigning to a variable like later.
    $search = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );

    // Early returns make your code more readable.
    if ( ! is_search() || empty( $search ) ) {
        return array();
    }

    global $wpdb;

    /**
     * Some things about `$address_table`:
     * - You don't need double quotes if you're concatenating
     * - You only use it in your query, see below where I incorporate it inline.
     * - $wpdb->prefix is usually "wp_", so you're table comes out to "wp_wp_products" - 
     * I don't think that's what you want.
     */
    $address_table = $wpdb->prefix . 'products';

    // Double quote would look like this: 
    // $address_table = "{$wpdb->prefix}products";

    // https://codex.wordpress.org/Class_Reference/wpdb/esc_like
    $search = $wpdb->esc_like( $search );
    $search = "%{$search}%";

    // Why not prepare the whole query"?
    // Also, you don't even need $address_table
    $query = "SELECT * FROM {$wpdb->prefix}products WHERE SKU LIKE %s OR Details LIKE %s OR Page Like %s";
    $query = $wpdb->prepare( $query, $search, $search, $search );
    return $wpdb->get_results();
}

Please let me know if you have any questions.

Edit: I accidentally typed filter_validate instead of filter_input

To address the second part of your code, it looks like the inner for loop is using $start and $end, which aren't defined. You also don't need another loop since you're already looping your results. Try this instead:

$cities = search_it();
if ( ! empty( $cities ) ) {
    echo '<h1>Catalogue Search Results:</h1>';
    echo "<table width='100%' align='center' border='3px solid grey'>";
    echo "<tr>";
    echo "<th style='background: #B9C9FE;'>Part Number</th>";
    echo "<th style='background: #B9C9FE;'>Description</th>";
    echo "<th style='background: #B9C9FE;'>Page</th>";
    echo "</tr>";
    echo "<tbody>";


    foreach( $cities AS $city ) {
        echo "<tr>";
        echo "<td>{$city->SKU}</td>";
        echo "<td>{$city->description}</td>";
        echo "<td>{$city->Page}</td>";
        echo "</tr>";
    }

    echo "</tbody>";
    echo "</table>"; 
}

Другие советы

I didn't look very deep into your code, but in your search_it() function you return $product instead of $results. $product is nowhere, it is always empty. You should activate WP_DEBUG in your wp-config.php, there must be errors from PHP.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с wordpress.stackexchange
scroll top