Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php DataTables 1.10具有返回“null”值响应的表联接的服务器端_Php_Sql_Pdo_Jquery Datatables - Fatal编程技术网

Php DataTables 1.10具有返回“null”值响应的表联接的服务器端

Php DataTables 1.10具有返回“null”值响应的表联接的服务器端,php,sql,pdo,jquery-datatables,Php,Sql,Pdo,Jquery Datatables,我正在尝试修改DataTables 1.10的默认服务器端脚本(最新版本,目前处于测试阶段),以允许表连接和自定义“WHERE”条件。“WHERE”条件工作得很好,就像我之前做的那样,但是,我在表联接方面遇到了一些问题。我在前面取得了一些进展,我不再收到firebug中的任何错误,但是每行的所有列都返回一个空值作为响应。换句话说,我的表格显示在页面上,每行都有空列 我尝试过datatables论坛,但没有得到太多的运气。为简单起见,我没有包括所有内容,但也包括了服务器端php处理脚本和ssp.c

我正在尝试修改DataTables 1.10的默认服务器端脚本(最新版本,目前处于测试阶段),以允许表连接和自定义“WHERE”条件。“WHERE”条件工作得很好,就像我之前做的那样,但是,我在表联接方面遇到了一些问题。我在前面取得了一些进展,我不再收到firebug中的任何错误,但是每行的所有列都返回一个空值作为响应。换句话说,我的表格显示在页面上,每行都有空列

我尝试过datatables论坛,但没有得到太多的运气。为简单起见,我没有包括所有内容,但也包括了服务器端php处理脚本和ssp.class.php脚本

processing.php:

ssp.class.php:

进一步信息-在下面显示的代码的这一点查看$数据将返回所有正确的值

$data = SSP::sql_exec( $db, $bindings,
    "SELECT SQL_CALC_FOUND_ROWS ".implode(", ", SSP::pluck($columns, 'db'))."
     FROM $table
     $myJoin
     $where
     $order
     $limit"
);
以下是返回数组的第一行的一部分,其中包含上面的正确值:

[3] => Array
    (
        [settings_id] => 1
        [0] => 1
        [user_id] => 11
        [1] => 11
        [username] => steve
        [2] => steve
        [computer_name] => TESTING
        [3] => TESTING
        [disable_desktop] => 1
        [4] => 1
        [disable_start] => 0
        [5] => 0
        [disable_shutdown] => 0
        [6] => 0
        [disable_run] => 0
        [7] => 0
        [disable_mouse] => 0
        [8] => 0
        [disable_bootkeys] => 0
        [9] => 0
        [disable_cp] => 0
        [10] => 0
        [disable_network] => 0
        [11] => 0
        [disable_taskbar] => 0
        [12] => 0
        [disable_clock] => 0
        [13] => 0
        [disable_logoff] => 0
        [14] => 0
        [disable_startchange] => 0
        [15] => 0
        [disable_taskman] => 0
        [16] => 0
        [disable_clipboard] => 0
        [17] => 0
        [disable_drives] => 0
        [18] => 0
    )
不完全确定这是否是正确的输出,但是,我相信这是因为您可以通过名称或索引引用datatables中的数据,这将解释此输出

编辑:

我把问题缩小了一点。静态函数数据_输出$primaryKey、$columns、$data是问题的一部分,正如预期的那样$primaryKey和$columns具有正确的值,但是,$data没有

在函数中,当您到达实际设置值的部分时,数组中没有要设置的值

$row[$column['dt']]=$data[$i][$columns[$j]['db']]


这里$row[$column['dt']]是正确的,但是$data[$i][$columns[$j]['db']];没有db值。正如您在$data的示例输出中所看到的,上面的db值不存在,而是作为相同值的dt值以及索引。通过将其更改为dt,我的表显示数据,然而,这打破了其他一些东西。我不知道为什么$data没有像它应该包含的那样包含db值。

