«

»

Şub 08

PHP-Server-Side Processing

Kullanılan bileşenler:

  • mariadb  Ver 15.1 Distrib 10.6.16-MariaDB, for debian-linux-gnu (x86_64) using  EditLine wrapper
  • Ubuntu 22.04.3 LTS
  • PHP 8.1.2-1ubuntu2.14 (cli) (built: Aug 18 2023 11:41:11) (NTS)

 

Örnek bir database (ister console ister phpmyadmin üzerinden create edilen):

CREATE TABLE PersonelBilgi (
id int(11) NOT NULL,
name varchar(32) COLLATE utf8_unicode_ci NOT NULL,
surname varchar(32) COLLATE utf8_unicode_ci NOT NULL,
birthday date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

 

Datatable’ler (https://datatables.net/) büyük boyutta veri ve satırlarda yavaşlamalar olur bunun nedeni son kullanıcı tarafındaki tarayıcılar ve pc kaynaklarıdır. Bu işlemi son kullanıcı yerine sunucu tarafında yapma işlemi server-side-processing olarak karşımıza çıkar.

 

 

Örnek bir html:

<!-- h4ck3r.html-->
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="initial-scale=1.0, maximum-scale=2.0">
	<title>PHP-Server-Side Processing for Datatables</title>
	<link rel="stylesheet" type="text/css" href="media/css/jquery.dataTables.css">
	<script type="text/javascript" language="javascript" src="media/js/jquery.js"></script>
	<script type="text/javascript" language="javascript" src="media/js/jquery.dataTables.js"></script>
	
	<script type="text/javascript" language="javascript" class="init">
		$(document).ready(function() {
			$('#example').dataTable( {
				"processing": true,
				"serverSide": true,
				"ajax": "scripts/SP.php"
			} );
		} );
	</script>
</head>

<body class="dt-example">
	<div class="container">
		<section>
			<table id="example" class="display" cellspacing="0" width="100%">
				<thead>
					<tr>
						<th>ID</th>
						<th>Name</th>
						<th>Surname</th>
						<th>Birthday</th>
					</tr>
				</thead>

				<tfoot>
					<tr>
						<th>ID</th>
						<th>Name</th>
						<th>Surname</th>
						<th>Birthday</th>
					</tr>
				</tfoot>
			</table>
		</section>
	</div>	
</body>
</html>


Sunucu tarafında işlemi yapacak PHP: SP.php
<?php

$table = "PersonelBilgi";
$primaryKey = 'id';
$columns = array(
    array('db' => 'id',     'dt' => 0), /* dt sırasını indexi*/
    array('db' => 'name',     'dt' => 1), /* Field'ler Vt de yazıldığı gibi*/
    array('db' => 'surname',  'dt' => 2), /* Hepsini yazmak zorunda değilsiniz */ 
    array('db' => 'birthday',   'dt' => 3) /* h4ck3r.html de table karşılığına göre ayarlanmalıdır*/ 
);

$host      ="localhost";
$username  ="h4ck3r";
$pass      ="Esr5XyAlp24*";
$vt        ="PersonelDB24";

$sql_details = array(
    'user' => $username,
    'pass' => $pass,
    'db'   => $vt,
    'host' => $host
);

require( 'datatablessp.class.php' );
 
echo json_encode(
    SSP::simple( $_GET, $sql_details, $table, $primaryKey, $columns )
);




datatablessp.class.php:

<?php

/*
 * Helper functions for building a DataTables server-side processing SQL query
 *
 * The static functions in this class are just helper functions to help build
 * the SQL used in the DataTables demo server-side processing scripts. These
 * functions obviously do not represent all that can be done with server-side
 * processing, they are intentionally simple to show how it works. More complex
 * server-side processing operations will likely require a custom script.
 *
 * 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
 */


// REMOVE THIS BLOCK - used for DataTables test environment only!
// $file = $_SERVER['DOCUMENT_ROOT'].'/datatables/mysql.php';
// if ( is_file( $file ) ) {
// include( $file );
// }


class SSP {
 /**
 * Create the data output array for the DataTables rows
 *
 * @param array $columns Column information array
 * @param array $data Data from the SQL get
 * @return array Formatted data in a row based format
 */
 static function data_output ( $columns, $data )
 {
 $out = array();

 for ( $i=0, $ien=count($data) ; $i<$ien ; $i++ ) {
 $row = array();

 for ( $j=0, $jen=count($columns) ; $j<$jen ; $j++ ) {
 $column = $columns[$j];

 // Is there a formatter?
 if ( isset( $column['formatter'] ) ) {
 $row[ $column['dt'] ] = $column['formatter']( $data[$i][ $column['db'] ], $data[$i] );
 }
 else {
 $row[ $column['dt'] ] = $data[$i][ $columns[$j]['db'] ];
 }
 }

 $out[] = $row;
 }

 return $out;
 }


 /**
 * Paging
 *
 * Construct the LIMIT clause for server-side processing SQL query
 *
 * @param array $request Data sent to server by DataTables
 * @param array $columns Column information array
 * @return string SQL limit clause
 */
 static function limit ( $request, $columns )
 {
 $limit = '';

 if ( isset($request['start']) && $request['length'] != -1 ) {
 $limit = "LIMIT ".intval($request['start']).", ".intval($request['length']);
 }

 return $limit;
 }


 /**
 * Ordering
 *
 * Construct the ORDER BY clause for server-side processing SQL query
 *
 * @param array $request Data sent to server by DataTables
 * @param array $columns Column information array
 * @return string SQL order by clause
 */
 static function order ( $request, $columns )
 {
 $order = '';

 if ( isset($request['order']) && count($request['order']) ) {
 $orderBy = array();
 $dtColumns = SSP::pluck( $columns, 'dt' );

 for ( $i=0, $ien=count($request['order']) ; $i<$ien ; $i++ ) {
 // Convert the column index into the column data property
 $columnIdx = intval($request['order'][$i]['column']);
 $requestColumn = $request['columns'][$columnIdx];

 $columnIdx = array_search( $requestColumn['data'], $dtColumns );
 $column = $columns[ $columnIdx ];

 if ( $requestColumn['orderable'] == 'true' ) {
 $dir = $request['order'][$i]['dir'] === 'asc' ?
 'ASC' :
 'DESC';

 $orderBy[] = '`'.$column['db'].'` '.$dir;
 }
 }

 $order = 'ORDER BY '.implode(', ', $orderBy);
 }

 return $order;
 }


 /**
 * Searching / Filtering
 *
 * Construct the WHERE clause for server-side processing SQL query.
 *
 * NOTE this does not match the built-in DataTables filtering which does it
 * word by word on any field. It's possible to do here performance on large
 * databases would be very poor
 *
 * @param array $request Data sent to server by DataTables
 * @param array $columns Column information array
 * @param array $bindings Array of values for PDO bindings, used in the
 * sql_exec() function
 * @return string SQL where clause
 */
 static function filter ( $request, $columns, &$bindings )
 {
 $globalSearch = array();
 $columnSearch = array();
 $dtColumns = SSP::pluck( $columns, 'dt' );

 if ( isset($request['search']) && $request['search']['value'] != '' ) {
 $str = $request['search']['value'];

 for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
 $requestColumn = $request['columns'][$i];
 $columnIdx = array_search( $requestColumn['data'], $dtColumns );
 $column = $columns[ $columnIdx ];

 if ( $requestColumn['searchable'] == 'true' ) {
 $binding = SSP::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
 $globalSearch[] = "`".$column['db']."` LIKE ".$binding;
 }
 }
 }

 // Individual column filtering
 for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
 $requestColumn = $request['columns'][$i];
 $columnIdx = array_search( $requestColumn['data'], $dtColumns );
 $column = $columns[ $columnIdx ];

 $str = $requestColumn['search']['value'];

 if ( $requestColumn['searchable'] == 'true' &&
 $str != '' ) {
 $binding = SSP::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
 $columnSearch[] = "`".$column['db']."` LIKE ".$binding;
 }
 }

 // Combine the filters into a single string
 $where = '';

 if ( count( $globalSearch ) ) {
 $where = '('.implode(' OR ', $globalSearch).')';
 }

 if ( count( $columnSearch ) ) {
 $where = $where === '' ?
 implode(' AND ', $columnSearch) :
 $where .' AND '. implode(' AND ', $columnSearch);
 }

 if ( $where !== '' ) {
 $where = 'WHERE '.$where;
 }

 return $where;
 }


 /**
 * Perform the SQL queries needed for an server-side processing requested,
 * utilising the helper functions of this class, limit(), order() and
 * filter() among others. The returned array is ready to be encoded as JSON
 * in response to an SSP request, or can be modified if needed before
 * sending back to the client.
 *
 * @param array $request Data sent to server by DataTables
 * @param array $sql_details SQL connection details - see sql_connect()
 * @param string $table SQL table to query
 * @param string $primaryKey Primary key of the table
 * @param array $columns Column information array
 * @return array Server-side processing response array
 */
 static function simple ( $request, $sql_details, $table, $primaryKey, $columns )
 {
 $bindings = array();
 $db = SSP::sql_connect( $sql_details );

 // Build the SQL query string from the request
 $limit = SSP::limit( $request, $columns );
 $order = SSP::order( $request, $columns );
 $where = SSP::filter( $request, $columns, $bindings );

 // Main query to actually get the data
 $data = SSP::sql_exec( $db, $bindings,
 "SELECT SQL_CALC_FOUND_ROWS `".implode("`, `", SSP::pluck($columns, 'db'))."`
 FROM `$table`
 $where
 $order
 $limit"
 );

 // Data set length after filtering
 $resFilterLength = SSP::sql_exec( $db,
 "SELECT FOUND_ROWS()"
 );
 $recordsFiltered = $resFilterLength[0][0];

 // Total data set length
 $resTotalLength = SSP::sql_exec( $db,
 "SELECT COUNT(`{$primaryKey}`)
 FROM `$table`"
 );
 $recordsTotal = $resTotalLength[0][0];


 /*
 * Output
 */
 return array(
 "draw" => intval( $request['draw'] ),
 "recordsTotal" => intval( $recordsTotal ),
 "recordsFiltered" => intval( $recordsFiltered ),
 "data" => SSP::data_output( $columns, $data )
 );
 }


 /**
 * Connect to the database
 *
 * @param array $sql_details SQL server connection details array, with the
 * properties:
 * * host - host name
 * * db - database name
 * * user - user name
 * * pass - user password
 * @return resource Database connection handle
 */
 static function sql_connect ( $sql_details )
 {
 try {
 $db = @new PDO(
 "mysql:host={$sql_details['host']};dbname={$sql_details['db']};charset=UTF8",
 $sql_details['user'],
 $sql_details['pass'],
 array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION )
 );
 }
 catch (PDOException $e) {
 SSP::fatal(
 "An error occurred while connecting to the database. ".
 "The error reported by the server was: ".$e->getMessage()
 );
 }

 return $db;
 }


 /**
 * Execute an SQL query on the database
 *
 * @param resource $db Database handler
 * @param array $bindings Array of PDO binding values from bind() to be
 * used for safely escaping strings. Note that this can be given as the
 * SQL query string if no bindings are required.
 * @param string $sql SQL query to execute.
 * @return array Result from the query (all rows)
 */
 static function sql_exec ( $db, $bindings, $sql=null )
 {
 // Argument shifting
 if ( $sql === null ) {
 $sql = $bindings;
 }

 $stmt = $db->prepare( $sql );
 //echo $sql;

 // Bind parameters
 if ( is_array( $bindings ) ) {
 for ( $i=0, $ien=count($bindings) ; $i<$ien ; $i++ ) {
 $binding = $bindings[$i];
 $stmt->bindValue( $binding['key'], $binding['val'], $binding['type'] );
 }
 }

 // Execute
 try {
 $stmt->execute();
 }
 catch (PDOException $e) {
 SSP::fatal( "An SQL error occurred: ".$e->getMessage() );
 }

 // Return all
 return $stmt->fetchAll();
 }


 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Internal methods
 */

 /**
 * Throw a fatal error.
 *
 * This writes out an error message in a JSON string which DataTables will
 * see and show to the user in the browser.
 *
 * @param string $msg Message to send to the client
 */
 static function fatal ( $msg )
 {
 echo json_encode( array( 
 "error" => $msg
 ) );

 exit(0);
 }

 /**
 * Create a PDO binding key which can be used for escaping variables safely
 * when executing a query with sql_exec()
 *
 * @param array &$a Array of bindings
 * @param * $val Value to bind
 * @param int $type PDO field type
 * @return string Bound key to be used in the SQL where this parameter
 * would be used.
 */
 static function bind ( &$a, $val, $type )
 {
 $key = ':binding_'.count( $a );

 $a[] = array(
 'key' => $key,
 'val' => $val,
 'type' => $type
 );

 return $key;
 }


 /**
 * Pull a particular property from each assoc. array in a numeric array, 
 * returning and array of the property values from each item.
 *
 * @param array $a Array to get data from
 * @param string $prop Property to read
 * @return array Array of property values
 */
 static function pluck ( $a, $prop )
 {
 $out = array();

 for ( $i=0, $len=count($a) ; $i<$len ; $i++ ) {
 $out[] = $a[$i][$prop];
 }

 return $out;
 }
}


Umarım herkese faydalı olur :)

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

AlphaOmega Captcha Classica  –  Enter Security Code
     
 

Şu HTML etiketlerini ve özelliklerini kullanabilirsiniz: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>