2

I want to add part search into a website powered by WordPress. I have currently achieved the function, but I have trouble of integrating it into WordPress. I tried several ways but the dynamic dependent select box still not working.

I followed this tutorial: Dynamic Dependent Select Box using jQuery, Ajax and PHP

Below are my code which works well outside WordPress.

index.php

<head>
    <script src="http://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script src="js/ajax-ps.js"></script>
</head>

<body>   
    <form class="select-boxes" action="ps-result.php" method="POST">
    <?php
        include('dbConfig.php');            
        $query = $db->query("SELECT * FROM ps_manufact WHERE status = 1 ORDER BY manufact_name ASC");
        $rowCount = $query->num_rows;
    ?>
        <select name="manufacturer" id="manufact" class="col-md-2 col-sm-2 col-xs-10" onchange="manufactText(this)">
            <option value="">Select Manufacturer</option>
            <?php
                if($rowCount > 0){
                    while($row = $query->fetch_assoc()){ 
                        echo '<option value="'.$row['manufact_id'].'">'.$row['manufact_name'].'</option>';
                    }
                }else{
                    echo '<option value="">Manufacturer Not Available</option>';
                }
            ?>
        </select>
        <input id="manufacturer_text" type="hidden" name="manufacturer_text" value=""/>
        <script type="text/javascript">
            function manufactText(ddl) {
                document.getElementById('manufacturer_text').value = ddl.options[ddl.selectedIndex].text;
            }
        </script>

        <select name="type" id="type" class="col-md-2 col-sm-2 col-xs-10" onchange="typeText(this)">
            <option value="">Select Manufacturer First</option>
        </select>
        <input id="type_text" type="hidden" name="type_text" value=""/>
        <script type="text/javascript">
            function typeText(ddl) {
                document.getElementById('type_text').value = ddl.options[ddl.selectedIndex].text;
            }
        </script>

        <select name="year" id="year" class="col-md-2 col-sm-2 col-xs-10" onchange="yearText(this)">
            <option value="">Select Type First</option>
        </select>
        <input id="year_text" type="hidden" name="year_text" value=""/>
        <script type="text/javascript">
            function yearText(ddl) {
                document.getElementById('year_text').value = ddl.options[ddl.selectedIndex].text;
            }
        </script>

        <select name="model" id="model" class="col-md-2 col-sm-2 col-xs-10" onchange="modelText(this)">
            <option value="">Select Year First</option>
        </select>
        <input id="model_text" type="hidden" name="model_text" value=""/>
        <script type="text/javascript">
            function modelText(ddl) {
                document.getElementById('model_text').value = ddl.options[ddl.selectedIndex].text;
            }
        </script>

        <input type="submit" name="search" id="search" class="col-md-2 col-sm-2 col-xs-10" value="Search">
    </form>
</body>

ajax-ps.js

$(document).ready(function(){
    $('#manufact').on('change',function(){
        var manufactID = $(this).val();
        if(manufactID){
            $.ajax({
                cache: false,
                type:'POST',
                url:'ajax-data.php',
                data:'manufact_id='+manufactID,
                success:function(type_data){
                    $('#type').html(type_data);
                    $('#year').html('<option value="">Select Type First</option>'); 
                }
            }); 
        }else{
            $('#type').html('<option value="">Select Manufact First</option>');
            $('#year').html('<option value="">Select Type First</option>'); 
        }
    });

    $('#type').on('change',function(){
        var typeID = $(this).val();
        if(typeID){
            $.ajax({
                cache: false,
                type:'POST',
                url:'ajax-data.php',
                data:'type_id='+typeID,
                success:function(year_data){
                    $('#year').html(year_data);
                    $('#model').html('<option value="">Select Year First</option>'); 
                }
            }); 
        }else{
            $('#year').html('<option value="">Select Type First</option>'); 
            $('#model').html('<option value="">Select Year First</option>'); 
        }
    });

    $('#year').on('change',function(){
        var yearID = $(this).val();
        if(yearID){
            $.ajax({
                cache: false,
                type:'POST',
                url:'ajax-data.php',
                data:'year_id='+yearID,
                success:function(model_data){
                    $('#model').html(model_data);
                }
            }); 
        }else{
            $('#model').html('<option value="">Select Year First</option>'); 
        }
    });
});

ajax-data.php

include('dbConfig.php');

