8

intデータベースでおよびとしてマークされているにもかかわらず、MySQL から呼び出された値が文字列として返されるという PHP スクリプトで問題が発生していますtinyint

これは、MySQL の日付に基づく配列を JSON データに変換するときに、整数であるべき値が二重引用符で囲まれているため、その JSON データを使用する Javascript と iPhone アプリの両方で問題を引き起こしているためです。"key" : "1"のように見える JSON 値を取得しています"key" : 1

いくつかの調査を行った後、PHP 5.3 とモジュールがインストールされている限り、値をネイティブ型として取得できるようです。mysqlnd私は 5.3.3 を持っており、モジュールをインストールして実行しphpinfo()ていることを示しているようです:mysqlnd

mysqlnd enabled
Version mysqlnd 5.0.10 - 20111026

ただし、私の値はまだ文字列として返されています。

mysqlndの PHP マニュアル エントリを見てきましたが、明らかなものが欠けている可能性は常にありますが、ネイティブ値を取得するためにコードで特定のことを行う必要があることを示すものは何も表示されません。

PHP で MySQL 関数を取得して、MySQL の結果をネイティブ型で取得するにはどうすればよいですか?


以下の回答を容易にするために、これはデータベースへの接続に使用するコマンドです。

private function databaseConnect()
{
    $this->mysqli = new mysqli(Database::$DB_SERVER, Database::$DB_USERNAME, Database::$DB_PASSWORD);
    $this->mysqli->set_charset("utf8");
    return true;
}

private function dbConnect()
{
    Database::$USE_MYSQLI = extension_loaded('mysqli');
    if (!$this->databaseConnect())
    {
        echo "Cannot Connect To The Database Server";
        throw new Exception();
    }
    if (!$this->databaseSelectDB())
    {
        echo "The database server connected, but the system could not find the right database";
        throw new Exception();
    }
}

private function databaseQuery($query)
{
    return $this->mysqli->query($query);
}

public function doQuery($query)
{
    $result = $this->databaseQuery($query);
    if ($result == FALSE)
    {
        //ErrorHandler::backtrace();
        die("This query did not work: $query");
    }
    return $result;
}

private function getRows($table, $matches, $orderBy = array(), $limit = array())
{
    $calcFoundRows = '';
    if (count($limit) > 0)
    {
        $calcFoundRows = ' SQL_CALC_FOUND_ROWS';
    }
    $query = 'SELECT ' . $calcFoundRows . ' * FROM ' . $table;
    if (count($matches) > 0)
    {
        $query .= ' WHERE ';
        $keys = array_keys($matches);
        $first = true;
        foreach ($keys as $key)
        {
            if (!$first)
            {
                $query .= ' AND ';
            }
            $first = false;

            // now he is safe to add to the query
            // the only time this is an array is when this is called by getSelectedUsers or getSelectedArticles
            // in that case it is an array of array's as the key (which is the column name) may have more than
            // one condition
            if (is_array($matches[$key]))
            {
                $firstForColumn = true;
                foreach ($matches[$key] as $conditions)
                {
                    if (!$firstForColumn)
                    {
                        $query .= ' AND ';
                    }
                    $firstForColumn = false;

                    // if the value is an array we generate an OR selection
                    if (is_array($conditions[1]))
                    {
                        $firstOr = true;
                        $query .= '(';

                        foreach ($conditions[1] as $value)
                        {
                            if (!$firstOr)
                            {
                                $query .= ' OR ';
                            }
                            $firstOr = false;
                            // clean this guy before putting him into the query
                            $this->cleanMySQLData($value);
                            if ($conditions[0] == Selection::$CONTAINS)
                            {
                                //$query .= 'MATCH (' . $key . ') AGAINST (' . $value . ') ';
                                $value = trim($value, "'");
                                $value = "'%" . $value . "%'";
                                $query .= $key . ' LIKE ' . $value;
                            }
                            else
                            {
                                $query .= $key . ' ' . $conditions[0] . ' ' . $value;
                            }
                        }

                        $query .= ')';
                    }
                    else
                    {
                        // clean this guy before putting him into the query
                        $var = $conditions[1];
                        $this->cleanMySQLData($var);
                        if ($conditions[0] == Selection::$CONTAINS)
                        {
                            //$query .= 'MATCH (' . $key . ') AGAINST (' . $var . ') ';
                            $var = trim($var, "'");
                            $var = "'%" . $var . "%'";
                            $query .= $key . ' LIKE ' . $var;
                        }
                        else
                        {
                            $query .= $key . ' ' . $conditions[0] . ' ' . $var;
                        }
                    }
                }
            }
            else
            {
                // clean this guy before putting him into the query
                $this->cleanMySQLData($matches[$key]);
                $query .= $key . " = " . $matches[$key];
            }
        }
    }
    if (count($orderBy) > 0)
    {
        $query .= " ORDER BY ";
        $first = true;
        foreach ($orderBy as $orderCol)
        {
            if (!$first)
            {
                $query .= ',';
            }
            $query .= $orderCol;
            $first = false;
        }
    }

    if (count($limit) > 0)
    {
        $query .= ' LIMIT ' . $limit[0];
        if (count($limit) > 1)
        {
            $query .= ',' . $limit[1];
        }
    }


    $result = $this->doQuery($query);
    $data = array();
    while ($row = $this->databaseFetchAssoc($result))
    {
        $data[] = $row;
    }
    if (strlen($calcFoundRows) > 0)
    {
        $numRows = $this->databaseCountFoundRows();
        $key = '^^' . $table . '_selectionCount';
        Session::getSession()->putUserSubstitution($key, $numRows);
    }

    return $data;
}
4

