微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

数据表 UTF-8 问题

如何解决数据表 UTF-8 问题

使用带有到 MysqL 表的服务器端连接的数据表,我想显示包含像 ö ä õ 这样的 UTF8 字符的表数据。

它不适用于认示例。参考https://datatables.net/examples/server_side/simple.html

错误

DataTables 警告:table id=example - Ajax 错误。有关此错误的详细信息,请参阅 http://datatables.net/tn/7 如何让它发挥作用?

JS:

$(document).ready(function() {
$('#example').DataTable( {
    "processing": true,"serverSide": true,"ajax": "scripts/server_processing.PHP"
} );
} );

HTML:

<table id="example" class="display" style="width:100%">
    <thead>
        <tr>
            <th>First name</th>
            <th>Last name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Start date</th>
            <th>Salary</th>
        </tr>
    </thead>
    <tfoot>
        <tr>
            <th>First name</th>
            <th>Last name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Start date</th>
            <th>Salary</th>
        </tr>
    </tfoot>
</table>

PHP

<?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 = 'datatables_demo';
 
// 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' => 'first_name','dt' => 0 ),array( 'db' => 'last_name','dt' => 1 ),array( 'db' => 'position','dt' => 2 ),array( 'db' => 'office','dt' => 3 ),array(
        'db'        => 'start_date','dt'        => 4,'formatter' => function( $d,$row ) {
            return date( 'jS M y',strtotime($d));
        }
    ),array(
        'db'        => 'salary','dt'        => 5,$row ) {
            return '$'.number_format($d);
        }
    )
);
 
// sql server connection information
$sql_details = array(
    'user' => '','pass' => '','db'   => '','host' => ''
);
 
 
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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 )
);

ssp.class.pp

<?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
 */


