Class PDO for query - php

Goodmorning.
I've an issue with this function inside a class:
public function singleField($query,$bindParam,$table){
$stmt = $this->conn->prepare($query);
while (list($key, $value) = each($bindParam)) {
$stmt->bindParam($key,$value);
}
$stmt->execute();
while($row = $stmt->fetch()){
return $row[$table];
}
}
cannot understand what I'm doing wrong, here how I use the class:
$conn = new conn;
$conn->singleField("SELECT field FROM table WHERE ID = :ID AND field2 = :field2....etcetc",array(":ID"=>1,":field2"=>"OtherVar...etc..."),"Table");
being sure that the connection created in construct is working, now I wonder why the query is not working and not return the result.
I wish I had the opportunity in the array can enter more than one value to pass to BindParam, this is why i created that while but I think that's wrong.
Are three days that I work on.
Thank You for any help.

Related

Simple PDO select statement not working

I'm not a PHP developer, but having a huge amount of trouble trying to do simple things in this language. The current issue is that I am simply just trying to make a select statement, that works fine if I do it like this:
$sql = "SELECT * FROM victim WHERE steamId = 129847129847"
The rest of my logic runs:
$stmt = $this->pdo->prepare($sql);
$stmt->execute();
$user = $stmt->fetch();
if($user) {
//success
error_log('hit');
} else {
error_log('error????????????');
}
And I get the hit in my console. Great, but that's not very useful. I want to simply just exchange the hardcoded value to something I am passing in the function.
function checkIfVictimExists($steamId)
Now I don't have ALL the code I've tried, but I've just about tried every flavor of this that I've seen on the internet and it continously hits the else no matter what I do. Again, hardcoding the steamId, works fine, trying to inject a value does not work.
Here's my current implementation that is not working:
$sql = "SELECT * FROM victim WHERE steamId = ?";
$stmt = $this->pdo->prepare($sql);
$stmt->execute(array($steamId));
$user = $stmt->fetch();
if($user) {
//success
error_log('hit');
} else {
error_log('error????????????');
}
I know I've tried to pass it in via:
...WHERE steamId = :steamId
and
...execute(array(':steamId' => $steamId);
with no luck.
I've simply just tried to add it onto the string, as such:
...WHERE steamId = {$steamId}
AND
...WHERE steamId = ".$steamId."
AND
...WHERE steamId = ".$steamId (thought maybe I needed an extra "?)
Literally nothing works. When I try to get error info, via $this->pdo->errorInfo() all I get is an array like this:
[0] = 0000
[1] =
[2] =
Really at a loss for words why this would be so confusing, but obviously I am missing something that I fail to see in any of the google searches I've done. Looking for some help here now, thanks in advance.
EDIT
here is my connection logic:
...
private $pdo;
function __construct() {
$dsn = "mysql:host=".$this->dbhost.";dbname=".$this->dbname.";charset=".$this->charset;
try {
$this->pdo = new PDO($dsn, $this->username, $this->password);
$this->connectionStatus = true;
} catch(Exception $ex) {
error_log('Could not connect to DB'.$ex);
}
}

PHP arrays of objects with mySQL

