JSON response not as expected using php - php

I know this is probably a really simple question, but I can't find an answer for this issue, maybe because it is a really basic php programming question. This is my function using PDO (php):
<?php
function getAllUsers(){
try {
$conn = getConnection(); //connects to database, no explanation needed... uses PDO
$dbh = $conn->prepare("SELECT * FROM User;");
$dbh->execute();
$users = $dbh->fetchAll(); //<---this is maybe the error
$conn = null;
return $users;
}catch (PDOException $ex){
echo "Error: ".$ex->getMessage();
}
} ?>
And when i consume the API that i'm implementing, i use this other PHP script (using slim framework, still pretty understandable)
<?php
$app->get("/user",function() use($app){
$app->response->headers->set("Content-type","application/json");
$app->response->status(200);
$result = getAllUsers(); //call to my function getAllUsers
$app->response->body(json_encode($result));
});
?>
It works fine, but the results that I get are these:
[{"idUser":"1","0":"1","userName":"asdasd","1":"asdasd","userPass":"password","2":"password"},{"idUser":"2","0":"2","userName":"2312","1":"2312","userPass":"password","2":"password"}]
And I think that the repeated values "0":"1" , "1":"asdasd" , "2":"password"should not be there, but i can't figure out how to get only the data that i want and not the repeated values. Any help would be very appreciated

I'm not using PDO, but "common" mysql queries and there is the same...you get doubled your values. One array is associative and other indexed (0,1,2). And there is option to pass ("MYSQL_ASSOC" if I recall well) to get only associative array, without indexed one. There must be some similar option with PDO.
$dbh->fetchAll(PDO::FETCH_ASSOC);
http://php.net/manual/en/pdostatement.fetchall.php

Related

A stored procedure that doesn't work in my PHP code but it works with a SQL Client

I'm working on a business monitor (a pannel that presents some metrics).
To get that data I do a sql request. By the way, I used a stored procedure.
My code is :
public function execErrorWarnLogs($id){
try {
$sql = "exec [BUSINESS_MONITOR_LOGS] #id='".$id."'";
$req = $this->_bdd->prepare($sql);
$req->execute();
$res = $req->fetchAll(PDO::FETCH_ASSOC);
$req->closeCursor();
return $res;
} catch (Exception $e) {
echo $e->getMessage();
}
}
When I'm trying to get some data indexed by $id, I get some troubles. I got an array that has null values... However, if I execute that stored procedure with an SQL client I get results.
Is that already happened to someone here ? Can someone explain me why I get that ?
If you want more information, please let me know.
Thanks.
Is $id an integer or a string?
Try using bound parameter instead. This is a example how it is working perfectly in my code:
public function execErrorWarnLogs($id){
try {
$sql = "exec BUSINESS_MONITOR_LOGS #id=:id";
$req = $this->_bdd->prepare($sql);
$req->execute([
'id' => $id
]);
$res = $req->fetchAll(PDO::FETCH_ASSOC);
$req->closeCursor();
return $res;
} catch (Exception $e) {
echo $e->getMessage();
}
}
You should use parameters for security reasons, too!
Two site notes:
If you do string interpolation you don't need to prepare the statement. Then you could just do:
$req = $this->_bdd->query($sql);
$res = $req->fetchAll(PDO::FETCH_ASSOC);
But the recommendet approach (for security) is to provide values as bound parameters and prepare the query.
As far as I know, you don't need $req->closeCursor() if you use Microsofts latest pdo driver for MSSQL. Whether you need closeCursor depends on the driver you use.
My stored procedure :
CREATE PROCEDURE BUSINESS_MONITOR #id VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
SELECT e.METRIC_NAME, e.METRIC_VALUE
FROM MONITOR_EVENTS e
WHERE e.MAIN_ID = #id
END
There are two more possible reasons:
Encoding issue
I would assume, that you have an encoding issue. If $id contains chars, that are out of the ascii-range, and you have another encoding, this could cause the query to fail. So check the encoding of $id and of you db connection
Whitespaces in $id
Maybe you have whitespaces in you id.

PHP Slim post route to MySql not working