// Please Remove below 4 lines as this is use in Datatatables test environment for your local or live environment please remove it or else it will not work
$file = $_SERVER['DOCUMENT_ROOT'].'/datatables/pdo.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'] ) ) {
                    if(empty($column['db'])){
                        $row[ $column['dt'] ] = $column['formatter']( $data[$i] );
                    }
                    else{
                        $row[ $column['dt'] ] = $column['formatter']( $data[$i][ $column['db'] ],$data[$i] );
                    }
                }
                else {
                    if(!empty($column['db'])){
                        $row[ $column['dt'] ] = $data[$i][ $columns[$j]['db'] ];
                    }
                    else{
                        $row[ $column['dt'] ] = "";
                    }
                }
            }

            $out[] = $row;
        }

        return $out;
    }


    /**
     * Database connection
     *
     * Obtain an PHP PDO connection from a connection details array
     *
     *  @param  array $conn sql connection details. The array should have
     *    the following properties
     *     * host - host name
     *     * db   - database name
     *     * user - user name
     *     * pass - user password
     *  @return resource PDO connection
     */
    static function db ( $conn )
    {
        if ( is_array( $conn ) ) {
            return self::sql_connect( $conn );
        }

        return $conn;
    }


    /**
     * 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 = self::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 ];
                
                //**ADDED THIS**
                if(mb_detect_encoding($request["search"]["value"])=="UTF-8"){
                    if($column['db']=="keep_alive" || $column['db']=="Now_playing_start"){
                        continue;
                    }
                }
                
                if ( $requestColumn['orderable'] == 'true' ) {
                    $dir = $request['order'][$i]['dir'] === 'asc' ?
                        'ASC' :
                        'DESC';

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

            if ( count( $orderBy ) ) {
                $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 = self::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' ) {
                    if(!empty($column['db'])){
                        $binding = self::bind( $bindings,'%'.$str.'%',PDO::ParaM_STR );
                        $globalSearch[] = "`".$column['db']."` LIKE ".$binding;
                    }
                }
            }
        }

        // Individual column filtering
        if ( isset( $request['columns'] ) ) {
            for ( $i=0,$dtColumns );
                $column = $columns[ $columnIdx ];

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

                if ( $requestColumn['searchable'] == 'true' &&
                 $str != '' ) {
                    if(!empty($column['db'])){
                        $binding = self::bind( $bindings,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|PDO $conn PDO connection resource or connection parameters array
     *  @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,$conn,$columns )
    {
        $bindings = array();
        $db = self::db( $conn );

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

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

        // Data set length after filtering
        $resFilterLength = self::sql_exec( $db,"SELECT COUNT(`{$primaryKey}`)
             FROM   `$table`
             $where"
        );
        $recordsFiltered = $resFilterLength[0][0];

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

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


    /**
     * The difference between this method and the `simple` one,is that you can
     * apply additional `where` conditions to the sql queries. These can be in
     * one of two forms:
     *
     * * 'Result condition' - This is applied to the result set,but not the
     *   overall paging information query - i.e. it will not effect the number
     *   of records that a user sees they can have access to. This should be
     *   used when you want apply a filtering condition that the user has sent.
     * * 'All condition' - This is applied to all queries that are made and
     *   reduces the number of records that the user can access. This should be
     *   used in conditions where you don't want the user to ever have access to
     *   particular records (for example,restricting by a login id).
     *
     *  @param  array $request Data sent to server by DataTables
     *  @param  array|PDO $conn PDO connection resource or connection parameters array
     *  @param  string $table sql table to query
     *  @param  string $primaryKey Primary key of the table
     *  @param  array $columns Column information array
     *  @param  string $whereResult WHERE condition to apply to the result set
     *  @param  string $whereAll WHERE condition to apply to all queries
     *  @return array          Server-side processing response array
     */
    static function complex ( $request,$whereResult=null,$whereAll=null )
    {
        $bindings = array();
        $db = self::db( $conn );
        $localWhereResult = array();
        $localWhereAll = array();
        $whereAllsql = '';

        // Build the sql query string from the request
        $limit = self::limit( $request,$bindings );

        $whereResult = self::_flatten( $whereResult );
        $whereAll = self::_flatten( $whereAll );

        if ( $whereResult ) {
            $where = $where ?
                $where .' AND '.$whereResult :
                'WHERE '.$whereResult;
        }

        if ( $whereAll ) {
            $where = $where ?
                $where .' AND '.$whereAll :
                'WHERE '.$whereAll;

            $whereAllsql = 'WHERE '.$whereAll;
        }

        // Main query to actually get the data
        $data = self::sql_exec( $db,"SELECT COUNT(`{$primaryKey}`)
             FROM   `$table` ".
            $whereAllsql
        );
        $recordsTotal = $resTotalLength[0][0];

        /*
         * Output
         */
        return array(
            "draw"            => isset ( $request['draw'] ) ?
                intval( $request['draw'] ) :
                0,$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']}",$sql_details['user'],$sql_details['pass'],array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION )
            );
        }
        catch (PDOException $e) {
            self::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,$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) {
            self::fatal( "An sql error occurred: ".$e->getMessage() );
        }

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


    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * 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++ ) {
            if ( empty($a[$i][$prop]) && $a[$i][$prop] !== 0 ) {
                continue;
            }

            //removing the $out array index confuses the filter method in doing proper binding,//adding it ensures that the array data are mapped correctly
            $out[$i] = $a[$i][$prop];
        }

        return $out;
    }


    /**
     * Return a string from an array or a string
     *
     * @param  array|string $a Array to join
     * @param  string $join glue for the concatenation
     * @return string Joined string
     */
    static function _flatten ( $a,$join = ' AND ' )
    {
        if ( ! $a ) {
            return '';
        }
        else if ( $a && is_array($a) ) {
            return implode( $join,$a );
        }
        return $a;
    }
}

解决方法

您需要将编码更改为 utf8mb4 才能处理特殊字符。

假设您使用的是 php mysqli,您需要在客户端更改字符集:

connection = new mysqli(host,username,password,database,port);
connection->set_charset("utf8mb4");

现在确保mysql也在使用utf8mb4:

ALTER DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

表格也是:

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

要确认字符集已设置:

USE database_name;
show variables like "character_set_database";

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。