Populate a DataTable with data from a MySQL database

I’m trying to build a CRUD application. I have a MySQL database of a large amount of records and would like to use a JQuery DataTable rather than trying to code out a table from scratch. The problem I have, is that I can see the table on my site, but I cannot get it to pull in the data from MySQL.

I’ve tried reading many site and forums including the official documentation on DataTable’s website, but none of it makes sense to me.

What do I need to do to fix this? I’ve been working on this project for a solid week and am getting frustrated.

// Call the dataTables jQuery plugin
$(document).ready(function() {
  $('#dataTable').DataTable();
});

You can start by showing us your code. We cant see your computer.

@benanamen I hate to say it, but the code above is the only code I have other than the database connector file. I don’t know where to start from there. I’ve read forums, other sites and documentations, but none of it makes sense to me.

Maybe you are looking for this, but you have to adapt it according to your script:

<?php
// use your connection credentials here
 $connect = mysqli_connect("localhost", "root", "", "test");  
// this is only example table 
$query ="SELECT * FROM users ORDER BY ID DESC";  
 $result = mysqli_query($connect, $query);  
 ?>  
 <!DOCTYPE html>  
 <html>  
      <head>  
           <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>  
           <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />  
           <script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>  
           <script src="https://cdn.datatables.net/1.10.12/js/dataTables.bootstrap.min.js"></script>            
           <link rel="stylesheet" href="https://cdn.datatables.net/1.10.12/css/dataTables.bootstrap.min.css" />  
      </head>  
      <body>  
           <br /><br />  
           <div class="container">  
                <div class="table-responsive">  
                     <table id="users" class="table table-striped table-bordered">  
                          <thead>  
                               <tr>  
                                    <td>ID</td>  
                                    <td>Name</td>  
                                    <td>Email</td>  
                               </tr>  
                          </thead>  
                          <?php  
                          while($row = mysqli_fetch_array($result))  
                          {
                               // echoing the fetched data from the database per column names
                               echo '  
                               <tr>
                                    <td>'.$row["id"].'</td>  
                                    <td>'.$row["name"].'</td>  
                                    <td>'.$row["email"].'</td>  
                               </tr>  
                               ';  
                          }  
                          ?>  
                     </table>  
                </div>  
           </div>  
      </body>  
 </html>  
 <script>  
 $(document).ready(function(){  
      $('#users').DataTable();  
 });  
 </script>

I suggest you using either Bootgrid or jsGrid because while refreshing data after sorting, it will stay on the current page where dataTables has problem realizing this, at least I can’t find a workaround as the developer clearly states that it is purposely done.

I had some help from a Stack Overflow forum that I posted in as well and was able to create the code below. However, the data is not pulling into DataTables and I can’t figure out why. I do not see any errors when I reload the webpage, it just doesn’t appear to be working.

Here is the HTML File:

<!DOCTYPE html>
<html lang="en">

<head>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>Cabarrus County Republican Party | Member Database</title>

  <!-- Custom fonts for this template -->
  <link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">

  <!-- Custom styles for this template -->
  <link href="css/sb-admin-2.min.css" rel="stylesheet">

  <!-- Custom styles for this page -->
  <link href="vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">

</head>