After following this tutorial: I now have a Slim environment. I can get my data from MySql, but I just can't post. I have tried something like this:
...
$app->post('/someRoute', function (Request $request, Response $response){
$sql = "INSERT INTO someTable(firstName, lastName)
VALUES(:FN, :LN)";
$db = $this->get(Connection::class);
$stmt = $db->prepare($sql);
//$rows = $db->table('someTable')->get();
$stmt->bindParam(':FN', $request->getParam('FN'));
$stmt->bindParam(':LN', $request->getParam('LN'));
$stmt->execute();
});
This does not work, but I can't see where the error might be because I don't know how to debug a POST function with HTML/PHP. My app send's the parameters to the function just fine. I don't have a lot of experience with server-side programming, so any help would be appreciated. Thanks.
If you are using the PDO class, you can "TryCatch" it:
try
{
// Your code
}
catch (PDOException $e)
{
// Error Message
print_r($e->getMessage());
}
I needed to use a query builder instead of my own SQL statements. Sorted

Error getting data using PDO and PHP

I'm developing a web based software that uses MySQL and PHP on the backend.
I'm trying to obtain data with a complex query and in the end I just obtain the query.
function consulttimes(){
$pdo = connect();
try{
$consult = $pdo->prepare("SELECT credentials.realname, timestamp_greenhouse.* FROM times.credentials, times.timestamp_greenhouse WHERE timestamp_greenhouse.id = credentials.id;");
$consult->execute();
$consult->fetch(PDO::FETCH_ASSOC);
echo json_encode($consult);
//file_put_contents('times.json', $json);
}
catch(PDOException $e) {
echo $e -> getMessage();
}
}
I have all the databases and the query works perfectly on phpmyadmin.
Can someone help me with this?
Cheers!
I'm trying to obtain data with a complex query and in the end I just obtain the query.
The problem is because of this line,
echo json_encode($consult);
$consult is a PDOStatement object returned from the prepared statement. I believe you're trying to encode the row obtained from ->fetch(PDO::FETCH_ASSOC) method.
So first fetch the row from the result set, store it in a variable and then apply json_encode on it, like this:
// your code
$consult->execute();
$result = $consult->fetch(PDO::FETCH_ASSOC);
echo json_encode($result);

Creating a container function for a PDO query in PHP

