0

I have several tables that I am using for reports on a website that I built. I have started using DataTables and am trying to convert to using server side processing. I followed the example here and modified it to use what I already have. Here is the completed file(ServerSide.php):

<?php
$Page = '';
if (isset($_GET['PageName']))
{
    //echo "<br>Page = Get<br>";
    $Page = $_GET['PageName'];
}
elseif (isset($_POST['PageName']))
{
    //echo "<br>Page = Post<br>";
    $Page = $_POST['PageName'];
}
//For testing just this page
//if($Page == '')
//{
//  $Page = 'TableHeadings';
//}

include 'DBConn.php';
$headings = array();
$hsql = "select Headings from TableHeadings where TableName = '$Page' order by Id";
$getHeadings = $conn->query($hsql);
$rHeadings = $getHeadings->fetchALL(PDO::FETCH_ASSOC);
$CountHeadings = count($rHeadings);
$tsqlHeadings = '';
$ColumnHeader = array();
for ($row = 0; $row < $CountHeadings; $row++)
{
    $headings[$row] = $rHeadings[$row]["Headings"];
    $tsqlHeadings = $tsqlHeadings . "[" . $headings[$row] . '],';
}

foreach($headings as $index => $columnName)
{
    $ColumnHeader[] = array('db'=>$columnName,'dt'=>$index);
}

//DB table to use
$table = $Page;

//Table's primary key
$primaryKey = 'id';

//Array of database columns which should be read and sent back to DataTables
$columns = $headings;

//SQL server connection information
$sql_details = array(
    'user'=> 'EngsysWebUser',
    'pass'=> 'Fr0ntier2016',
    'db'=> 'EngSys',
    'host'=> 'MAFINFWWAPV01'
);
$connectionInfo = array( "Database"=>$dbname, "UID"=>$username, "PWD"=>$password);
$conn = sqlsrv_connect( $servername, $connectionInfo );
if( $conn === false ) {
    die( print_r( sqlsrv_errors(), true));
}

// Get data to display 
$Query = "
    SELECT count($primaryKey) over() as Row_Count, ".str_replace(" , ", " ", implode(", ", $columns))."
    FROM   $table";

$rResult = sqlsrv_query( $conn, $Query );
if( $rResult === false) {
    die( print_r( sqlsrv_errors(), true) );
}

// Data set length after filtering
$iFilteredTotal = sqlsrv_num_rows( $rResult );

// Total data set length 
$sQuery = "SELECT COUNT($primaryKey)
    FROM $table";
$rResultTotal = sqlsrv_query( $conn, $sQuery );
$aResultTotal = sqlsrv_fetch_array( $rResultTotal, SQLSRV_FETCH_ASSOC);
$iTotal = $aResultTotal;

// Output
$output = array(
    "iTotalRecords" => $iTotal,
    "iTotalDisplayRecords" => $iFilteredTotal,
    "Data" => array()
);

while ( $aRow = sqlsrv_fetch_array( $rResult,SQLSRV_FETCH_ASSOC ) )
{
    $row = array();
    for ( $i=0 ; $i<count($columns) ; $i++ )
    {
        if ( $columns[$i] == "version" )
        {
            // Special output formatting for 'version' column 
            $row[] = ($aRow[ $columns[$i] ]=="0") ? '-' : $aRow[ $columns[$i] ];
        }
        else if ( $columns[$i] != ' ' )
        {
            // General output 
            $row[] = $aRow[ $columns[$i] ];
        }
    }
    $output['Data'][] = $row;
}

echo json_encode($output);
?>

Then I have my other file, which if I'm understanding correctly is supposed to call the previous one(ServerSide.php) and place the json response, formatted as a table, into the tbody of my table(RunningServerSide.php):