<body id="page-top">

  <!-- Page Wrapper -->
  <div id="wrapper">

    <!-- Sidebar -->
    <ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">

      <!-- Sidebar - Brand -->
      <a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
        <!--<div class="sidebar-brand-icon rotate-n-15">
          <i class="fas fa-laugh-wink"></i>
        </div> -->
        <div class="sidebar-brand-text mx-3"><img src="img/republican_logo.png" width = "50" height="50">&nbsp;&nbsp;CCRP</div>
      </a>

      <!-- Divider -->
      <hr class="sidebar-divider my-0">

      <!-- Nav Item - Dashboard -->
      <li class="nav-item active">
        <a class="nav-link" href="index.html">
          <i class="fas fa-fw fa-table"></i>
          <span>Database</span></a>
      </li>

      <!-- Divider -->
      <hr class="sidebar-divider">

      <!-- Heading -->
      <div class="sidebar-heading">
        User Interface
      </div>

      <!-- Nav Item - Pages Collapse Menu -->
      <li class="nav-item">
        <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages" aria-expanded="true" aria-controls="collapsePages">
          <i class="fas fa-fw fa-tachometer-alt"></i>
          <span>Menu</span>
        </a>
        <div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
          <div class="bg-white py-2 collapse-inner rounded">
            <h6 class="collapse-header">Update Database</h6>
            <a class="collapse-item" href="create.html">Add New Members</a>
			<a class="collapse-item" href="#">Email <small>(beta)</small></a>
			<a class="collapse-item" href="#">Mass Email <small>(beta)</small></a>		  	
            <h6 class="collapse-header">User Account</h6>
            <a class="collapse-item" href="login.html">Login</a>
            <a class="collapse-item" href="register.html">Register</a>
            <a class="collapse-item" href="forgot-password.html">Forgot Password</a>
            <div class="collapse-divider"></div>
            <!-- <a class="collapse-item" href="blank.html">Blank Page</a> -->
          </div>
        </div>
      </li>

      <!-- Divider -->
      <hr class="sidebar-divider d-none d-md-block">

      <!-- Sidebar Toggler (Sidebar) -->
      <div class="text-center d-none d-md-inline">
        <button class="rounded-circle border-0" id="sidebarToggle"></button>
      </div>

    </ul>
    <!-- End of Sidebar -->

    <!-- Content Wrapper -->
    <div id="content-wrapper" class="d-flex flex-column">

      <!-- Main Content -->
      <div id="content">

        <!-- Topbar -->
        <nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">

          <!-- Sidebar Toggle (Topbar) -->
          <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
            <i class="fa fa-bars"></i>
          </button>

          <!-- Topbar Search -->
          <form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
            <div class="input-group">
              <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
              <div class="input-group-append">
                <button class="btn btn-primary" type="button">
                  <i class="fas fa-search fa-sm"></i>
                </button>
              </div>
            </div>
          </form>

          <!-- Topbar Navbar -->
          <ul class="navbar-nav ml-auto">

            <!-- Nav Item - Search Dropdown (Visible Only XS) -->
            <li class="nav-item dropdown no-arrow d-sm-none">
              <a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="fas fa-search fa-fw"></i>
              </a>
              <!-- Dropdown - Messages -->
              <div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in" aria-labelledby="searchDropdown">
                <form class="form-inline mr-auto w-100 navbar-search">
                  <div class="input-group">
                    <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
                    <div class="input-group-append">
                      <button class="btn btn-primary" type="button">
                        <i class="fas fa-search fa-sm"></i>
                      </button>
                    </div>
                  </div>
                </form>
              </div>
            </li>

            <!-- <div class="topbar-divider d-none d-sm-block"></div> -->

            <!-- Nav Item - User Information -->
            <li class="nav-item dropdown no-arrow">
              <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <span class="mr-2 d-none d-lg-inline text-gray-600 small">Valerie Luna</span>
                <img class="img-profile rounded-circle" src="https://source.unsplash.com/QAB-WJcbgJk/60x60">
              </a>
              <!-- Dropdown - User Information -->
              <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
                <a class="dropdown-item" href="#">
                  <i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
                  Profile
                </a>
                <a class="dropdown-item" href="#">
                  <i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
                  Settings
                </a>
                <a class="dropdown-item" href="#">
                  <i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
                  Activity Log
                </a>
                <div class="dropdown-divider"></div>
                <a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
                  <i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
                  Logout
                </a>
              </div>
            </li>

          </ul>

        </nav>
        <!-- End of Topbar -->

        <!-- Begin Page Content -->
        <div class="container-fluid">

          <!-- Page Heading -->
          <h1 class="h3 mb-2 text-gray-800">Members List</h1>
          <!-- <p class="mb-4">DataTables is a third party plugin that is used to generate the demo table below. For more information about DataTables, please visit the <a target="_blank" href="https://datatables.net">official DataTables documentation</a>.</p> -->

          <!-- DataTales Example -->
          <div class="card shadow mb-4">
            <div class="card-header py-3">
              <h6 class="m-0 font-weight-bold text-primary">Cabarrus County Republican Party </h6>
            </div>
            <div class="card-body">
              <div class="table-responsive">
                <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
                  <thead>
                    <tr>
					  <th>ID</th>
                      <th>Name</th>
                      <th>Residential Address</th>
                      <th>Mailing Address</th>
                      <th>Precinct</th>
                      <th>Age</th>
                      <th>Ethnicity</th>
					  <th>Gender</th>
					  <th>Party</th>
					  <th>Race</th>
					  <th>Phone Number</th>
                    </tr>
                  </thead>
                  <tfoot>
                    <tr>
					  <th>ID</th>
                      <th>Name</th>
                      <th>Residential Address</th>
                      <th>Mailing Address</th>
                      <th>Precinct</th>
                      <th>Age</th>
                      <th>Ethnicity</th>
					  <th>Gender</th>
					  <th>Party</th>
					  <th>Race</th>
					  <th>Phone Number</th>
                    </tr>
                  </tfoot>
                </table>
              </div>
            </div>
          </div>

        </div>
        <!-- /.container-fluid -->

      </div>
      <!-- End of Main Content -->

      <!-- Footer -->
      <footer class="sticky-footer bg-white">
        <div class="container my-auto">
          <div class="copyright text-center my-auto">
            <span>Copyright &copy; <a href="https://cascosigns.com">Casco Signs Inc.</a> 2019</span>
          </div>
        </div>
      </footer>
      <!-- End of Footer -->

    </div>
    <!-- End of Content Wrapper -->

  </div>
  <!-- End of Page Wrapper -->

  <!-- Scroll to Top Button-->
  <a class="scroll-to-top rounded" href="#page-top">
    <i class="fas fa-angle-up"></i>
  </a>

  <!-- Logout Modal-->
  <div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
          <button class="close" type="button" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
        <div class="modal-footer">
          <button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
          <a class="btn btn-primary" href="login.html">Logout</a>
        </div>
      </div>
    </div>
  </div>

  <!-- Bootstrap core JavaScript-->
  <script src="vendor/jquery/jquery.min.js"></script>
  <script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

  <!-- Core plugin JavaScript-->
  <script src="vendor/jquery-easing/jquery.easing.min.js"></script>

  <!-- Custom scripts for all pages-->
  <script src="js/sb-admin-2.min.js"></script>

  <!-- Page level plugins -->
  <script src="vendor/datatables/jquery.dataTables.min.js"></script>
  <script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>

  <!-- Page level custom scripts -->
  <script src="js/datatables.js"></script>

