mysqli and query with multiple rows - php

I am connecting xcode to webservices using, ASIHTTPRequest, and the mysqli prepare statement and also JSON.
Whatever i do i get only one single Mysql-record in xcode as a result.
I have looked everywhere and i have used Ray Wenderlich's "Promo code" example.
I guess i have to learn a bit here, but i just cannot find the answer.
Who can point me into the right direction?
Thank you in advance,
See the code below
// Helper method to send a HTTP response code/message
function sendResponse($status = 200, $body = '', $content_type = 'text/html')
{
$status_header = 'HTTP/1.1 ' . $status . ' ' . getStatusCodeMessage($status);
header($status_header);
header('Content-type: ' . $content_type);
echo $body;
}
class GetLevelAPI {
private $db;
// Constructor - open DB connection
function __construct() {
$this->db = new mysqli('localhost', 'root', '', 'madmagnets');
$this->db->autocommit(FALSE);
}
// Destructor - close DB connection
function __destruct() {
$this->db->close();
}
// Main method to post user info
function getLevel() {
// Check for required parameters
if (isset($_POST["username"])) {
// Put parameters into local variables
$usernameQ = $_POST["username"];
// fire the query
$stmt = $this->db->prepare('SELECT level_id, username, filename from
mm_levels WHERE username=? ');
$stmt->bind_param("s", $usernameQ ) ;
$stmt->execute();
$stmt->bind_result($id1, $username, $filename );
while ($stmt->fetch()) {
break;
}
$stmt->close();
$result = array(
"filename" => $filename ,
"username" => $username ,
);
sendResponse(200, json_encode($result));
return true;
}
sendResponse(400, 'Invalid request');
return false;
} //getLevel
} //GetLevelAPI
$api = new GetLevelAPI;
$api->getLevel();

I finally have found the solution for the question, of course with help of two of you.
I think the solution need a bit more clarification.
The best way to do that is to post the code which worked for me, here it is,
// Main method to post user info
function getLevel() {
// Check for required parameters
if (isset($_POST["username"])) {
// Put parameters into local variables
$usernameQ = $_POST["username"];
// fire the query
$stmt = $this->db->prepare('SELECT level_id, username, filename from mm_levels WHERE username=? ');
$stmt->bind_param("s", $usernameQ ) ;
$stmt->execute();
$arr = array();
$stmt->bind_result($lev_id,$username, $filename);
$i=0;
while ($stmt->fetch())
{
$arr[] = array( "filename" => $filename ); // <= this line was the last addition and did the trick
$i++;
}
$stmt->close();
sendResponse(200,json_encode($arr));
return true;
}
sendResponse(400, 'Invalid request');
return false;
} //getLevel
} //GetLevelAPI

Related

Empty return from Api