<?php
$Page = '';
if (isset($_GET['PageName']))
{
    $Page = $_GET['PageName'];
}
elseif (isset($_POST['PageName']))
{
    $Page = $_POST['PageName'];
}
include 'DBConn.php';
$headings = array();
$hsql = "select Headings from TableHeadings where TableName = '$Page' order by Id";
$getHeadings = $conn->query($hsql);
$rHeadings = $getHeadings->fetchALL(PDO::FETCH_ASSOC);
$CountHeadings = count($rHeadings);
$tsqlHeadings = '';
$ColumnHeader = array();
for ($row = 0; $row < $CountHeadings; $row++)
{
    $headings[$row] = $rHeadings[$row]["Headings"];
    $tsqlHeadings = $tsqlHeadings . "[" . $headings[$row] . '],';
}
$Edit = 0;
?>

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title></title>
        <?php require 'StyleLinks.php'; ?>
        <?php include 'DataTableLinks.php'; ?>
    </head>
    <body>
        <table class="NormalTable display nowrap"  style="width: 100%; border: 1px" id="DataTable">
                <thead>
                    <tr><?php echo "\n";
                            if($Edit == 1)
                            {?>
                        <th class="cell">Edit</th><?php echo "\n";                          
                            }
                            foreach($headings as $heading)
                            {?>
                        <th class="cell"><?php echo $heading; ?></th><?php echo "\n";
                            }?>
                    </tr>
                </thead><?php echo "\n";?>
            </table>
    </body>
</html>

Then just for clarity I have included a couple of files in the head of the second file for styling purposes. They include the CSS that I created for tables and the files that I downloaded from DataTables to have their formatting. Plus on the DataTableLinks.php file I have this to initialize the DataTable:

<script>
    $(document).ready(function ()
    {
        $('#DataTable').DataTable(
      {
          "lengthMenu": [[25, 50, 75, 100, 150], [25, 50, 75, 100, 150]],
          "ScrollX": true,
          "dom": '<"top"Biflp<"clear">>rt<"bottom"ip<"clear">>',
          buttons: [{ extend: 'collection', text: 'Selection', buttons: ['selectAll', 'selectNone'] }, { extend: 'collection', text: 'Export', buttons: ['excel', 'csv', 'pdf']}],
          fixedHeader: { header: true, footer: false },
          select: true,
          "processing": true,
          "serverSide": true,
          "ajax": { "url": "ServerSide.php", "dataType": "jsonp", "success": function(data){$('#DataTable').append(data);} }
      });
    });
</script>

I have worked on correcting issues that I found in the console(F12) and there are no longer any problems there. But I still only get the 2 buttons and the table header and then a pop-up that says:

DataTables warning: table id=DataTable - Invalid JSON response. For more information about this error, please see http://datatables.net/tn/1

The link in that error message says to check the response in the Network portion of the Developer Tools. In there it looks fine to me, but I've never used DataTables before and I've only been working with JSON and AJAX for about a week now. The Response looks like this:

Respnse

And the Preview tab like this:

enter image description here

Gyrocode.com
  • 57,606
  • 14
  • 150
  • 185