Is there an easy way to make an array of objects in php when you have the objects attributes come from a mySQL query?
My code is below in order to show you what I'm doing. I'm probably far off because I'm not used to php at all and I can't grasp it for some reason.
public function loadMeals(){
$stmt = $this->conn->prepare("SELECT id, dishName, ingredients FROM meals");
$stmt->execute();
$stmt->bind_result($id, $dishName, $ingredients);
$meals = array();
while ($stmt->fetch()) {
$this->id = $id;
$this->dishName = $dishName;
$this->ingredients = $ingredients;
$meals[] = $this;
}
return $meals;
}
Keep in mind that this is all in a class Meals.
Thanks guys.
Based on how you are using it (creating an array of Meal objects, the method should be declared as a static method, called without $this context. The loop may create Meal objects via new self() and set the appropriate properties before appending onto the array.
If you think about it, this method's purpose is not to act on a single Meal, so it makes sense for it to be static.
Since it is called without $this context, you will need to pass the MySQLi connection as a parameter
public static function loadMeals($conn) {
// Do the query/fetch like you already have
// except that $conn is a local param, not a class prop.
$stmt = $conn->prepare("SELECT id, dishName, ingredients FROM meals");
$stmt->execute();
$stmt->bind_result($id, $dishName, $ingredients);
$meals = array();
while ($stmt->fetch()) {
// Create a new Meal object
$meal = new self();
// And set its properties
$meal->id = $id;
$meal->dishName = $dishName;
$meal->ingredients = $ingredients;
// Append it to the array
$meals[] = $meal;
}
// Return it
return $meals;
}
To use it, outside the class:
// Call the function statically.
// You'll need to pass the database connection to it
$meals = Meal::loadMeals($conn);
I'll point out that while it is very good to be in the habit of doing prepare()/execute(), you do not actually need it here since you are not passing any input into the query. You can just call $conn->query(), eliminating some complexity from MySQLi's bind_result() variable references.
$result = $conn->query("SELECT id, dishName, ingredients FROM meals");
if ($result) {
// Fetch and instantiate a Meal object in one go.
while ($meal = $result->fetch_object('Meal')) {
$meals[] = $meal;
}
}
This might be a short solution to your problem but consider using mysql_fetch_assoc when grabbing your elements from the database.
For more reading and example:
mysql_fetch_assoc documentation from php.net
For PDO:
public function loadMeals(){
$stmt = $this->conn->prepare("SELECT id, dishName, ingredients FROM meals");
$stmt->execute();
$meals = array();
while ($obj = $stmt->fetch(PDO::FETCH_OBJ)) {
$meals[] = $obj;
}
return $meals;
}
or $meal = $stmt->fetchObject('MyMeal', $ctor_args); See this from PHP manual. Also note the first comment about constructors there, to expect the unexpected results that using this may cause.

Converting into PDO

Good evening everyone!
I need your help again. Please bear with me because I am very new to this. Hoping for your understanding. So, I am having a project on oop and pdo. I am having quite hard time converting this into pdo.. Here is my code..
bookReserve.php
while($row=mysql_fetch_array($sql))
{
$oldstock=$row['quantity'];
}
$newstock = $oldstock-$quantity;
Here's what i've done
while($row = $code->fetchAll())
{
$oldstock=$row['quantity'];
}
$newstock = $oldstock-$quantity;
Is that even correct?
And for the oop part, after this while loop I have a query to execute.
$sql="update books set no_copies = '$newstock' where book_title = '$book_title'";
Here's what I've done trying to convert it into pdo
public function bookreserve2($q)
{
$q = "UPDATE books SET quantity WHERE = $newstock where book_title = '$book_title'";
$stmt = $this->con->prepare($q);
$stmt->execute(array(':newstock'=>$newstock));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result;
}
Again, Is that even the correct converted query?
and how would I call $newstock?
P.S. my oop class and pdo is placed in a separate file. Thought this might help.
Thanks
You are not including your query parameters in your function, and your query has syntax errors (extra WHERE) and you are directly inserting your values not using placeholders.
It should look something like -
public function bookreserve2($newstock,$book_title)
{
$q = "UPDATE books SET quantity = :newstock WHERE book_title = :book_title";
$stmt = $this->con->prepare($q);
$stmt->execute(array(':newstock'=>$newstock,':booktitle'=>$book_title));
if($stmt){
return true;
}
else {
return false;
}
}

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.

Is it possible to fetch_object while using bind_param? (PHP/MySQLi)

I have a question for you guys. I'm trying to make the way that I run MySQL as secure as I can. I'm currently wondering if it's possible to fetch an object with MySQLi after I have prepared the statement, binded the parameters, and executed the statement.
Example:
$sql = $mysqli->prepare('SELECT * FROM users WHERE username = ?;');
$sql->bind_param('s', $username);
$username = 'RastaLulz';
$sql->execute();
$object = $sql->fetch_object();
echo $object->mail;
I get the following error:
Fatal error: Call to a member function fetch_object() on a non-object in C:\xampp\htdocs\ProCMS\DevBestCMS\inc\global\class.mysql.php on line 23
However, when I add "$sql->result_metadata();" I don't get an error, but it doesn't return a result (it's just NULL).
$sql = $mysqli->prepare('SELECT * FROM users WHERE username = ?;');
$sql->bind_param('s', $username);
$username = 'RastaLulz';
$sql->execute();
$result = $sql->result_metadata();
$object = $result->fetch_object();
echo $object->mail;
This is how you'd do it without binding the parameters:
$sql = $mysqli->query("SELECT * FROM users WHERE username = 'RastaLulz';");
$object = $sql->fetch_object();
echo $object->mail;
Here's my current MySQL class - just need to get the execute function working.
http://uploadir.com/u/lp74z4
Any help is and will be appreciated!
I had the same question. I found out that I could do the following:
# prepare statement
$stmt = $conn->prepare($sql)
# bind params
$stmt->bind_param("s", $param);
# execute query
$stmt->execute();
# get result
$result = $stmt->get_result();
# fetch object
$object = $result->fetch_object();
I hope that works for you, too.
I just dug around in my Database class and this is how I do it. Honestly I don't remember why I needed to do it this way and there might be a much better way. But if it helps you here is the code. I do vaguely remember being irritated about there not being a simple way to get your results as an object.
// returns an array of objects
public function stmtFetchObject(){
$rows=array(); //init
// bind results to named array
$meta = $this->stmt->result_metadata();
$fields = $meta->fetch_fields();
foreach($fields as $field) {
$result[$field->name] = "";
$resultArray[$field->name] = &$result[$field->name];
}
call_user_func_array(array($this->stmt, 'bind_result'), $resultArray);
// create object of results and array of objects
while($this->stmt->fetch()) {
$resultObject = new stdClass();
foreach ($resultArray as $key => $value) {
$resultObject->$key = $value;
}
$rows[] = $resultObject;
}
return $rows;
}
What is the ';' at the end of your statement? You are giving mysqli an invalid query and so it is not creating an object for you.
The problem is not the fetch_object, but the prepare statement.
Remove the ';' and try again. It should work like a charm.
I've never seen a query end like that.
Try instantiating the variable before binding.
I think its just good practice but use double quotes instead of single quotes.

Categories