5 に答える 5

4

PHP で MySQL 関数を取得して、MySQL の結果をネイティブ型で取得するにはどうすればよいですか?

データベースに接続し、クエリを準備して実行し、結果をバインドしてフェッチします。

これらの手順を 1 行ずつ実行してみましょう。

$conn = new Mysqli('localhost', 'testuser', 'test', 'test');
$stmt = $conn->prepare("SELECT id FROM config LIMIT 1");
$stmt->execute();
$stmt->bind_result($id);
$stmt->fetch();
var_dump($id); # it's an int!

これは私にとってはうまくいきます。コードがより複雑になるにつれて、データベースにクエリを実行する場所を特定する必要があります。使用していることを確認し、使用Mysqli::prepare()していない場合は導入してください。

また、使用する必要がありますMysqli_Stmt::execute()Mysqli_Stmt::bind_result()そうしないと、(ここでは整数) タイプがその結果列に保持されません。

于 2013-01-06T10:43:47.113 に答える
3

ただし、私の値はまだ文字列として返されています。

PHP では、データが int、bool、string であるかどうかは問題ではありません...そのような型がある場合、それらはスカラー データと呼ばれ、動的キャストにより、必要に応じて動作させることができます。たとえば、文字列"12345"+"54321"66666. すべての言語のように、データを特定のタイプにしたい場合、それはドライバーの仕事ではありません。Java では、JDBC のインターフェースのメソッドのようなものが.getStringあり.getIntますが、PHP ではあまり役に立たないのでありません。intval boolval strval... 関数または... キャスト演算子を使用して(int)、自分でデータをキャストする必要があります。(bool)

あなたの投稿が言ったように、サーバー側の準備されたステートメントを使用してそれを持つことができます:

PDO に mysqlnd を使用する利点

mysqlnd は、サーバー側のプリペアド ステートメントを使用する場合、ネイティブ データ型を返します。たとえば、INT 列は、文字列ではなく整数変数として返されます。つまり、内部でのデータ変換が少なくなります。

PDOあり

接続の後にこの行を配置する必要があります

$PDO->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

次に、クエリを実行する場合:

$s = $PDO->prepare('yourquery');
//here, binding params
$s->bindValue('paramName','paramValue');
$s->execute();

Mysqliで

mysqli を使用すると、構文が少し異なります。注: クライアント側で準備済みステートメントを使用する方法はないため、PDO で設定した構成行は必要ありません。

したがって、クエリは次のようになります。

$statement = $MySQli->prepare('your query');
$statement->bind_param('si', $stringParam, $intParam);
$statement->bind_result($var1, $var2 /*,...*/);
$statement->execute();
while($statement->fetch()){
  //process here, result will be in var1, var2...
}

ここでは、組み込みの fetchAll メソッドがないことがわかります。データをバインドするには、のように値として渡されるのではなく、参照によって渡されるため、変数を使用する必要がありますPDOStatement::bindValue()。さらに、型は最初の引数で定義されます (文字列の場合は s、整数の場合は i...)。名前付きパラメーターはなく、インデックス付きのパラメーターのみです。このfetchメソッドは別の方法で動作し、execute ステートメントの前に bind_result を呼び出す必要があります。

于 2013-01-06T09:55:21.967 に答える
0

これはおそらく最良の答えではありませんが、intval()などを使用してデータ型を強化できます。私は個人的に、PDO、Mysqli、または古い (現在は廃止された) mysql 関数を使用しているときに、この経験をしました。とを使用してテスト ケースを実行するis_int()is_string()、データベースからフェッチされたデータが実際に文字列であるのに対し、int であることが 100% 確実になります。申し訳ありませんが、これ以上お役に立てませんでした。

于 2013-01-06T09:54:44.233 に答える