if(isset($_POST["manufact_id"]) && !empty($_POST["manufact_id"])){
    $query = $db->query("SELECT * FROM ps_type WHERE manufact_id = ".$_POST['manufact_id']." AND status = 1 ORDER BY type_name ASC");

    $rowCount = $query->num_rows;

    if($rowCount > 0){
        echo '<option value="">Select Type</option>';
        while($row = $query->fetch_assoc()){ 
            echo '<option value="'.$row['type_id'].'">'.$row['type_name'].'</option>';
        }
    }else{
        echo '<option value="">Type Not Available</option>';
    }
}

if(isset($_POST["type_id"]) && !empty($_POST["type_id"])){
    $query = $db->query("SELECT * FROM ps_year WHERE type_id = ".$_POST['type_id']." AND status = 1 ORDER BY year_name ASC");

    $rowCount = $query->num_rows;

    if($rowCount > 0){
        echo '<option value="">Select Year</option>';
        while($row = $query->fetch_assoc()){ 
            echo '<option value="'.$row['year_id'].'">'.$row['year_name'].'</option>';
        }
    }else{
        echo '<option value="">Year Not Available</option>';
    }
}

if(isset($_POST["year_id"]) && !empty($_POST["year_id"])){
    $query = $db->query("SELECT * FROM ps_model WHERE year_id = ".$_POST['year_id']." AND status = 1 ORDER BY model_name ASC");

    $rowCount = $query->num_rows;

    if($rowCount > 0){
        echo '<option value="">Select Model</option>';
        while($row = $query->fetch_assoc()){ 
            echo '<option value="'.$row['model_id'].'">'.$row['model_name'].'</option>';
        }
    }else{
        echo '<option value="">Model Not Available</option>';
    }
}

Now the problem is, when select the first box, the second one becomes empty, nothing is returned from the database:

Capture - After select the first box

Really appreicate Christos Lytras to help me solve the previous problem.

I have a new problem with action="ps-result.php" in the line <form class="select-boxes" action="ps-result.php" method="POST">.

ps-result.php

<?php
if (isset($_POST['search'])) {
    $clauses = array();
    if (isset($_POST['manufacturer_text']) && !empty($_POST['manufacturer_text'])) {
        $clauses[] = "`manufacturer` = '{$_POST['manufacturer_text']}'";
    }
    if (isset($_POST['type_text']) && !empty($_POST['type_text'])) {
        $clauses[] = "`type` = '{$_POST['type_text']}'";
    }
    if (isset($_POST['year_text']) && !empty($_POST['year_text'])) {
        $clauses[] = "`year` = '{$_POST['year_text']}'";
    }
    if (isset($_POST['model_text']) && !empty($_POST['model_text'])) {
        $clauses[] = "`model` = '{$_POST['model_text']}'";
    }
    $where = !empty( $clauses ) ? ' where '.implode(' and ',$clauses ) : '';

    $sql = "SELECT * FROM `wp_products` ". $where;
    $result = filterTable($sql);
}
else {
    $sql = "SELECT * FROM `wp_products` WHERE `manufacturer`=''";
    $result = filterTable($sql);
}

function filterTable($sql) {
    $con = mysqli_connect("localhost", "root", "root", "i2235990_wp2");
    if (!$con) {
        die('Could not connect: ' . mysqli_error($con));
    }
    $filter_Result = mysqli_query($con, $sql);
    return $filter_Result;
}
?>

<?php get_header(); ?>

<div class="container">
...
</div>

<?php get_footer(); ?>

Now when I click Search, it returns

Fatal error: Call to undefined function get_header() in /Applications/MAMP/htdocs/wordpress/wp-content/themes/myTheme/inc/ps-result.php on line 42.