Mike
  • 1,853
  • 3
  • 45
  • 75
  • 1
    [Little Bobby](http://bobby-tables.com/) says ***[your script is at risk for SQL Injection Attacks.](http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php)***. Even [escaping the string](http://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string) is not safe! ***SQL Injection!*** *It's not just for breakfast any more!* – Jay Blanchard Nov 09 '16 at 17:20
  • you have no success function for ajax – Mohamed Athif Nov 09 '16 at 17:22
  • @JayBlanchard This is an internal only site so that will limit the threat. And there are no open text boxes for adding anything to my SQL, only a few drop down lists. I do plan on converting the SQL to use PDO `prepare` statements, but I want to get this working first. – Mike Nov 09 '16 at 17:51
  • @MohamedAthif I don't know what you mean about the success function for ajax. Is there a link that would explain that? – Mike Nov 09 '16 at 17:51
  • 2
    I hate when people say *"I'm not that far along..."* or *"This site will not be public..."* or *"It's only for school, so security doesn't matter..."*. If teachers and professors are not talking about security from day one, they're doing it wrong. Challenge them. They're teaching sloppy and dangerous coding practices which students will have to unlearn later. I also hate it when folks say, *"I'll add security later..."* or *"Security isn't important now..."* or *"Ignore the security risk..."*. If you don't have time to do it right the first time, when will you find the time to add it later? – Jay Blanchard Nov 09 '16 at 17:52
  • 1
    _This is an internal only site so that will limit the threat_ Most hacks start inside the business or are assisted by internal staff. ___So that excuse is totally bogus___ – RiggsFolly Nov 09 '16 at 17:55
  • @JayBlanchard Right now there is only one user of the site, me. Before I let it go to more users I'll have the security in place. But I need to have the tables showing first. I'm not using the PDO `prepare` yet because it's easier to print the sql without that. Once this is working it'll be pretty easy to add that in. My professors in school did preach about security and I did listen. It will be secure before it goes out to the rest of those who will be using it. – Mike Nov 09 '16 at 17:55

1 Answers1

1

you ajax should have a success function as to what should it do with the response received once it is a success. below i am telling to append the response to the data table. just a basic idea

$.ajax({

  "url": "ServerSide.php",
  "dataType": "jsonp",
  "success": function(response) {
     $('#DataTable').append(response);
   }
})

Edit: as per conversation modify your files as below.

RunningServerSide.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title></title>

    <link rel="stylesheet" href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css">
    <script src="//code.jquery.com/jquery-1.12.3.js"></script>
    <script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
    <style>
        td {text-align:center;}
    </style>
</head>
<body>
<table class="NormalTable display nowrap"  style="width: 100%; border: 1px" id="DataTable">

    </table>

<script>
    $(document).ready(function ()
    {

        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });

        $.ajax({
            url: 'ServerSide.php',
            success: function(response) {
                $('#DataTable').append(response).DataTable({
                    bSort: false,
                    aoColumns: [ { sWidth: "45%" }, { sWidth: "45%" }, { sWidth: "10%", bSearchable: false, bSortable: false } ],
                    "scrollY":        "200px",
                    "scrollCollapse": true,
                    "info":           true,
                    "paging":         true
                } );

            }
        })

    });
</script>
</body>
</html>

ServerSide.php

<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "tester";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT * FROM mike";
$result = $conn->query($sql);

echo "<thead>
                <tr>
                    <th>ID</th>
                    <th>TableName</th>
                    <th>Headings</th>
                </tr>
                </thead>
                <tfoot>
                <tr>
                    <th>ID</th>
                    <th>TableName</th>
                    <th>Headings</th>
                </tr>
                </tfoot>
                <tbody>";
if ($result->num_rows > 0) {
    // output data of each row
    while($row = $result->fetch_assoc()) {

        echo"<tr><td>" . $row["Id"]. "</td><td>" . $row["TableName"]. "</td><td>" . $row["Headings"]. "</td></tr>";

    }
} else {
    echo "0 results";
}

echo"</tbdoy>";
$conn->close();
?>
Mohamed Athif
  • 468
  • 2
  • 6
  • 19
  • So this would go with the `script` that is initializing the DataTable? or is this a separate script that I'll need? – Mike Nov 09 '16 at 18:02
  • modify your script with this. – Mohamed Athif Nov 09 '16 at 18:03
  • I tried adding `"success": function(data){$('#DataTable').append(data);}` to what I already have for the initializing of the DataTable, inside the `"ajax":` part. But it doesn't seem to do anything. How do I figure out that the `function(data)` is supposed to be called. I thought it would be `data` or `response`, but neither will return anything. – Mike Nov 09 '16 at 18:16
  • it can be anything. try changing the dataType to json, rather than jsonp – Mohamed Athif Nov 09 '16 at 18:19
  • can i ask what exactly are you trying to achieve – Mohamed Athif Nov 09 '16 at 18:20
  • I am trying to use DataTables to format my tables and I have result sets that are too large to render client side. So I'm trying to do this server side. From what I've read to do this I have to use json. The response is supposed to be formatted on the client side into a table that is very customizable. – Mike Nov 09 '16 at 18:40
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/127742/discussion-between-mohamed-athif-and-mike). – Mohamed Athif Nov 09 '16 at 18:43
  • So it doesn't matter what is in the function? How does it know what the response is? – Mike Nov 09 '16 at 18:43