对ssp进行了一些更改,使其正常工作。已更改的包括选择x作为x,以确保获取正确的表列以及对数据输出函数的微小更改$数据现在已正确返回。有点黑,可以清理,但它在所有的测试,我已经做了迄今为止的作品

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 )
    {
        //show $data values in file since it cannot be echo'ed out
        //file_put_contents('/home/test/public_html/filename.txt', print_r($data, true));

        $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['dt'] ], $data[$i] );
                }
                else {
                    $row[ $column['dt'] ] = $data[$i][ $columns[$j]['dt'] ];
                }

            }

            $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
     EDIT : added $mywhere functionality for passing initial filtering conditions
     */
    static function filter ( $request, $columns, &$bindings, $myWhere )
    {
        $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 ', $globalSearch) :
                $where .' AND '. implode(' AND ', $globalSearch);
        }

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

            // add my clause
            if ($myWhere !== '') {
                $where .= ' AND '.$myWhere;
            }
        }

        if ( $where == '' && $myWhere !== '') {
            // add my clause
            $where = 'WHERE '.$myWhere;
        }       

        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, $db, $table, $primaryKey, $columns, $myJoin, $myWhere )
    {
        $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, $myWhere );    

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

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

        //add my initial where clause for correct results
        $dataWhere = ($myWhere !== '' ? 'WHERE '.$myWhere : '');

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

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

    }

    /**
     * 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;
    }

    /**
     * Create and return select array in the format `db` AS `dt` 
     * returning and array of the property values from each item.
     *
     *  @param  array  $a    Array to get data from
     *  @return array        Array of property values
     */
    static function pluckAs ( $a )
    {
        $out = array();

        for ( $i=0, $len=count($a) ; $i<$len ; $i++ ) {
            $out[] = $a[$i]['db']." AS `".$a[$i]['dt']."`";
        }

        return $out;
    }

}

看一看:emranulhadi提供了一个定制的SSP类,用于实现连接和附加条件,其中:


Github上提供:

对于脚本中的记录,有一个bug,下一行:

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

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

我已经搜索了好几天了,但这是php脚本文件中的错误

尝试转储整个查询并直接执行到mysql命令行,看看是否有任何错误。如果我理解正确,那就没有什么帮助了。我可以很容易地查询数据库与我想要的。。。这是一个修改此脚本以接受我所追求的表联接的问题。正在正确返回draw、recordsTotal和recordsFiltered。data=>SSP::data\u输出$primaryKey、$columns、$data似乎是问题所在,因为所有列都返回null。能否尝试在SSP::sql\u exec之后转储$data变量,
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 )
    {
        //show $data values in file since it cannot be echo'ed out
        //file_put_contents('/home/test/public_html/filename.txt', print_r($data, true));

        $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['dt'] ], $data[$i] );
                }
                else {
                    $row[ $column['dt'] ] = $data[$i][ $columns[$j]['dt'] ];
                }

            }

            $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
     EDIT : added $mywhere functionality for passing initial filtering conditions
     */
    static function filter ( $request, $columns, &$bindings, $myWhere )
    {
        $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 ', $globalSearch) :
                $where .' AND '. implode(' AND ', $globalSearch);
        }

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

            // add my clause
            if ($myWhere !== '') {
                $where .= ' AND '.$myWhere;
            }
        }

        if ( $where == '' && $myWhere !== '') {
            // add my clause
            $where = 'WHERE '.$myWhere;
        }       

        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, $db, $table, $primaryKey, $columns, $myJoin, $myWhere )
    {
        $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, $myWhere );    

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

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

        //add my initial where clause for correct results
        $dataWhere = ($myWhere !== '' ? 'WHERE '.$myWhere : '');

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

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

    }

    /**
     * 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;
    }

    /**
     * Create and return select array in the format `db` AS `dt` 
     * returning and array of the property values from each item.
     *
     *  @param  array  $a    Array to get data from
     *  @return array        Array of property values
     */
    static function pluckAs ( $a )
    {
        $out = array();

        for ( $i=0, $len=count($a) ; $i<$len ; $i++ ) {
            $out[] = $a[$i]['db']." AS `".$a[$i]['dt']."`";
        }

        return $out;
    }

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