I'm a junior android developer, and i was asked to make an app that connects to a mysql database and downloads some data.
I have no knowledge at all of PHP and mysql, so please forgive me in advance for any badly written code, if you'd like to comment and thus help me improve my code writing, i'll be grateful :)
I had no issues with downloading all data from a database and passing it to the app through my simple API, but when i'm trying to pass only some entries of another database (that's to say, with a get function with a parameter in it) i'm having some issues.
I'm posting the code right here.
DbOperation.php
class DbOperation
{
private $con;
//Class constructor
function __construct()
{
require_once dirname(__FILE__) . '/DbConnect.php';
$db = new DbConnect();
$this->con = $db->connect();
}
//This is the WORKING function, i have no issues with it.
function getEvento(){
$stmt = $this->con->prepare("SELECT event_id, event_title, event_begin, event_end, event_category, event_link, event_label FROM wp_my_calendar");
$stmt->execute();
$stmt->bind_result($id, $titolo, $inizio, $fine, $categoria, $link, $luogo);
$eventi = array();
while($stmt->fetch()){
$evento = array();
$evento['id'] = $id;
$evento['titolo'] = $titolo;
$evento['inizio'] = $inizio;
$evento['fine'] = $fine;
$evento['categoria'] = $categoria;
$evento['link'] = $link;
$evento['luogo'] = $luogo;
array_push($eventi, $evento);
}
return $eventi;
}
From now on, what i'm doing is: first (getUtenteId) i get the submission_id from the mail of the user. Then (getUtenteDati) from the submission_id i can get all the user's values and return them. I'll call both get functions in the Api.php file.
(Here we're still in DbOperation.php)
function getUtenteId($email){
$idutente = $this->con->prepare("SELECT submission_id FROM wp_rm_submissions WHERE user_email='$email'");
$idutente->execute();
$idutente->bind_result($sub_id);
$idutente->fetch();
//echo $sub_id;
return $sub_id;
}
function getUtenteDati($utenteid) {
$stmt = $this->con->prepare("SELECT field_id, value FROM wp_rm_submission_fields WHERE submission_id='$utenteid' ORDER BY field_id");
$stmt->execute();
$stmt->bind_result($fieldid, $valori);
$dati = array();
while($stmt->fetch()){
$dato = array();
$dato['id'] = $fieldid;
$dato['valore'] = $valori;
//echo $valori;
array_push($dati, $dato);
}
return $dati;
}
}
?>
And here's the Api.php file
<?php
require_once '../includes/DbOperation.php';
function isTheseParametersAvailable($params){
$available = true;
$missingparams = "";
foreach($params as $param){
if(!isset($_POST[$param]) || strlen($_POST[$param])<=0){
$available = false;
$missingparams = $missingparams . ", " . $param;
}
}
if(!$available){
$response = array();
$response['error'] = true;
$response['message'] = 'Parameters ' . substr($missingparams, 1, strlen($missingparams)) . ' missing';
echo json_encode($response);
die();
}
}
$response = array();
if(isset($_GET['apicall'])){
switch($_GET['apicall']){
case 'geteventi':
$db = new DbOperation();
$response['error'] = false;
$response['message'] = 'Calendario aggiornato';
$response['messagedata'] = 'Data aggiornata';
$response['eventi'] = $db->getEvento();
break;
case 'getutente':
$db = new DbOperation();
//isTheseParametersAvailable(array('emailutente')); Commented because it returns error, don't know why.
$response['error'] = false;
$response['message'] = 'Dati utente scaricati';
$response['messagedata'] = 'Dati utente scaricati';
$emailutente = $_GET['emailutente'];
$idutente = $db->getUtenteId($emailutente);
//echo "id utente $idutente";
$dbdue = new DbOperation();
$response['utente'] = $dbdue->getUtenteDati($idutente);
break;
}
}else{
$response['error'] = true;
$response['message'] = 'Errore nel tentativo di aggiornare i dati, controlla la connessione a internet e riprova';
}
echo json_encode($response);
If i call this API correctly (http://.../Api/v1/Api.php?apicall=getutente&emailutente=user#mail.it), what i get is a blank page.
If i write "emailutente" wrong in the url (like emailsuteente), i get no error, but the response is empty.
{"error":false,"message":"Dati utente scaricati","messagedata":"Dati utente scaricati","utente":[]}
I tried to use an echo inside my getUtenteDati function, and it prints all the data i need correctly.
Any clues?
Thank you in advance!
EDIT: I tried to use this code in my local DB, and it's working. Issue still remains inside my remote DB. And it's weird, because with a simple ECHO inside the get function, i'm getting all the values i want. But it simply seems to refuse to give them to me inside an array.
Just a small update. The code was actually correct. The issue was with the Wordpress database refusing to return sensible data with my query from remote. I managed to get them in a safer way, with a simple self-made plugin:
global $wpdb;
[...]
if( is_user_logged_in() AND ! is_admin() ) {
$current_user = wp_get_current_user();
$email = $current_user->user_email;
$userid= $wpdb->get_var($wpdb->prepare("SELECT [...], $email);

PHP database connection class bind_param

I would like to write a database connection class and I dont understand how I have to write the select method with bind_param-s. Here is the full code. And here the part of the code where I need the help:
public function select($sql){
$db = $this->connect(); //This methos connect to the DB
$stmt = $db->prepare($sql);
if($stmt === false){ //If the prepare faild
trigger_error("Wrong SQL", E_USER_ERROR);
}
$error = $stmt->bind_param("i", $id);
if($error){
return "Error: ".$stmt->error, $stmt->errno;
}
$err = $stmt->execute();
if($error){
return "Error: ".$stmt->error, $stmt->errno;
}
$result = $stmt->bind_result($id);
$stmt->close();
$dbConnection->closeConnection($db);
return $result;
}
I need to got it parameters or how can I slove it?
You need to pass your values into this function too. And eventually bind them into prepared statement.
Optionally you can pass string with types, but by default all "s" will do.
Also remember that you should connect only ONCE per script execution. and then use one single connection all the way throughout your code.
And get rid of all these error checks. Set mysqli in exception mode instead.
public function q($sql, $values = array(), $types = NULL)
{
$stm = $this->mysql->prepare($sql);
if (!$types)
{
$types = str_repeat("s", count($values));
}
if (strnatcmp(phpversion(),'5.3') >= 0)
{
$bind = array();
foreach($values as $key => $val)
{
$bind[$key] = &$values[$key];
}
} else {
$bind = $values;
}
array_unshift($bind, $types);
call_user_func_array(array($stm, 'bind_param'), $bind);
$stm->execute();
return $stm->get_result();
}
so it can be used like this
$res = $db->q("SELECT name FROM users WHERE id=?", [$id]);
or
$res = $db->q("SELECT name FROM users WHERE id=?", [$id], "i");
your other functions have to be changed as well.
class DB{
public $con;
function __construct()
{
$this->con = new mysqli("localhost", "root", "", "proba_fferenc");
}
public function select(...)
{
// as shown above
}
}

SELECT_IDENTITY() not working in php

Scenario:
I have a SQL Query INSERT INTO dbo.Grades (Name, Capacity, SpringPressure) VALUES ('{PHP}',{PHP}, {PHP})
The data types are correct.
I need to now get the latest IDENTIY which is GradeID.
I have tried the following after consulting MSDN and StackOverflow:
SELECT SCOPE_IDENTITY() which works in SQL Management Studio but does not in my php code. (Which is at the bottom), I have also tried to add GO in between the two 'parts' - if I can call them that - but still to no avail.
The next thing I tried, SELECT ##IDENTITY Still to no avail.
Lastly, I tried PDO::lastInsertId() which did not seem to work.
What I need it for is mapping a temporary ID I assign to the object to a new permanent ID I get back from the database to refer to when I insert an object that is depended on that newly inserted object.
Expected Results:
Just to return the newly inserted row's IDENTITY.
Current Results:
It returns it but is NULL.
[Object]
0: Object
ID: null
This piece pasted above is the result from print json_encode($newID); as shown below.
Notes,
This piece of code is running in a file called save_grades.php which is called from a ajax call. The call is working, it is just not working as expected.
As always, I am always willing to learn, please feel free to give advice and or criticize my thinking. Thanks
Code:
for ($i=0; $i < sizeof($grades); $i++) {
$grade = $grades[$i];
$oldID = $grade->GradeID;
$query = "INSERT INTO dbo.Grades (Name, Capacity, SpringPressure) VALUES ('" . $grade->Name . "',". $grade->Capacity .", ".$grade->SpringPressure .")";
try {
$sqlObject->executeNonQuery($query);
$query = "SELECT SCOPE_IDENTITY() AS ID";
$newID = $sqlObject->executeQuery($query);
print json_encode($newID);
} catch(Exception $e) {
print json_encode($e);
}
$gradesDictionary[] = $oldID => $newID;
}
EDIT #1
Here is the code for my custom wrapper. (Working with getting the lastInsertId())
class MSSQLConnection
{
private $connection;
private $statement;
public function __construct(){
$connection = null;
$statement =null;
}
public function createConnection() {
$serverName = "localhost\MSSQL2014";
$database = "{Fill In}";
$userName = "{Fill In}";
$passWord = "{Fill In}";
try {
$this->connection = new PDO( "sqlsrv:server=$serverName;Database=$database", $userName, $passWord);
$this->connection->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e ) {
die("Connection Failed, please contact system administrator.");
}
if ($this->connection == null) {
die("Connection Failed, please contact system administrator.");
}
}
public function executeQuery($queryString) {
$results = array();
$this->statement = $this->connection->query( $queryString );
while ( $row = $this->statement->fetch( PDO::FETCH_ASSOC ) ){
array_push($results, $row);
}
return $results;
}
public function executeNonQuery($queryString) {
$numRows = $this->connection->exec($queryString);
}
public function getLastInsertedID() {
return $this->connection->lastInsertId();
}
public function closeConnection() {
$this->connection = null;
$this->statement = null;
}
}
This is PDO right ? better drop these custom function wrapper...
$json = array();
for ($i=0; $i < sizeof($grades); $i++) {
//Query DB
$grade = $grades[$i];
$query = "INSERT INTO dbo.Grades (Name, Capacity, SpringPressure)
VALUES (?, ?, ?)";
$stmt = $conn->prepare($query);
$success = $stmt->execute(array($grade->Name,
$grade->Capacity,
$grade->SpringPressure));
//Get Ids
$newId = $conn->lastInsertId();
$oldId = $grade->GradeID;
//build JSON
if($success){
$json[] = array('success'=> True,
'oldId'=>$oldId, 'newId'=>$newId);
}else{
$json[] = array('success'=> False,
'oldId'=>$oldId);
}
}
print json_encode($json);
Try the query in this form
"Select max(GradeID) from dbo.Grades"

PHP using PDO to store session in DB doesnt produce the errors i expected

SOLVED :
answer is in the 2nd post
i try to store session in DB using PDO, but it doesn't produce errors i expected, please read my code.
here's the code for my session handler class:
class MySessionHandler implements SessionHandlerInterface
{
protected $conn = NULL;
public function open($savePath, $sessionName)
{
if(is_null($this->conn))
{
$dsn = 'mysql:host=localhost;dbname=php_advanced';
$username = 'root';
$password = 'password';
try
{
$this->conn = new PDO($dsn, $username, $password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
$this->conn = NULL;
die('error in open function ' . $e->getMessage());
}
}
return TRUE;
}
public function close()
{
echo '<p>close</p>';
$this->conn = NULL;
return TRUE;
}
public function read($id)
{
echo '<p>read</p>';
$query = 'SELECT data FROM session_table WHERE session_id = :id';
try
{
$pdo = $this->conn->prepare($query);
$pdo->bindValue(':id', $id);
$pdo->execute();
// Kalo query berhasil nemuin id..
if($pdo->rowCount() == 1)
{
list($sessionData) = $pdo->fetch();
return $sessionData;
}
return FALSE;
}
catch(PDOException $e)
{
$this->conn = NULL;
die('error in read function => ' . $e->getMessage());
}
}
public function write($id, $data)
{
echo '<p>write</p>';
$query = 'REPLACE INTO session_table(session_id, data) VALUES(:id, :data)';
try
{
$pdo = $this->conn->prepare($query);
$pdo->bindValue(':id', $id);
$pdo->bindValue(':data', $data);
$pdo->execute();
// return the value whether its success or not
return (bool)$pdo->rowCount();
}
catch(PDOException $e)
{
$this->conn = NULL;
die('error in write function => ' . $e->getMessage());
}
}
public function destroy($id)
{
echo '<p>destroy</p>';
$query = 'DELETE FROM session_table WHERE session_id = :id LIMIT 1';
try
{
$pdo = $this->conn->prepare($query);
$pdo->bindValue(':id', $id);
$pdo->execute();
$_SESSION = array();
return (bool)$pdo->rowCount();
}
catch(PDOException $e)
{
$this->conn = NULL;
die('error in destroy function => ' . $e->getMessage());
}
}
public function gc($maxLifeTime)
{
echo '<p>garbage collection</p>';
$query = 'DELETE FROM session_table WHERE DATE_ADD(last_accessed INTERVAL :time SECOND) < NOW()';
try
{
$pdo = $this->conn->prepare($query);
$pdo->bindValue(':time', $maxLifeTime);
$pdo->execute();
return TRUE;
}
catch(PDOException $e)
{
$this->conn = NULL;
die('error in gc function => ' . $e->getMessage());
}
}
}
$SessionHandler = new MySessionHandler();
session_set_save_handler($SessionHandler);
session_name('my_session');
session_start();
i remove the session_write_close on purpose. This probably sounds stupid, but i want to get the session error to learn more..
here's session script(using the book's code):
require('session_class.php');
?><!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>DB Session Test</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<?php
// Store some dummy data in the session, if no data is present:
if (empty($_SESSION)) {
$_SESSION['blah'] = 'umlaut';
$_SESSION['this'] = 3615684.45;
$_SESSION['that'] = 'blue';
// Print a message indicating what's going on:
echo '<p>Session data stored.</p>';
} else { // Print the already-stored data:
echo '<p>Session Data Exists:<pre>' . print_r($_SESSION, 1) . '</pre></p>';
}
// Log the user out, if applicable:
if (isset($_GET['logout'])) {
session_destroy();
echo '<p>Session destroyed.</p>';
} else { // Otherwise, print the "Log Out" link:
echo 'Log Out';
}
// Reprint the session data:
echo '<p>Session Data:<pre>' . print_r($_SESSION, 1) . '</pre></p>';
// Complete the page:
echo '</body>
</html>';
// Write and close the session:
// session_write_close() <<<<<--- I REMOVE THIS ON PURPOSE TO GET ERROR
?>
but i dont get any error, then i try to use book's mysqli script to connect db and it produces error i expected because i removed the session_write_close()..
can anyone explain why if im using PDO it doesn't generate error? i'm even dont use
register_shutdown_function('session_write_close');
in my session class destructor (on purpose)
NOTE : I'm doing this on purpose because i want to learn more.
the error im expecting is like when im using mysqli connection(connection closed by php at the end of script then session try to write and close but no connection available) :
Warning: mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in /var/www/ullman_advance/ch3/ullman_db.php on line 66
Warning: mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in /var/www/ullman_advance/ch3/ullman_db.php on line 66
Warning: mysqli_query() expects parameter 1 to be mysqli, null given in /var/www/ullman_advance/ch3/ullman_db.php on line 67
Warning: mysqli_close() expects parameter 1 to be mysqli, null given in /var/www/ullman_advance/ch3/ullman_db.php on line 33
update 1
i recently figured it out that mysqli needs database connection everytime it uses mysqli_real_escape_string() and mysqli_query and because of but what im thinking is my pdo also needs db connection when the script ends -> db connection closed -> MySessionHandler will try to write and close, but there's no db connection since pdo has been closed by php, but no error produced..
update 2
i just tried to pass session_set_save_handler function callback and it produces the errors
<?php
$conn = NULL;
function open_session()
{
echo '<p>open session</p>';
global $conn;
$_dsn = 'mysql:host=localhost;dbname=php_advanced';
$_username = 'root';
$_password = 'password';
$conn = new PDO($_dsn, $_username, $_password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return TRUE;
}
function close_session()
{
echo '<p>close session</p>';
global $conn;
$conn = NULL;
return TRUE;
}
function read_session($sid)
{
echo '<p>read session</p>';
global $conn;
$query = 'SELECT data FROM session_table WHERE session_id = :sid';
$pdo = $conn->prepare($query);
$pdo->bindValue(':sid', $sid, PDO::PARAM_STR);
$pdo->execute();
if($pdo->rowCount() == 1)
{
list($session_data) = $pdo->fetch();
echo '<pre>';
print_r($session_data);
echo '</pre>';
return $session_data;
}
else
{
return '';
}
}
function write_session($sid, $data)
{
echo '<p>write session</p>';
global $conn;
$query = 'REPLACE INTO session_table(session_id, data) VALUES(:sid, :data)';
$pdo = $conn->prepare($query);
$pdo->bindValue(':sid', $sid, PDO::PARAM_STR);
$pdo->bindValue(':data', $data, PDO::PARAM_STR);
$pdo->execute();
return $pdo->rowCount();
}
function destroy_session($sid)
{
echo '<p>destroy session </p>';
global $conn;
$query = 'DELETE FROM session_table WHERE session_id = :sid';
$pdo = $conn->prepare($query);
$pdo->bindValue(':sid', $sid, PDO::PARAM_STR);
$pdo->execute();
// clean the session array;
$_SESSION = array();
return (bool)$pdo->rowCount();
}
function clean_session($expire)
{
echo '<p>clean session</p>';
global $conn;
$query = 'DELETE FROM session_table WHERE DATE_ADD(last_accessed, INTERVAL :expire SECOND) < NOW()';
$pdo = $conn->prepare($query);
$pdo->bindValue(':expire', $expire, PDO::PARAM_INT);
$pdo->execute();
return $pdo->rowCount();
}
session_set_save_handler('open_session', 'close_session', 'read_session', 'write_session', 'destroy_session', 'clean_session');
session_name('my_session');
session_start();
but still when im passing MySessionHandler class , it doesn't produce error because of no connection.
SOLUTION
sorry guys my mistake actually its a pretty easy answer why MySessionHandler class doesnt produce error wihtout session_write_close() in the end of script,
session_set_save_handler() by default will register session_write_close() to register_shutdown_function()
so if u want to make your own shutdown function for session then use :
session_set_save_handler($SessionClass, FALSE) , if u do this then u must provide session_write_close() in your class destructor
source : http://php.net/manual/en/function.session-set-save-handler.php
thanks for the tips and your attention

How to use prepared statements (named parameters) on a php Class

I want to know how to use named parameters in a prepared statement with pdo class, so the call to pdo look something like following.
$query = $bdd->prepare('SELECT * FROM table WHERE login = :login AND pww = :pww');
$query->execute(array('login' => $login, 'pww' => $pww));
And I want to integrate this on a class regardless of the number of parameters.
Currently, I have this code
require_once 'constants.php';
class Mysql extends PDO {
private $con;
public function __construct() {
try {
$this->con = parent::__construct(DB_DSN, DB_USER, DB_PASS);
if ($this->getAttribute(PDO::ATTR_DRIVER_NAME) == DB_TYPE)
$this->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, TRUE);
return $this->con;
} catch (PDOException $e) {
die('Error:' . $e->getMessage());
}
}
public function select($reqSelect) {
try {
$this->con = parent::beginTransaction();
$result = parent::prepare($reqSelect);
$result->execute();
//$this->con = parent::commit();
$this->con = parent::rollBack();
return $result;
$result->closeCursor();
} catch (Exception $e) {
die('Error:' . $e->getMessage());
}
}
public function selectAll($reqSelect) {
$result = parent::prepare($reqSelect);
$result->execute();
$resultat = $result->fetchAll();
return $resultat;
$result->closeCursor();
}
}
And for parameters, I use somethings like ( which is wrong and vulnerable to injection )
require_once 'classes/Mysql.class.php';
$mysql = new Mysql();
$sql = 'SELECT * FROM articles WHERE id = '.$_GET['id'].' LIMIT 1';
$data = $mysql->select($sql);
Thanks.
So it's seems that I have figured it out, the trick was adding an optional parameter to the function, you use it whenever you need to work with prepared statements (named parameters).
So the function is something like
public function selectAll($reqSelect, $param = null) {
$result = parent::prepare($reqSelect);
//Check whether the parameter was passed or not
if (is_null($param)) {
$result->execute();
$resultat = $result->fetchAll();
return $resultat;
} else {
//Binding the parameters
$result->execute($param);
$resultat = $result->fetchAll();
return $resultat;
}
$result->closeCursor();
}
And for applying it, it goes like
//First param, the SQL. Here we have named parameters, so we need them to get bind
$sql = 'SELECT * FROM articles WHERE publish = :number';
//Second param, the parameters that will get bind with the named ones
$param = array(':number' => 1);
$query = $mysql->selectAll($sql, $param);
foreach ($query as $row) {
extract($row);
echo $title . '<br />';
}
I don't know if this, is considered the best practice, secured or even correct. if I'm mistaken feel free to correct me.

Categories