</body>

</html>

here is the PHP file:

<?php
 
/*
 * DataTables example server-side processing script.
 *
 * Please note that this script is intentionally extremely simple to show how
 * server-side processing can be implemented, and probably shouldn't be used as
 * the basis for a large complex system. It is suitable for simple use cases as
 * for learning.
 *
 * See http://datatables.net/usage/server-side for full details on the server-
 * side processing requirements of DataTables.
 *
 * @license MIT - http://datatables.net/license_mit
 */
 
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Easy set variables
 */
 
// DB table to use
$table = 'members';
 
// Table's primary key
$primaryKey = 'id';
 
// Array of database columns which should be read and sent back to DataTables.
// The `db` parameter represents the column name in the database, while the `dt`
// parameter represents the DataTables column identifier. In this case simple
// indexes
$columns = array(
    array( 'db' => 'id', 'dt' => 0 ),
    array( 'db' => 'name',  'dt' => 1 ),
    array( 'db' => 'residential_address', 'dt' => 2 ),
    array( 'db' => 'mailing_address', 'dt' => 3 ),
    array( 'db' => 'precinct', 'dt' => 4),
    array( 'db' => 'age', 'dt' => 5 ),
    array( 'db' => 'ethnicity',  'dt' => 6 ),
    array( 'db' => 'gender', 'dt' => 7 ),
    array( 'db' => 'party', 'dt' => 8 ),
    array( 'db' => 'race', 'dt' => 9 ),
    array( 'db' => 'phone', 'dt' => 10 )		
);
 
// SQL server connection information
$sql_details = array(
    'user' => 'root',
    'pass' => '',
    'db'   => 'ccrp_db',
    'host' => 'localhost'
);
 
 
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * If you just want to use the basic configuration for DataTables with PHP
 * server-side, there is no need to edit below this line.
 */
 
require( 'ssp.class.php' );
 
echo json_encode(
    SSP::simple( $_GET, $sql_details, $table, $primaryKey, $columns )
);
?>

and here is the datatables.js file that it is calling:

$(document).ready(function() {
    $('#dataTable').DataTable( {
        "processing": true,
        "serverSide": true,
        "ajax": "../api/server.php" // your php file
    });
});

Does the PHP code actually return any data to the calling code? In theory you could just call the PHP code directly and see what it outputs.

You need to figure out whether the JS code is not calling the PHP, the PHP is not returning anything, or the JS is not doing anything with the data returned from PHP, as a first step.

1 Like

If I navigate to where the server file is in my browser, I can see my converted data. I’m not sure what else is required to make the data visible in the table.