L. Leo
  • 53
  • 1
  • 9
  • Do you have any PHP/Javascript errors in body or console? And also, how do you try to integrate this to Wordpress? – Christos Lytras Nov 22 '16 at 17:40
  • @Christos Lytras I have edit the question to make it clear. – L. Leo Nov 22 '16 at 20:13
  • @L-Leo you can make this work, if you change `url:'ajax-data.php',` to point into the right `ajax-data.php` url related to your domain root (ex.: `/ajax_calls/ajax-data.php`); however, there is a "proper" way to have such functionality in wordpress, which is described here [AJAX in Plugins](https://codex.wordpress.org/AJAX_in_Plugins). You have to use wordpress AJAX actions and wordpress database object. But if you don't want to get into this, simple change the url of the PHP file in your ajax call and it should work. – Christos Lytras Nov 22 '16 at 21:48
  • @Christos Lytras Actually `ajax-data.php` is on the root directory of my theme. And I also tried the full path of url `http://localhost:8888/wordpress/ajax-data.php` but got the same error. – L. Leo Nov 22 '16 at 22:58
  • #L-Leo, this is not the root directory of "a" theme `http://localhost:8888/wordpress/`, but the root directory of the whole wordpress site. The root directory of a theme, is something like this `/wp-content/themes/twentyfifteen/`. – Christos Lytras Nov 22 '16 at 23:02
  • @Christos Lytras Sorry for that silly mistake, but now nothing is returned in the second box when select the first one – L. Leo Nov 22 '16 at 23:14
  • @Christos Lytras I edit the problem to add a capture – L. Leo Nov 22 '16 at 23:34
  • OK. So, where you want exactly to have the dynamic select boxes? Inside your `index.php`; a wordpress page or a wordpress post? It does not make any sense to have it directly to the `index.php` of your template. Is this file maybe a total different `index.php` page, other than wordpress default `index.php` and theme's `index.php`? – Christos Lytras Nov 22 '16 at 23:55
  • Please visit http://chat.stackoverflow.com/ so I can add you to a chat room so we can talk there. – Christos Lytras Nov 23 '16 at 00:04
  • @Christos Lytras It is part of the theme's `index.php`. I'm now on [chat.stackoverflow.com](http://chat.stackoverflow.com/) – L. Leo Nov 23 '16 at 01:35
  • I still can't add you. Maybe it's your rep or maybe I'm doing something wrong. Rep needs to be > 20 for someone to talk to the chat. – Christos Lytras Nov 23 '16 at 01:49
  • @Christos Lytras It's my problem, I only have 9 rep... – L. Leo Nov 23 '16 at 02:02
  • I have it working on a demo wordpress site that I have. Check it [here](http://demo.wiznet.gr/citytours/hello-world-2/) (it's under the "Hello world!" white panel). I added this to the `single-post.php` because `index.php` of my theme is too complex. I can write an answer and help you make it work, but I have to go now. If you're not in a rush, then I can write it later for you. – Christos Lytras Nov 23 '16 at 02:24
  • @Christos Lytras Thanks a lot! You can do it when you are free. – L. Leo Nov 23 '16 at 02:27

1 Answers1

1

The proper way to do this, is to create a wordpress shortcode and then use that shortcode wherever you want, page or post, but if you want to create something more specific, then you should create a small wordpress plugin. I won't get into this, but it’s really not a big deal to create a simple wordpress plugin having such functionality. I’ll go through the steps on how you can have this working in wordpress with the files and the code you already have. I assume you already have the tables of your example created. My tables are like this:

wp_citytours_dynsel_cities
wp_citytours_dynsel_states
wp_citytours_dynsel_countries

I have imported some data and I have all those tables filled with proper data. I can provide some sql files if you like, but I assume you already have your tables filled with the proper data for each table.

My test theme root directory is:

/wp-content/themes/citytours/

I have created the directory under my theme root directory and I have included all the code files there, so we have 3 files:

/wp-content/themes/citytours/dynsel/index-partial.php

<?php
//Include database configuration file
include('dbConfig.php');

//Get all country data
$query = $db->query("SELECT * FROM wp_citytours_dynsel_countries WHERE status = 1 ORDER BY country_name ASC");

//Count total number of rows
$rowCount = $query->num_rows;
?>
<select name="country" id="country">
    <option value="">Select Country</option>
    <?php
    if($rowCount > 0){
        while($row = $query->fetch_assoc()){ 
            echo '<option value="'.$row['country_id'].'">'.$row['country_name'].'</option>';
        }
    }else{
        echo '<option value="">Country not available</option>';
    }
    ?>
</select>

<select name="state" id="state">
    <option value="">Select country first</option>
</select>

<select name="city" id="city">
    <option value="">Select state first</option>
</select>

<script type="text/javascript">
jQuery(function($) {
    $('#country').on('change',function(){
        var countryID = $(this).val();
        if(countryID){
            $.ajax({
                type:'POST',
                url:'<?php echo home_url('wp-content/themes/citytours/dynsel/ajaxData.php') ?>',
                data:'country_id='+countryID,
                success:function(html){
                    $('#state').html(html);
                    $('#city').html('<option value="">Select state first</option>'); 
                }
            }); 
        }else{
            $('#state').html('<option value="">Select country first</option>');
            $('#city').html('<option value="">Select state first</option>'); 
        }
    });

    $('#state').on('change',function(){
        var stateID = $(this).val();
        if(stateID){
            $.ajax({
                type:'POST',
                url:'<?php echo home_url('wp-content/themes/citytours/dynsel/ajaxData.php') ?>',
                data:'state_id='+stateID,
                success:function(html){
                    $('#city').html(html);
                }
            }); 
        }else{
            $('#city').html('<option value="">Select state first</option>'); 
        }
    });
});
</script>

/wp-content/themes/citytours/dynsel/dbConfig.php

<?php
//db details
$dbHost = 'localhost';
$dbUsername = 'xxxx';
$dbPassword = 'xxxx';
$dbName = 'xxxx';

//Connect and select the database
$db = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName);

if ($db->connect_error) {
    die("Connection failed: " . $db->connect_error);
}
?>

/wp-content/themes/citytours/dynsel/ajaxData.php

<?php
//Include database configuration file
include('dbConfig.php');

if(isset($_POST["country_id"]) && !empty($_POST["country_id"])){
    //Get all state data
    $query = $db->query("SELECT * FROM wp_citytours_dynsel_states WHERE country_id = ".$_POST['country_id']." AND status = 1 ORDER BY state_name ASC");

    //Count total number of rows
    $rowCount = $query->num_rows;

    //Display states list
    if($rowCount > 0){
        echo '<option value="">Select state</option>';
        while($row = $query->fetch_assoc()){ 
            echo '<option value="'.$row['state_id'].'">'.$row['state_name'].'</option>';
        }
    }else{
        echo '<option value="">State not available</option>';
    }
}

if(isset($_POST["state_id"]) && !empty($_POST["state_id"])){
    //Get all city data
    $query = $db->query("SELECT * FROM wp_citytours_dynsel_cities WHERE state_id = ".$_POST['state_id']." AND status = 1 ORDER BY city_name ASC");

    //Count total number of rows
    $rowCount = $query->num_rows;

    //Display cities list
    if($rowCount > 0){
        echo '<option value="">Select city</option>';
        while($row = $query->fetch_assoc()){ 
            echo '<option value="'.$row['city_id'].'">'.$row['city_name'].'</option>';
        }
    }else{
        echo '<option value="">City not available</option>';
    }
}
?>

As you can see, the index-partial.php now contains only needed code, without <body>, <head> and script files included. Wordpress already includes jQuery to the application for most themes, but you should always check that. Now, you can add the functionality wherever you want, even at the theme index.php file, but always with caution. I have used theme's single post template file, which is single-post.php. I have included the example code, under the main post body inside a div. I just include the index-partial.php like this:

<div class="<?php echo esc_attr( $content_class ); ?>">
    <div class="box_style_1">
    ...
    </div><!-- end box_style_1 -->

    <div class="box_style_1">
        <?php include(__DIR__.'/dynsel/index-partial.php'); ?>
    </div>
</div><!-- End col-md-9-->

I also have used the wordpress home_url function, to have a proper url rooted for the ajaxData.php file like this:

url:'<?php echo home_url('wp-content/themes/citytours/dynsel/ajaxData.php') ?>'

Now, if you have followed all these steps, then you should have your code example working at under each post. You can now included it wherever you want by using that line of code <?php include(__DIR__.'/dynsel/index-partial.php'); ?>.

enter image description here

Please let me know if that worked for you.

Christos Lytras
  • 36,310
  • 4
  • 80
  • 113
  • Really appreciate your help! But it still has the same problem show in the capture. I also tried to put the javascript in an independent js file, the console returned an error of `Uncaught SyntaxError: Unexpected identifier` with `url:''` – L. Leo Nov 23 '16 at 19:39
  • Can you update with a screenshot of your chrome/firefox console opened just to see the error? – Christos Lytras Nov 23 '16 at 20:06
  • I just fixed the problem, the mistake is the way I include `dbConfig.php`. The dependent select box is now working. I have a new problem with `action="ps-result.php"`. I will soon update the question. – L. Leo Nov 23 '16 at 20:32
  • That's because `get_header()` is part of the wordpress API, which you do not include into `ps-result.php`. Do you really need the output of the `get_header()` function? – Christos Lytras Nov 23 '16 at 22:30
  • I just found I made a silly mistake again. I should not directly call the php file. I should use the link as `http://localhost:8888/wordpress/part-search-result/`. One simple question: is there any other way to write the link so that I don't need to change it after uploading to the server? – L. Leo Nov 23 '16 at 23:14
  • Can you join this chatroom: http://chat.stackoverflow.com/rooms/128883/dynselwordpress – Christos Lytras Nov 23 '16 at 23:19
  • I am now on my way home. I wonder if you still have time 30 min later. Sorry for any inconvenience. – L. Leo Nov 23 '16 at 23:52
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/128884/discussion-between-christos-lytras-and-l-leo). – Christos Lytras Nov 23 '16 at 23:58
  • I am now in chat. – L. Leo Nov 24 '16 at 00:40