Because I find PDO executions extremely hard to remember and find myself looking back at previous projects or other websites just to remember how to select rows from a database, I decided that I would try and create my own functions that contain the PDO executions and just plug in the data I need. It seemed a lot simpler than it actually is though...
So far I have already created a connect function successfully, but now when it comes to create a select function I'm stumped for multiple reasons.
For starters there could be a variating amount of args that can be passed into the function and secondly I can't figure out what I should pass to the function and in which order.
So far the function looks like this. To keep me sane, I've added the "id" part to it so I can see what exactly I need to accomplish in the final outcome, and will be replaced by variables accordingly when I work out how to do it.
function sql_select($conn, **what to put here**) {
try {
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
$result = $stmt->fetchAll();
if ( count($result) ) {
foreach($result as $row) {
print_r($row);
}
} else {
return "No rows returned.";
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
}
So far what I've established that the function will need to do is
Connect to the database (using another function to generate the $conn variable, already done)
Select the table
Specify the column
Supply the input to match
Allow for possible args such as ORDER by 'id' DESC
Lastly from this I would need to create a function to insert, update and delete rows from the database.
Or, is there a better way to do this rather than functions?
If anyone could help me accomplish my ambitions to simply simplify PDO executions it would be greatly appreciated. Thanks in advance!
First of all, I have no idea where did you get 10 lines
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = ?');
$stmt->execute(array($id));
$result = $stmt->fetchAll();
is ALL the code you need, and it's actually three lines, which results with a regular PHP array that you can use wherever you wish. Without the need of any PDO code. Without the need of old mysql code.
Lastly from this I would need to create a function to insert, update and delete rows from the database.
DON'T ever do it.
Please read my explanations here and here based on perfect examples of what you'll end up if continue this way.
accomplish my ambitions to simply simplify PDO executions
That's indeed a great ambition. However, only few succeeded in a real real simplification, but most resulted with actually more complex code. For starter you can try code from the first linked answer. Having a class consists of several such functions will indeed improve your experience with PDO.
. . . and find myself looking back at previous projects or other
websites just to remember how to select rows from a database . . .
FYI, we all do that.
You had a problem with the PDO API and now you have two problems. My best and strongest suggestion is this: If you want a simpler/different database API, do not roll your own. Search http://packagist.org for an ORM or a DBAL that looks good and use it instead of PDO.
Other people have already done this work for you. Use their work and focus instead on whatever awesome thing is unique to your app. Work smart, not hard and all that.
Writting a wrapper, should start form connecting the DB, and all the possible method could be wrapped. Passing connection to the query method, doesn't look good.
A very rough example would be the code bellow, I strongly do not suggest this mixture, but it will give you the direction.
You connection should be made either from the constructor, or from another method called in the constructor, You can use something like this:
public function __construct($driver = NULL, $dbname = NULL, $host = NULL, $user = NULL, $pass = NULL, $port = NULL) {
$driver = $driver ?: $this->_driver;
$dbname = $dbname ?: $this->_dbname;
$host = $host ?: $this->_host;
$user = $user ?: $this->_user;
$pass = $pass ?: $this->_password;
$port = $port ?: $this->_port;
try {
$this->_dbh = new PDO("$driver:host=$host;port=$port;dbname=$dbname", $user, $pass);
$this->_dbh->exec("set names utf8");
} catch(PDOException $e) {
echo $e->getMessage();
}
}
So you can either pass connection credentials when you instantiate your wrapper or use default ones.
Now, you can make a method that just recieves the query. It's more OK to write the whole query, than just pass tables and columns. It will not make a whole ORM, but will just make the code harder to read.
In my first times dealing with PDO, I wanted everything to be dynamically, so what I achieved, later I realized is immature style of coding, but let's show it
public function query($sql, $unset = null) {
$sth = $this->_dbh->prepare($sql);
if($unset != null) {
if(is_array($unset)) {
foreach ($unset as $val) {
unset($_REQUEST[$val]);
}
}
unset($_REQUEST[$unset]);
}
foreach ($_REQUEST as $key => $value) {
if(is_int($value)) {
$param = PDO::PARAM_INT;
} elseif(is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif(is_null($value)) {
$param = PDO::PARAM_NULL;
} elseif(is_string($value)) {
$param = PDO::PARAM_STR;
} else {
$param = FALSE;
}
$sth->bindValue(":$key", $value, $param);
}
$sth->execute();
$result = $sth->fetchAll();
return $result;
}
So what all of these spaghetti does?
First I though I would want all of my post values to be send as params, so if I have
input name='user'
input name='password'
I can do $res = $db->query("SELECT id FROM users WHERE username = :user AND password = :password");
And tada! I have fetched result of this query, $res is now an array containing the result.
Later I found, that if I have
input name='user'
input name='password'
input name='age'
In the same form, but the query remains with :user and :password and I submit the form, the called query will give mismatch in bound params, because the foreach against the $_REQUEST array will bind 3 params, but in the query I use 2.
So, I set the code in the beginning of the method, where I can provide what to exclude. Calling the method like $res = $db->query("SELECT id FROM users WHERE username = :user AND password = :password", 'age'); gave me the possibility to do it.
It works, but still is no good.
Better have a query() method that recieves 2 things:
The SQL string with the param names
The params as array.
So you can use the foreach() logic with bindValue, but not on the superglobal array, but on the passed on.
Then, you can wrap the fetch methods
public function fetch($res, $mode = null)
You should not directly return the fetch from the query, as it might be UPDATE, INSERT or DELETE.
Just pass the $res variable to the fetch() method, and a mode like PDO::FETCH_ASSOC. You can use default value where it would be fetch assoc, and if you pass something else, to use it.
Don't try to be so abstract, as I started to be. It will make you fill cracks lately.
Hum... IMHO I don't think you should try to wrap PDO in functions, because they're already "wrapped" in methods. In fact, going from OOP to procedural seems a step back (or at least a step in the wrong direction). PDO is a good library and has a lot of methods and features that you will surely lose if you wrap them in simple reusable functions.
One of those features is the BeginTransaction/Rollback (see more here)
Regardless, In a OOP point of view you can decorate the PDO object itself, adding some simple methods.
Here's an example based on your function
Note: THIS CODE IS UNTESTED!!!!
class MyPdo
{
public function __construct($conn)
{
$this->conn = $conn;
}
public function pdo()
{
return $this->conn;
}
public function selectAllById($table, $id = null)
{
$query = 'SELECT * FROM :table';
$params = array('table'=>$table);
if (!is_null($id)) {
$query .= ' WHERE id = :id';
$params['id'] = $id;
}
$r = $this->conn->prepare($query)
->execute($params)
->fetchAll();
//More stuff here to manipulate $r (results)
return $r;
}
public function __call($name, $params)
{
call_user_func_array(array($this->conn, $name), $params);
}
}
Note: THIS CODE IS UNTESTED!!!!
ORM
Another option is using an ORM, which would let you interact with your models/entities directly without bothering with creating/destroying connections, inserting/deleting, etc... Doctrine2 or Propel are good bets for PHP.
Howeveran ORM is a lot more complex than using PDO directly.

custom function for mysqli queries

I'm trying my hand at custom functions in PHP in order to streamline a lot of stuff I'm otherwise doing manually. I'm damn new to custom functions so I'm not sure the limitations. Right now I'm trying to get data with MySQLi using custom functions Here's the code, and then I'll explain the issue:
function connect_db($db = 'db_username') {
iconv_set_encoding("internal_encoding", "UTF-8");
mb_language('uni');
mb_internal_encoding('UTF-8');
# $mysqli = new mysqli('host',$db,'password',$db);
if(mysqli_connect_errno())
{
die('connection error');
}
}
This one seems to be working fine. It's the next function I'm having more trouble with.
edit: Updated thanks to Jeremy1026's response
function do_query($db = 'default_db', $query) {
connect_db();
$result = $mysqli->query($query);
if(!$result){
trigger_error("data selection error");
}
while($row = $result->fetch_assoc()){
$result_array[] = $row;
}
return $result_array;
}
My host forces database names and usernames as the same, so if the db name is 'bob' the username to access it will be 'bob' as well, so that's why $db shows up twice in the connection.
The problem I'm having is that these two functions are in functions.php and being called from another page. I want to be able to pull the results from the query in that other page based on the column name. But I also need to be able to do this with formatting, so then maybe the while() loop has to happen on that page and not in a function? I want this to be as universal as possible, regardless of the page or the data, so that I can use these two functions for all connections and all queries of the three databases I'm running for the site.
God I hope I'm being clear.
Big thanks in advance for any suggestions. I've googled this a bit but it's tough to find anything that's not using obsolescent mysql_ prefixes or anything that's actually returning the data in a way that I can use.
Update: I'm now getting the following error when accessing the page in question:
Fatal error: Call to a member function query() on a non-object in /functions.php`
with the line in question being $result = $mysqli->query($query);. I assume that's because it thinks $query is undefined, but shouldn't it be getting the definition from being called in the page? This is that page's code:
$query = "SELECT * FROM `table`";
$myArray = do_query($db, $query);
echo $myArray['column_name'];
In your 2nd function you aren't returning any data, so it is getting lost. You need to tell it what to return, see below:
function do_query($db = 'default_db', $query) {
connect_db();
$result = $mysqli->query($query);
if(!$result){
trigger_error("data selection error");
}
while($row = $result->fetch_assoc()){
$result_array[] = $row;
}
return $result_array;
}
Then, when using the function you'll do something like:
$myArray = do_query($db, 'select column from table');
$myArray would then be populated with the results of your query.
This is a half-answer. The following single function works in place of the two.
function query_db($database, $new_query) {
$sqli = new mysqli('host', $database, 'password', $database);
$sqli->set_charset("utf8");
global $result;
if($result = $sqli->query($new_query)){
return $result;
}
}
By adding global $result I was able to access the results from the query, run from another page as
query_db("username","SELECT * FROM `column`");
while($row = $result->fetch_assoc()){
print_r($row);
}
It's more streamlined than I have without functions, but it's still not idea. If I have the connection to the database in another function, it doesn't work. If I try to put the while loop in the combined function, it doesn't work. Better than nothing, I guess.

Categories