Create JSON with specific format using PHP - php

I have a table in my server database with the following columns:
|---category--|---name---|---description---|
So, lets say for example that we have the following data inside the table:
|---CategoryA--|---name1---|---description1---|
|---categoryB--|---name2---|---description2---|
|---categoryA--|---name3---|---description3---|
|---categoryA--|---name4---|---description4---|
I would like to create a .php file, and when i call it from my Android app i would like to get a JSON as response. The json file would like to have the following format:
{
"CategoryA":[
{"name":"name1","description":"description1"},
{"name":"name3","description":"description3"},
{"name":"name4","description":"description4"}
],
"KatigotiaB":[
{"name":"name2","description":"description2"}
]
}
I have created a .php file that returns me the data in JSON format, but not in the specific format i want. Here is my .php file:
<?php
header('content-type: text/html; charset=utf-8');
try {
$pdo = new PDO('mysql:host=****;dbname=****', '****', '****', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
$stmt = $pdo->prepare("SELECT * FROM `db`.`table`;");
$stmt->execute();
$results = array();
while ($obj = $stmt->fetch(PDO::FETCH_ASSOC)) {
array_push($results, $obj);
}
function replace_unicode_escape_sequence($match) {
return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UTF-16BE');
}
$str = preg_replace_callback('/\\\\u([0-9a-f]{4})/i', 'replace_unicode_escape_sequence', json_encode($results));
echo $str;
?>
and the result is:
[{"category":"CategoryA","name":"name1","description":"description1"},
{"category":"CategoryB","name":"name2","description":"description2"},
{"category":"CategoryA","name":"name3","description":"description3"},
{"category":"CategoryA","name":"name4","description":"description4"}]
As i'm an Android developer and my php knowledge is limited, how could i recreate my .php file in order to get the correct JSON format?
UPDATE:
that works
foreach ($nameDescriptionPairs as $nameDescriptionPair) {
$result[$row['category']][] = array(
'name' => $nameDescriptionPair['name'],
'description' => $nameDescriptionPair['description']
);
}

Solution #1 (simple):
<?php
$host = 'localhost';
$database = '******';
$user = '******';
$password = '******';
$result = [];
try {
$pdo = new PDO(
"mysql:host=$host; dbname=$database;",
$user,
$password,
[PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"]
);
$stmt = $pdo->prepare("SELECT category, name, description FROM `YOUR_TABLE_HERE`");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$result[$row['category']][] = [
'name' => $row['name'],
'description' => $row['description'],
];
}
} catch (Exception $e) {
echo 'ERROR: ' . $e->getMessage();
}
header('content-type: application/json; charset=utf-8');
echo json_encode($result);
Solution #2 (geeky):
One note to my code: I used hex conversion to prevent problems with quotes. Thus, even if any column has any number of ", the code will work fine.
<?php
function hexToStr($hex) {
$string = '';
for ($charIter = 0; $charIter < strlen($hex) - 1; $charIter += 2) {
$string .= chr(hexdec($hex[$charIter] . $hex[$charIter + 1]));
}
return $string;
}
//----------------------
$host = 'localhost';
$database = '******';
$user = '******';
$password = '******';
$result = [];
try {
$pdo = new PDO(
"mysql:host=$host; dbname=$database;",
$user,
$password,
[PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"]
);
$query = <<<QUERY
SELECT category, CONCAT('[', GROUP_CONCAT( CONCAT( '{"name":"', hex( name ) , '", "description":"', hex( description ) , '"}' ) ), ']') raw_json
FROM `YOUR_TABLE_HERE`
GROUP BY category
QUERY;
$stmt = $pdo->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$nameDescriptionPairs = json_decode($row['raw_json'], true);
foreach ($nameDescriptionPairs as $nameDescriptionPair) {
$result[$row['category']][] = [
'name' => hexToStr($nameDescriptionPair['name']),
'description' => hexToStr($nameDescriptionPair['description'])
];
}
}
} catch (Exception $e) {
echo 'ERROR: ' . $e->getMessage();
}
header('content-type: application/json; charset=utf-8');
echo json_encode($result);

One major issue is you're setting the content-type to text/html. You're not printing HTML, this should be set to JSON:
header('content-type: application/json; charset=utf-8');
Not sure if it has any effect, but your callback is unnecessary:
$str = preg_replace_callback('/\\\\u([0-9a-f]{4})/i', 'replace_unicode_escape_sequence', json_encode($results));
If you truly don't want json_encode to escape unicode, use the JSON_UNESCAPED_UNICODE option found here: http://php.net/manual/en/function.json-encode.php
$str = json_encode($results, JSON_UNESCAPED_UNICODE);
Beyond that, you could also use JSON_PRETTY_PRINT to format it, but line breaks and such shouldn't matter to the app interpreting the JSON if it is made aware that it is JSON (what setting content-type correctly should do).

Related

Construct http_build_query with PDO and Select

I am trying to create an http_build_query array but it is inserting some diferent characters, this is my Code:
function Conectar(){
try{
$opcoes = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8');
$con = new PDO("mysql:host=localhost; dbname=*****;", "*****", "*****", $opcoes);
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $con;
} catch (Exception $e){
echo 'Erro: '.$e->getMessage();
return null;
}
}
$pdo = Conectar();
$sql = "
SELECT dominio
FROM dominios_extraidos
WHERE verificado='0' LIMIT 3
";
$stm = $pdo->prepare($sql);
$stm->execute();
while ($rows = $stm->fetch()) {
$query = http_build_query(array(
'domains' => array(
''.$rows['dominio'].'',
)
));
print_r($query);
}
Creating this output:
domains%5B0%5D=0002021web.com.br%0Adomains%5B0%5D=007import.com.br%0Adomains%5B0%5D=00pet.com.br%0A
But this is my desire output:
domains%5B0%5D=0002021web.com.br&domains%5B1%5D=007import.com.br&domains%5B2%5D=00pet.com.br
My desire output could be generated manually using this code:
$query = http_build_query(array(
'domains' => array(
'0002021web.com.br',
'007import.com.br',
'00pet.com.br',
)
));
print_r($query);
Thank you for your time :)
You want to build up your array properly first, so that it looks like your manual array, then use http_build_query:
$domains = ['domains' => []];
while ($rows = $stm->fetch()) {
$domains['domains'][] = trim($rows['dominio']);
}
$query = http_build_query($domains);
print_r($query);
Create an array of domains in the loop and then after the loop is complete pass it as a param to the http_build_query().
while ($rows = $stm->fetch()) {
$doms[] = trim($rows['dominio']);
}
$query = http_build_query( ['domains' => $doms] );
print_r($query);
This will produce
domains%5B0%5D=0002021web.com.br%0A&domains%5B1%5D=007import.com.br%0A&domains%5B2%5D=00pet.com.br%0A
which equates to
domains[0]=0002021web.com.br
&domains[1]=007import.com.br
&domains[2]=00pet.com.br
0A decoded is \n or Line Feed;
perhaps try sanitizing first with
$query= trim($query, "\x00..\x20\x7F");
this code remove ASCII character from 00 to 20 hex and 7f hex

reading entries from database

is anyone able to find out what went wrong in this code below? It just shows a blank page. I'm new to PDO, always used mysqli but someone told me to try PDO since my page had problems showing arabic characters.
<html>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<?php
/* Connect to an ODBC database using driver invocation */
$dsn = 'mysql:dbname=testdb;host=127.0.0.1;charset=UTF8;'
$user = 'dbuser'; // don't hardcode this...store it elsewhere
$password = 'dbpass'; // this too...
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$sql = "SELECT :column FROM :table";
$opts = array(
':column' => 'Name',
':table' => 'Mothakirat'
);
$dbh->beginTransaction();
$statement = $dbh->prepare($sql);
if ($statement->execute($opts)) {
$resultArray = array(); // If so, then create a results array and a temporary one
$tempArray = array(); // to hold the data
while ($row = $result->fetch_assoc()) // Loop through each row in the result set
{
$tempArray = $row; // Add each row into our results array
array_push($resultArray, $tempArray);
}
echo json_encode($resultArray); // Finally, encode the array to JSON and output the results
}
$dbh->commit();
</html>
This has no parse errors checked in my IDE. I use netbeans, its very good and available on several platforms.
<html>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<?php
/* Connect to an ODBC database using driver invocation */
$dsn = 'mysql:dbname=testdb;host=127.0.0.1;charset=UTF8;';
$user = 'dbuser'; // don't hardcode this...store it elsewhere
$password = 'dbpass'; // this too...
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$sql = "SELECT :column FROM :table";
$opts = array(
':column' => 'Name',
':table' => 'Mothakirat'
);
$dbh->beginTransaction();
$statement = $dbh->prepare($sql);
if ($statement->execute($opts)) {
$resultArray = array(); // If so, then create a results array and a temporary one
$tempArray = array(); // to hold the data
while ($row = $result->fetch_assoc()) // Loop through each row in the result set
{
$tempArray = $row; // Add each row into our results array
array_push($resultArray, $tempArray);
}
echo json_encode($resultArray); // Finally, encode the array to JSON and output the results
}
$dbh->commit();
?>
</html>

How to do a select with two parameters after the WHERE using PDO?

I try to select data from a database, but I'm unable to get it when I have two parameters after the WHERE.
Code that works:
$conn = null;
$host = 'localhost';
$db = 'database';
$user = 'root';
$pwd = 'root';
$auth = 'EP';
$nr = 2007;
try {
$conn = new \PDO('mysql:host='.$host.';dbname='.$db, $user, $pwd);
$stmt = $conn->prepare('SELECT family FROM table WHERE nr = :nr');
$stmt->execute(array('nr' => $nr));
while($row = $stmt->fetch(PDO :: FETCH_ASSOC)) {
echo '<pre>';
print_r($row);
echo '</pre>';
}
}
catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
but when I use following select it doesn't work:
SELECT family FROM table WHERE auth = :auth AND nr = :nr
I think it's a problem in the line
$stmt->execute(array('nr' => $nr));
When I do the following I have no result on the screen:
$stmt->execute(array('nr' => $nr, 'auth' => $auth));
Has anybody an idea what I'm doing wrong?
CHANGE THIS
stmt->execute(array('nr' => $nr, 'auth' => $auth));
TO
$stmt->execute(array(':nr' => $nr, ':auth' => $auth));
: is a small typo error but PDO is Serious :( and the parameters will be empty.

returning multiple rows from mysql in php

I'm trying to write a PHP-script that will fetch multiple rows from MySQL and return them as a JSONObject, the code works if I try to only fetch 1 row but if I try to get more than one at a time the return string is empty.
$i = mysql_query("select * from database where id = '$v1'", $con);
$temp = 2;
while($row = mysql_fetch_assoc($i)) {
$r[$temp] = $row;
//$temp = $temp +1;
}
If I write the code like this it returns what I expect it to, but if I remove the // from the second row in the while loop it will return nothing. Can anyone explain why this is and what I should do to solve it?
You are using an obsolete mysql_* library.
You are SQL injection prone.
Your code is silly and makes no sense.
If you really wan to stick to it, why simply not do:
while($row = mysql_fetch_assoc($i)) {
$r[] = $row;
}
echo json_encode($r);
And finally, an example using PDO:
$database = 'your_database';
$user = 'your_db_user';
$pass = 'your_db_pass';
$pdo = new \PDO('mysql:host=localhost;dbname='. $database, $user, $pass);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
try
{
$stmt = $pdo->prepare("SELECT * FROM your_table WHERE id = :id");
$stmt->bindValue(':id', $id);
$stmt->execute();
$results = $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
catch(\PDOException $e)
{
$results = ['error' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine());
}
echo json_encode($results);
You don't need the $temp variable. You can add an element to an array with:
$r[] = $row;

Using PHP to query a MDB file, and return JSON

I have a Microsoft Access Database, and I am trying to query the table using PHP, and output valid JSON. I have an equivalent code for a MSSQL database, am I am trying to make my code do the same thing, but just for the Access database.
Here is the MSSQL code
$myServer = "server";
$myDB = "db";
$conn = sqlsrv_connect ($myServer, array('Database'=>$myDB));
$sql = "SELECT *
FROM db.dbo.table";
$data = sqlsrv_query ($conn, $sql);
$result = array();
do {
while ($row = sqlsrv_fetch_array ($data, SQLSRV_FETCH_ASSOC)) {
$result[] = $row;
}
} while (sqlsrv_next_result($data));
$json = json_encode ($result);
sqlsrv_free_stmt ($data);
sqlsrv_close ($conn);
Here is what I tried for the MDB file
$dbName = "/filename.mdb";
if (!file_exists($dbName)) {
die("Could not find database file.");
}
$db = odbc_connect("Driver={Microsoft Access Driver (*.mdb)};Dbq=$dbName", $user, $password);
$sql = "SELECT *
FROM cemetery";
$data = $db->query($sql); // I'm getting an error here
$result = array();
// Not sure what do do for this part...
do {
while ($row = fetch($data, SQLSRV_FETCH_ASSOC)) {
$result[] = $row;
}
} while (sqlsrv_next_result($data));
$json = json_encode ($result);
I kind of followed this to try to connect to the database: http://phpmaster.com/using-an-access-database-with-php/
Currently this is giving me a 500 Internal Server Error. I'm expecting a string such as this to be saved in the variable $json
[
{
"col1":"col value",
"col2":"col value",
"col3":"col value",
},
{
"col1":"col value",
"col2":"col value",
"col3":"col value",
},
{
etc...
}
]
Can someone help me port the MSSQL code I have above so I can use it with an MDB database? Thanks for the help!
EDIT: I'm commenting out the lines one by one, and it throws me the 500 error at the line $data = $db->query($sql);. I looked in the error log, and I'm getting the error Call to a member function query() on a non-object. I already have the line extension=php_pdo_odbc.dll uncommented in my php.ini file. Anyone know what the problem could be?
You only need 1 loop,
fetchAll is your iterable friend:
while ($row = $data->fetchAll(SQLSRV_FETCH_ASSOC)) {
$result[] = $row;
}
odbc_connect doesn't return an object, it returns a resource. see (http://php.net/manual/en/function.odbc-connect.php) so you would need to do something like this.
$db = odbc_connect("Driver={Microsoft Access Driver (*.mdb)};Dbq=$dbName", $user, $password);
$oexec = obdc_exec($db,$sql);
$result[] = odbc_fetch_array($oexec);
and then you can iterate over results..
see also:
http://www.php.net/manual/en/function.odbc-fetch-array.php
http://www.php.net/manual/en/function.odbc-exec.php
I finally figured it out.
<?php
// Location of database. For some reason I could only get it to work in
// the same location as the site. It's probably an easy fix though
$dbName = "dbName.mdb";
$tName = "table";
// Throws an error if the database cannot be found
if (!file_exists($dbName)) {
die("Could not find database file.");
}
// Connects to the database
// Assumes there is no username or password
$conn = odbc_connect("Driver={Microsoft Access Driver (*.mdb)};Dbq=$dbName", '', '');
// This is the query
// You have to have each column you select in the format tableName.[ColumnName]
$sql = "SELECT $tName.[ColumnOne], $tName.[ColumnTwo], etc...
FROM $dbName.$tName";
// Runs the query above in the table
$rs = odbc_exec($conn, $sql);
// This message is displayed if the query has an error in it
if (!$rs) {
exit("There is an error in the SQL!");
}
$data = array();
$i = 0;
// Grabs all the rows, saves it in $data
while( $row = odbc_fetch_array($rs) ) {
$data[$i] = $row;
$i++;
}
odbc_close($conn); // Closes the connection
$json = json_encode($data); // Generates the JSON, saves it in a variable
?>
I use this code to get results from an ODBC query into a JSON array:
$response = null;
$conn = null;
try {
$odbc_name = 'myODBC'; //<-ODBC connectyion name as is in the Windows "Data Sources (ODBC) administrator"
$sql_query = "SELECT * FROM table;";
$conn = odbc_connect($odbc_name, 'user', 'pass');
$result = odbc_exec($conn, $sql_query);
//this will show all results:
//echo odbc_result_all($result);
//this will fetch row by row and allows to change column name, format, etc:
while( $row = odbc_fetch_array($result) ) {
$json['cod_sistema'] = $row['cod_sistema'];
$json['sistema'] = $row['sistema'];
$json['cod_subsistema'] = $row['cod_subsistema'];
$json['sub_sistema'] = $row['sub_sistema'];
$json['cod_funcion'] = $row['cod_funcion'];
$json['funcion'] = $row['funcion'];
$json['func_desc_abrev'] = $row['desc_abreviada'];
$json['cod_tipo_funcion'] = $row['cod_tipo_funcion'];
$response[] = array('funcionalidad' => $json);
}
odbc_free_result($result); //<- Release used resources
} catch (Exception $e) {
$response = array('resultado' => 'err', 'detalle' => $e->getMessage());
echo 'ERROR: ', $e->getMessage(), "\n";
}
odbc_close($conn);
return $response;
And finnally encoding the response in JSON format:
echo json_encode($response);

Categories