OK, so the PHP is working. You might want to remove that screen-shot if any of those are actual people and addresses, though.

I can’t tell how the Ajax code decides where it’s going to insert the data that comes back from the PHP.

How do I call that in? Maybe that’s what I’m missing? Not too sure where to go from here…

Here is your solution as I have tested it and it’s working as a sweet pie.

First, double check if your table in database is named members in the $table variable.

Second, replace all links hrefs and scripts links with the cdn ones just to be sure if you have missed a folder, for example:

<script src="vendor/datatables/jquery.dataTables.min.js"></script>

with:

<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>

Third, delete this line because it is unneeded duplicate:

<!-- Page level custom scripts --> 
<script src="js/datatables.js"></script>

Fourth, right after the last script loaded add this code and double check your ajax sourced data, i.e. your PHP file is named as it is in the ajax option in DataTables (I suggest you for testing, place your server.php in the folder where your index.html is):

<script>
  $(document).ready(function() {
    $('#dataTable').DataTable( {
        "processing": true,
        "serverSide": true,
        "ajax": "server.php" // your php file in the main folder where index.html is located
    });
});
</script>

Fifth, double check in the $columns variable the columns are exact matches as in your table in the SQL database. Let’s say check if ‘id’ in your PHP code matches with your database’s table column named ‘id’:

array( 'db' => 'id', 'dt' => 0 ), // and so on...

That’s it.

It’s been deleted now for privacy reasons, but in post #8 the OP posted a screen shot showing that the PHP code is retrieving data, so that would suggest that the table name is correct. It might also suggest that the column names are correct, I’m not sure whether the code ignores errors in that area, or stops altogether.

It is. That’s how I can see my data when I load the PHP file in the browser.

I’m using a template that has included the files I need to make the table work.

This file contains the script needed to get the table information (which you also posted in your fourth point). Therefore, I cannot delete it.

All of my column names are correct as I can see the data being pulled in from my web browser when I load the PHP file. As @droopsnoot said in his response, I did post a screenshot showing the data being pulled in, however, I had to delete it because they were, in fact, real people’s names and addresses that I cannot release.

I reached out to DataTables and they mentioned that my draw value is incorrect. Mine is 0 and it should be 1. I am not sure what this means or how to change it. Below is the beginning of the output that the PHP file is giving out:

{"draw":0,"recordsTotal":46893,"recordsFiltered":46893...

The PHP code is retrieving data, but as I understood you cannot obtain data with DataTables from SQL and as a result you get empty HTML table, right?

That is true, but I ran the debugger as they suggested and I see the following:



There is an error in Chrome, but I don’t think it has anything to do with my script.

Doesn’t that first screen-shot say there are no rows after the search?

@droopsnoot So it does, but what does that mean as far as setup? Is there something wrong in my script?

It doesn’t look like it, compared to the small example code on their site. Do you have any server logs that tell you whether the PHP code is actually being called? Could you add something like writing to a little file if not, just to see if it’s working? I wonder if the relative URL is correct.

Apparently, I don’t have a PHP log in XAMPP… not sure why that is. I have an apache log, but I can’t open it because the file is too big. I’m not sure how to write out to a file much less what I need to write out.

There’s a function called file_put_contents(), documentation here: https://www.php.net/manual/en/function.file-put-contents.php

That would allow you to write a string into a file that doesn’t already exist, the sole purpose of which is to show whether your PHP is being called or not. Once you know it’s being called (because the file gets created) you can delete the line again.

To me, you obviously have problems getting DataTables and your PHP code in mutual connection. I have made a simulation of what I think you have as a problem and came to a solution:

In your datatables.js please double check that your server.php is located in a folder called api, if not, create it and place server.php there:

"ajax": "../api/server.php"

If your main folder is sbadmin2, your datatables.js is located in a subfolder, for example, called js, the above part of the code gives command to go one folder up from where datatables.js is located and search in subfolder called api where server.php is located.

If you don’t have ssp.class.php for json encoding go here https://github.com/DataTables/DataTables then download the package and when you open the *.zip file search in examples/server_side/scripts and there you will find ssp.class.php.
Copy place that file in api folder, i.e. where server.php is located everything will be fine. The whole point of the problem lies in the inability of server.php code:

require( 'ssp.class.php' );

to locate the ssp.class.php

I hope this will solve your problem. If you don’t understand something, ask here and I will try to clear things out.

1 Like