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.
Related
I created a function to grab data from my database. I want this function to be reusable just by placing correct arguments for different tables. Here's what I've done :
public function selectdata($table, $arguments='*', $where = null){
if($this->isconnect){
//check whether users put column names in the select clause
if(is_array($arguments)){
$new_args = implode(',', $arguments);
$sql = 'SELECT '.$new_args.' FROM '.$table;
} else {
$sql = 'SELECT '.$arguments.' FROM '.$table;
}
//check whether users use the where clause
if($where != null && is_array($where)){
$where = implode(' ', $where);
$sql .= ' WHERE '.$where ;
}
$query = $this->db->query($sql);
$query -> SetFetchMode(PDO::FETCH_NUM);
while($row = $query->fetch()){
print_r($row);
}
} else {
echo 'failed, moron';
}
}
And this is the way to run the function :
$columnname = array('bookname');
$where = array('bookid','=','2');
echo $database-> selectdata('buku', $columnname, $where);
The code worked quite decently so far, but I'm wondering how I want to use $where but without $columnname in the function. How do I pass the arguments in the function?
And could you point to me the better way to create a function to grab data using PDO?
Just use a PDO class which can look like this:
<?php
class DB_Connect{
var $dbh;
function __construct(){
$host = "xxx";
$db = "xxx";
$user = "xxx";
$password = "xxx";
$this -> dbh = $this -> db_connect($host, $db, $user, $password);
}
public function getDBConnection(){
return $this -> dbh;
}
protected function db_connect($host, $db, $user, $password){
//var_dump($host, $db, $user, $password);exit();
try {
$dbh = new PDO("mysql:host=$host;dbname=$db", $user, $password);
}
catch(PDOException $err) {
echo "Error: ".$err->getMessage()."<br/>";
die();
}
return $dbh;
}
public function query($statement){
$keyword = substr(strtoupper($statement), 0, strpos($statement, " "));
$dbh = $this->getDBConnection();
if($dbh){
try{
$sql = $dbh->prepare($statement);
$exe = $sql->execute();
}
catch(PDOException $err){
return $err->getMessage();
}
switch($keyword){
case "SELECT":
$result = array();
while($row = $sql->fetch(PDO::FETCH_ASSOC)){
$result[] = $row;
}
return $result;
break;
default:
return $exe;
break;
}
}
else{
return false;
}
}
}
?>
Now you can include that class and create an object with $dbh = new DB_Connect; and call every statement you want just with the reference on $dbh->query($statement)
This is my prefered way to do this.
EDIT: If you want to use a statement on another Database, just use the __construct($db) method to pass your database name on object creation
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
}
}
I have a very simple query that works when I don't use parameters. With parameters, it returns nothing. Someone else posted the same issue over here:
Query with input parameters doesn't work whereas direct query works
However no one has answered it. Below is my code.
require_once('database.class.php');
class Plan extends Database {
public function getBenefitAmounts($plan_id, $group_id, $level) {
$sql = 'SELECT DISTINCT benefit FROM rates WHERE plan_id = :plan AND group_id IS NULL AND `level` = :lvl';
$params = array(':plan'=>896, ':lvl'=>1);
$this->sqlQuery($sql, $params);
// $sql = 'SELECT DISTINCT benefit FROM rates WHERE plan_id = 896 AND group_id IS NULL AND `level` = 1';
// $this->sqlQuery($sql);
$results = $this->sth->fetchAll(PDO::FETCH_COLUMN);
$options = '';
foreach ($results as $value) {
$options .= '<option value="' . $value . '">$' . $value . '</option>';
}
return $options;
}
}
In the database class:
public function sqlQuery($sql, $values_to_bind=null) {
$this->sth = $this->pdo->prepare($sql);
if (isset($values_to_bind)) {
foreach ($values_to_bind as $param => $value) {
$this->sth->bindValue($param, $value);
}
}
$success = $this->sth->execute();
if (!$success) {
$arr = $this->$sth->errorInfo();
print_r($arr);
}
}
The code commented out of the first code snippet works just fine, but with parameters, it returns nothing. The getBenefitAmounts function is called from another PHP file which is called using a JQuery get.
Did you try to add the third param which is optional for bindValue(). It can be something like PDO::PARAM_INT, PDO::PARAM_STR etc. Just try to debug and see if it helps.
I don't know why do you like so much try...catch if you use with no sense code. Because this technique: } catch (PDOException $e) { throw new PDOException($e);} means the same as } catch (PDOException $e) {;} like you ask php to do nothing if catch. Why do you asked to catch if you do nothing in case it happens?
Now my guess about how to fix your code:
public function sqlQuery($sql, $values_to_bind=null) {
$this->sth = $this->pdo->prepare($sql);
if (isset($values_to_bind)) {
foreach ($values_to_bind as $param => $value) {
$this->sth->bindValue($param, $value);
}
}
$success = $this->sth->execute();
if (!$success) {
$arr = $this->$sth->errorInfo();
print_r($arr);
}
}
By the way you use $this->sth = $this->pdo->prepare($sql); that means your sqlQuery function is a method of some class that you didn't show to us. and your first piece of code is somewhere outside that class? it would be better if you post full version of code, not just lines you think are involved.
and here you can switch to regular way:
//$results = $this->sth->fetchAll(PDO::FETCH_COLUMN); //you don't need it
$options = '';
while ($row = $this->sth->fetch(PDO::FETCH_ASSOC)) {
$options .= '<option value="' . $row['benefit'] . '">$' . $row['benefit'] . '</option>';
}
Why not bind the parameters using bindParam?
$plan = 896;
$lvl = 1;
$sth = $dbh->prepare("SELECT DISTINCT benefit FROM rates WHERE plan_id = :plan AND group_id IS NULL AND `level` = :lvl");
$sth->bindParam(":plan", $plan);
$sth->bindParam(":lvl", $lvl);
$sth->execute();
$r = $sth->fetchAll();
I am new to OOP, and I am switching all of my websites code to it! I am currently writing a class that grabs a user's information, and will eventually update it.
The code I am using is below:
<?php
require("C:\wamp\www\postin'\db_connection.php");
session_start();
class user {
public function __construct($userid, $connection, $information) {
$this->userid = $userid;
$this->connection = $connection;
$this->information = $information;
}
public function user_information($userid, $connection, $information) {
$query = "SELECT * FROM users WHERE id = :id";
$params = array(':id' => $userid);
try{
$stmt = $connection->prepare($query);
$result = $stmt->execute($params);
}
catch(PDOException $ex){
echo ("Failed to run query: " . $ex->getMessage());
}
$columns = $stmt->fetch();
return $columns["$information"];
}
}
$username = new user($_SESSION["logged_in"], $connection, "username");
echo $username->user_information($_SESSION["logged_in"], $connection, "username");
?>
Now as you can see on the last two lines of code (one from the end) I have to use the parameters twice. Basically the first parameter says what the ID is, second says what the $connection is, and the third is what I want to grab from the database. So what am I doing wrong? Did I define something I did not need to?
EDIT
Would the following be valid as well?
<?php
require("C:\wamp\www\postin'\db_connection.php");
session_start();
class user {
public function user_information($userid, $connection, $information) {
$query = "SELECT * FROM users WHERE id = :id";
$params = array(':id' => $userid);
try{
$stmt = $connection->prepare($query);
$result = $stmt->execute($params);
}
catch(PDOException $ex){
echo ("Failed to run query: " . $ex->getMessage());
}
$columns = $stmt->fetch();
return $columns["$information"];
}
}
$username = new user();
echo $username->user_information($_SESSION["logged_in"], $connection, "username");
?>
Like is this in-properer, or wrong...?
If the user class has all the information it needs as data members, then user_information doesn't need to take any arguments:
public function user_information() {
$query = "SELECT * FROM users WHERE id = :id";
$params = array(':id' => $this->userid);
try{
$stmt = $this->connection->prepare($query);
$result = $stmt->execute($params);
}
catch(PDOException $ex){
echo ("Failed to run query: " . $ex->getMessage());
}
$columns = $stmt->fetch();
return $columns[$this->information];
}
Since you have a lot of questions about the way a class works and about OOP I will try to give you a little direction.
There is no standard way of building your class. You are the one that decides what goes where in terms of what belongs to the class and what needs to be injected. This is just to tell you that you cannot pin yourself down. You need to get a feel for it and build a logic.
I took your class and rebuild it some with added comments. Hope that will help you some. Good luck!
<?php
require ("C:\wamp\www\postin'\db_connection.php");
session_start();
class user {
public $dbconnection;
public function __construct($connection) {
/**
* Your user class interacts with the database.
* Inject the connection here and set your
* global class variable.
*/
$this -> dbconnection = $connection;
}
public function user_information($userid, $column) {
/**
* The userid and column are specific for this
* method action. No need to set these variables
* in the global scope of the class.
*/
$query = "SELECT" . $column . " FROM users WHERE id = :id";
$params = array(':id' => $userid);
try {
$stmt = $this -> dbconnection -> prepare($query);
$stmt -> execute($params);
} catch(PDOException $ex) {
echo("Failed to run query: " . $ex -> getMessage());
}
$result = $stmt -> fetch();
return $result;
}
}
$username = new user($connection);
echo $username -> user_information($_SESSION["logged_in"], $information);
?>
I'm tinkering with a class that 'should' allow me to easily execute a fetchall query and display the results within a foreach statement. I assume all is working correctly as I have no errors. As for the foreach - this must be the problem? How would I foreach the results gained from the $connect->query()? I'm new to using any database OOP framework in my functions so I could be along the wrong lines completely.
<?
error_reporting(1);
class dbconnect {
private $host;
private $database;
private $username;
private $password;
private $pdo;
private $error;
public function __construct() {
$this->host = "localhost"; // Host
$this->database = "images"; // Database Name
$this->username = "*"; // Username
$this->password = "*"; // Password
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
);
try {
$this->pdo = new PDO("mysql:host={$this->host};dbname={$this->dbname};charset=utf8", $this->username, $this->password, $options);
}
catch(PDOException $e) {
$this->error = $e->getMessage();
}
}
public function query($query) {
try {
$stmt = $this->pdo->prepare($query);
$stmt->execute();
} catch(PDOException $ex) {
die("Failed to run query: " . $ex->getMessage());
}
$rows = $stmt->fetchAll();
return $rows;
}
}
$connect = new dbconnect;
$rows = $connect->query("select * from photos");
foreach($rows as $row):
print $row['id'];
endforeach;
?>
The $rows variable you're declaring inside query is not accessible to the outside, it is local to that function. Most likely, you simply want to return those results to the caller:
$rows = $stmt->fetchAll();
return $rows; // return value from function...
and have the caller capture that return value in its own variable:
$rows = $connect->query("select * from images"); // ... is received by caller
foreach($rows as $row):
Also check out dougjore's answer, you're mixing $this->stmt and $stmt inside your query method.
Pretty sure you aren't ever actually executing the query:
$this->stmt = $this->pdo->prepare($query);
$stmt->execute();
I believe (I could be wrong, I'm rather new to PDO myself and I haven't built a class for it), that you need to say $this->stmt->execute();
You could do
//PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
$this->stmt = $this->pdo->prepare($query);
$this->stmt->execute();
while ($result = $this->stmt->fetch(PDO::FETCH_ASSOC))
{
//do something with the result
}
Have a look here for more options to fetch PDO query results:
http://php.net/manual/en/pdostatement.fetch.php
$connect = new dbconnect;
$sql="select * from photos";
$stmt=$connect->pdo->prepare($sql);
$stmt->execute();
$result=$stmt->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
echo $key . "-" . $value . "<br/>";
}