I'm storing a JSON array in a mysql TEXT field using PDO. (encoded with json_encode())
Once I get the data, if I do json_decode the result is NULL.
It seems that PDO is replacing every " with ".
I have already use PDO and JSON together multiple times, but this is the first time I got this problem so I don't understand what's happening.
I'm on PHP 5.4.4
Also, the JSON is sent with AJAX for your information
Thanks if you can help.
Example of JSON in the table :
{"type_voie":"BD","indice_repetition":"T","num_voie":"121","nom_voie":"NOM_RUE","infos_voie":"NOM_RUE2","distribution_speciale":"BP789","cp":"34000","ville":"MONTPELLIER","bureau_distributeur":""}
What i really see with var_dump :
{"type_voie":"BD","indice_repetition":"T","num_voie":"121","nom_voie":"NOM_RUE","infos_voie":"NOM_RUE2","distribution_speciale":"BP789","cp":"34000","ville":"MONTPELLIER","bureau_distributeur":""}
This is inserted with a prepared query
Code for retrieve DATA :
$formDataSQL = '
SELECT * FROM '.$this->prefix.'
WHERE formalite_id = '.$this->proc_id.'
';
$formDataReq = self::$db->prepare($formDataSQL);
$formDataReq->execute();
$formData = $formDataReq->fetch(PDO::FETCH_ASSOC);
Then on the JSON field :
$addrData = json_decode(str_replace('"', '"', $champ['value']), true); // WORKING BUT NOT MAINTAINABLE
$addrData = json_decode($champ['value'], true); // NOT WORKING => NULL + JSON ERROR = JSON_ERROR_SYNTAX
Here is a simplified example of my insert code :
foreach($saveData['personne_physique'] as $field => $value){
if(is_array($value)) $value = json_encode($value);
$param = ':'.$field;
$fields .= $field.'='.$param.', ';
$values[$param] = $value;
}
$fields = trim($fields, ', ');
$persPhysSQL = "UPDATE personne_physique SET $fields WHERE personne_id = ".$this->id;
$persPhysReq = self::$db->prepare($persPhysSQL);
$persPhysReq->execute($values);
Here is how I'm connecting :
$host = 'mysql:dbname='.BDD_NAME.';host='.BDD_HOST.';charset=utf8';
$user = BDD_USER;
$pass = BDD_PASS;
$db = new PDO($host, $user, $pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8") );
This is really strange :(
Here is my example script based on your data example:
<?php
try {
$Connection = new PDO('mysql:host=localhost;dbname=testing', USER, PASS);
$Connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo 'Unable to connect to database' . "\n";
}
$id = $argv[1];
try {
$data = $Connection->prepare('SELECT * FROM `stackoverflow_26399231` WHERE ID = :id');
$data->bindParam(':id', $id, PDO::PARAM_INT);
$data->execute();
while($row = $data->fetch(PDO::FETCH_OBJ)){
print_r($row);
print_r(json_decode($row->data));
}
$Connection = null;
}catch(PDOException $e){
echo 'Error executing query: ' . $e->getMessage() . "\n";
}
?>
The database table looks like this:
*************************** 1. row ***************************
id: 1
data: {"type_voie":"BD","indice_repetition":"T","num_voie":"121","nom_voie":"NOM_RUE","infos_voie":"NOM_RUE2","distribution_speciale":"BP789","cp":"34000","ville":"MONTPELLIER","bureau_distributeur":""}
When you run the script in the CLI, you get this back:
stdClass Object (
[id] => 1
[data] => {"type_voie":"BD","indice_repetition":"T","num_voie":"121","nom_voie":"NOM_RUE","infos_voie":"NOM_RUE2","distribution_speciale":"BP789","cp":"34000","ville":"MONTPELLIER","bureau_distributeur":""}
)
stdClass Object (
[type_voie] => BD
[indice_repetition] => T
[num_voie] => 121
[nom_voie] => NOM_RUE
[infos_voie] => NOM_RUE2
[distribution_speciale] => BP789
[cp] => 34000
[ville] => MONTPELLIER
[bureau_distributeur] =>
)
How does my script differ to yours? I'm not able to reproduce the issue.
UPDATE:
My update script following your example:
try {
$Connection = new PDO('mysql:host=localhost;dbname=testing', USER, PASS);
$Connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo 'Unable to connect to database' . "\n";
}
$id = $argv[1];
$ary = array(
'foo' => 'bar',
'bar' => 'foo',
'a' => 'b',
'c' => 'd',
'e' => 'f'
);
try {
$fields = 'data=:data';
$values = array('data' => json_encode($ary));
$update = $Connection->prepare("UPDATE `stackoverflow_26399231` SET $fields WHERE ID = $id");
$update->execute($values);
$Connection = null;
}catch(PDOException $e){
echo 'Error executing query: ' . $e->getMessage() . "\n";
}
Using the same script to receive as above but changing from PDO::FETCH_OBJ to PDO::FETCH_ASSOC as that's what you're using, I get this output:
Array
(
[id] => 1
[data] => {"foo":"bar","bar":"foo","a":"b","c":"d","e":"f"}
)
stdClass Object
(
[foo] => bar
[bar] => foo
[a] => b
[c] => d
[e] => f
)
So I can still not reproduce the issue you're having. There must be something different between the two scripts.
Related
I can't get SQLite LIKE search to work with PDO. This works fine with
MySQL and MariaDB but I can't get this to work with SQLite3.
I have also tried with different examples from internet.
I'm using sqlite3 version 3.35.3 and version PHP 8.0.3 on Linux 5.9.
echo '<pre>';
$createTable = <<<EOT
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
INSERT INTO users(name) VALUES
('alpha'),
('beta'),
('gamma'),
('theta');
EOT;
if (!file_exists(__DIR__ . '/test.db'))
{
echo "#CREATING DB# <br>";
$pdo = new \PDO('sqlite:' . __DIR__ . '/test.db');
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->exec($createTable);
$term = 'et';
$sql = " SELECT * FROM users WHERE name LIKE :term ";
$stmt = $pdo->prepare($sql);
$prepare = [
'term' => "'%". $term ."%'"
];
echo getPdoCompiledSqlString($sql, $prepare) . '<br>';
if($stmt)
{
$stmt->execute($prepare);
//$stmt->debugDumpParams();
debugPdo($stmt);
echo "#FETCHALL# <br>";
print_r( $stmt->fetchAll() );
}
}
else
{
echo "#DELETING DB#";
unlink(__DIR__ . '/test.db');
}
function getPdoCompiledSqlString($sql, $params){
echo "#SQL STRING# <br>";
$keys = [];
foreach ($params as $key => $value){ if (is_string($key)) {$keys[] = '/:'.$key.'/';} else {$keys[] = '/[?]/';}}
return preg_replace($keys, $params, $sql, 1, $count);
}
function debugPdo(&$stmt){
echo "#DEBUG PDO OBJ# <br>";
$stmt->debugDumpParams();
}
echo '<pre>';
You don't need to quote the parameter :
'term' => "%". $term ."%"
Instead of
'term' => "'%". $term ."%'"
Because the parameter will automatically be quoted during execute()
$term = 'et';
$sql = " SELECT * FROM users WHERE name LIKE :term ";
$stmt = $pdo->prepare($sql);
$prepare = [
'term' => "%". $term ."%" //only the search string: `%et%`
];
$stmt->execute($prepare);
print_r($stmt->fetchAll());
Output:
Array
(
[0] => Array
(
[id] => 2
[0] => 2
[name] => beta
[1] => beta
)
[1] => Array
(
[id] => 4
[0] => 4
[name] => theta
[1] => theta
)
)
I am using SQLite3 and PHP, and try to write a generic function to execute my queries.
For this I would like to retrieve the name of the parameters from variables in the bindParam.
But it doesn't seem to work. Here is a code showing the unexpected behavior:
<?php
header("Content-Type: text/plain");
$db = new SQLite3(':memory:');
$db->exec("create table mytable (lsid integer primary key autoincrement, usid TEXT, source TEXT)");
$myid = 'agoodid';
$mydatasources = array('home', 'news');
foreach($mydatasources as $datasource) {
$params[] = array(':datasource' => $datasource, ':usid' => $myid);
}
echo "here are the inputs : " .PHP_EOL;
print_r($params);
$querystring = 'insert into mytable (source, usid) values (:datasource, :usid)' ;
echo " I prepare the query '$querystring'" . PHP_EOL;
$query = $db->prepare($querystring);
foreach($params as $set) {
foreach($set as $key => $value) {
echo " Setting $key = $value." . PHP_EOL;
$query->bindParam($key, $value, SQLITE3_TEXT);
}
echo " I execute the query" . PHP_EOL;
$queryres[] = $query->execute();
$query->reset();
}
$results = $db->query('select * from mytable');
echo "and here is what I get : " . PHP_EOL;
while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
print_r($row);
}
?>
And here is the final result :
Array
(
[lsid] => 1
[usid] => agoodid
[source] => agoodid
)
Array
(
[lsid] => 2
[usid] => agoodid
[source] => agoodid
)
All the parameters seem to be bound with the value of the last bound parameter.
The expected result is:
Array
(
[lsid] => 1
[usid] => agoodid
[source] => home
)
Array
(
[lsid] => 2
[usid] => agoodid
[source] => news
)
How to do this? As a reminder: the aim is to not hard code the name of the parameter in bindParam.
I got the binParam function wholy wrong. it is attaching to the given parameter in the sql query a reference to the given variable in php.
I have to use bindValue instead.
I'm getting Informations from the Zabbix Api with a PHP library. At the moment I get the "lastvalue" from the json Array:
try {
// connect to Zabbix-API
$api = new ZabbixApi($api_url, $username, $password);
$params = array(
'groupids' => '2',
'real_items' =>TRUE,
'monitored_items' =>TRUE,
'search' => array('name' => 'Disk root used p'),
'selectFunctions' => 'extend',
'output' => 'extend',
'sortfield' => 'name',
'limit' => '1'
);
$trends = $api->itemGet($params); // get data from api
$names = array();
foreach($trends as $trend) { // loop through the returned data
$names[] = $trend->lastvalue;
}
//print_r($names);
} catch(Exception $e) {
// Exception in ZabbixApi catched
echo $e->getMessage();
}
But now I want to get the "lastvalue" plus the "name" of the Item in this Array for example like that: "name"+"lastvalue". How can I get both of them into my array $names[]?
Here is my answer from my comments, hope its what you are looking for!
$trends = $api->itemGet($params);
$names = array();
foreach($trends as $trendKey => $trendValue)
{
$names[$trendKey] = $trendValue;
}
#Test the names array
foreach ($names as $nameKey => $nameValue)
{
print("{$nameKey} = {$nameValue}<br />");
}
Return value:
groupids = 2
real_items = TRUE
...
sortfield = name
limit = 1
I've seen a few similar questions and tried the fixes and they are not working. Any help would be greatly appreciated.
I'm trying to return some data from the database as JSON.
Here is my code:
<?php
$db = "signup";
$servername = "localhost";
$username = "username";
$password = "password";
$fetch = ("SELECT * FROM bookings");
$return_arr = array();
$conn = new mysqli($servername, $username, $password, $db); // working
$query_result = mysqli_query($conn, $fetch);
mysqli_select_db("bookings",$db);
while ($row = mysqli_fetch_array($query_result, MYSQL_ASSOC)) {
$return_arr[] = array(
'TIMESLOT' => $row['TIMESLOT'],
'USERPIN' => $row['USERPIN'],
'PLAYERS' => $row['PLAYERS'],
'ACCEPTED' => $row['ACCEPTED'],
'EMAIL' => $row['EMAIL'],
'TOTAL BOOKINGS' => $row['TOTALBOOKINGS'],
'BOOKING ID' => $row['BOOKINGID'],
'LAST BOOKING' => $row['LASTBOOKING'],
'DATE' => $row['DATE']
);
}
$user = json_encode($return_arr);
echo "<pre>";
print_r($return_arr);
echo "</pre>";
mysqli_close($conn);
?>
Now I'm getting this information back from the database:
Array
(
[0] => Array
(
[TIMESLOT] => 12:00-14:00
[USERPIN] => 25225649
[PLAYERS] => 4
[ACCEPTED] => 0
[EMAIL] => email#address.com
[TOTAL BOOKINGS] => 0
[BOOKING ID] => 1
[LAST BOOKING] => 0000,00,00
[DATE] => 0000,00,00
)
)
I would change the while to this:
//...
$conn = new mysqli($servername, $username, $password, $db); // working
$query_result = mysqli_query($conn, "SELECT * FROM bookings");
//...
// Option 1 : Change MYSQL_ASSOC to MYSQLI_ASSOC
while ($row = mysqli_fetch_array($query_result, MYSQLI_ASSOC)) {
// Option 2 : Change to mysqli_fetch_assoc
// while ($row = mysqli_fetch_assoc($query_result)) {
// Debug
echo "<pre>";
print_r($row);
echo "</pre>";
$return_arr[] = array($row['BOOKINGID'],
$row['USERPIN'],
$row['TIMESLOT'],
$row['PLAYERS'],
$row['ACCEPTED'],
$row['EMAIL'],
$row['TOTALBOOKINGS'],
$row['LASTBOOKING'],
$row['DATE']
);
}
See that I added brackets to $return_arr, otherwise you'll be changing the value of the array and you'll get only the last one.
After that remove the "[0]" from the $return_arr[0]. This way you'll have the entire array encoded to json.
Try this code
$conn = new mysqli($servername, $username, $password, $db); // working
$sql = ""; // your query
$result = $conn->query($sql);
while($row = $result->fetch_array()) {
// Create results array
$rows[] = array(
'BOOKINGID' => $row['BOOKINGID'],
'USERPIN' => $row['USERPIN'],
// and go on....
);
}
mysqli_close($conn);
echo json_encode($rows[0]);
I tried using the fields() method on the cursor:
<?php
$mongo = new Mongo("mongodb://localhost");
print_r($mongo);
$db = $mongo->test;
// access collection
$collection = $db->test;
// execute query
// retrieve all documents
print_r($test);
$cursor = $collection->find();
print_r($cursor);
$fields = $cursor->fields(array("summary" => true));
print_r($fields);
The output is:
Mongo Object ( [connected] => 1 [status] => [server:protected] => [persistent:protected] => )
MongoCursor Object ( )
MongoCursor Object ( )
Looks like the driver and the connection work but I can't retrieve the distinct summarization of the fields.
Assume that we have access to mongodb database with the name db, are going to retrieve data from MyCollection and use MongoDB\Driver\Manager:
$manager = new MongoDB\Driver\Manager( $DB_CONNECTION_STRING );
Then we retrieve data in this case by name with a limit 2 documents and want to get only fields name, age and address among many others. Projection option can be used to specify which fields should be returned using 0 to exclude and 1 to include:
$filter = ['name' => 'John'];
$options = [ 'projection' => ['_id' => 0, 'name' => 1, 'age' => 1, 'address' => 1], 'limit' => 2 ];
$query = new MongoDB\Driver\Query($filter, $options);
$manager->executeQuery('db.MyCollection', $query);
If we need to get all columns, then we simply omit projection option at all as the following:
$filter = ['name' => 'daniel'];
$options = [];
$query = new MongoDB\Driver\Query($filter, $options);
$manager->executeQuery('db.MyCollection', $query);
const HOST = 'localhost';
const PORT = 27017;
const DBNAME = 'test';
const COLLECTION = 'test';
$connectionString = sprintf('mongodb://%s:%d', HOST, PORT);
try {
$connection = new Mongo($connectionString);
$database = $connection->selectDB(DBNAME);
} catch (MongoConnectionException $e) {
throw $e;
}
$collection = $database->selectCollection(COLLECTION);
try{
$query = array();
$specifyKey = array("summary" => true);
$cursor = $collection->find($query , $specifyKey);
}catch(MongoException $e) {
die('Failed to find One data '.$e->getMessage());
}catch (MongoCursorException $e) {
echo "error message: ".$e->getMessage()."\n";
echo "error code: ".$e->getCode()."\n";
}
while ($cursor->hasNext()){
$nextCursor = $cursor->getNext();
//process next cursor
}
After the $cursor variable try an foreach instead. It goes through the cursor results.
foreach($cursor as $document) {
var_dump($document);
}