I have this code:
class mysql {
public $mysql;
function __construct($host, $user, $pass, $db){
$this->mysql = new mysqli($host, $user, $pass, $db);
if($this->mysql->connect_errno)
exit('Error connecting to the database');
}
public function replace(array $var){
$str = "";
foreach($var as $k => $v){
$str .= substr_replace($v, "'", 0) . substr_replace ($v, "',", -1);
}
$str[strlen($str)-1] = "";
return $str;
}
public function insert($table, array $kv){
$p1 = implode(',', array_keys($kv));
$p2 = $this->replace($kv);
$q = "INSERT INTO $table ($p1) VALUES ($p2)";
echo $q;
echo $this->mysql->query($q);
}
}
And I use the function and no data is inserted to database I cant se anything on DB
Output of echo:
INSERT INTO users (username,password,email) VALUES ('Hi','Hwghrwhw','WREHRWWRWRGH')
I think the problem of your code is the missing escaping of your colnames
INSERT INTO `users` (`username`,`password`,`email`) VALUES ('Hi','Hwghrwhw','WREHRWWRWRGH')
PASSWORD is a protected keyword. Here your changed code:
public function insert($table, array $kv){
$p1 = implode('`,`', array_keys($kv));
$p2 = $this->replace($kv);
$q = "INSERT INTO `$table` (`$p1`) VALUES ($p2)";
echo $q;
echo $this->mysql->query($q);
}
Related
I am creating a class "DBQuery" that contains all the database query functions such as insert, select, delete, ...
Everything is working fine when I create database connection inside the INSERT function. But i want separate the configuration so that i can include it in any other files and pages.
configuration.php
define("HOSTNAME", "localhost");
define("USERNAME", "root");
define("PASSWORD", "");
define("DATABASE", "edubits");
try {
$conn = new PDO("mysql:host=" . HOSTNAME . ";dbname=" . DATABASE . ";", USERNAME, PASSWORD);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo $e;
}
class.php
/**
* Created by PhpStorm.
* User: Sunusi Mohd Inuwa
* Date: 11/18/2018
* Time: 11:02 AM
*/
class QUERY
{
function INSERT($table, $data, $conn)
{
include_once('../configuration.php');
// variable declaration
$columns = "";
$valueset = "";
$values = "";
//loop
foreach ($data as $column => $value) {
$columns = $columns . ', ' . $column;
$valueset = $valueset . ', ?';
$values = $values . ', ' . $value;
}
//trimming the first comma from the result above
$columns = ltrim($columns, ',');
$valueset = ltrim($valueset, ',');
$values = ltrim($values, ',');
//statement
$sql = "INSERT INTO " . $table . "(" . $columns . ") VALUES(" . $valueset . ")";
//convert values to array
$values = explode(',', $values);
//query
$query = $conn->prepare($sql)->execute($values);
//$query = $conn->prepare($sql)->execute([$values]);;
}
}
Use include, not include_once. If you use include_once, then it won't execute the code in the file the second time you call the method.
But it would probably be better to include the file in the class's constructor, so you only need to execute it once, rather than create a new connection every time you perform a query. Make $conn a class property instead of an ordinary variable.
The class below give the ability to get a connection object from getInstance() funtion, so you just include the Config class where you wanna communicate with database (model)
getInstance() : is singleton, which means that you have a single instance
class Config{
private $HOSTNAME = "localhost";
private $USERNAME = "root";
private $PASSWORD = "";
private $DATABASE = "edubits";
private static $pdo = null;
public static function getInstance($data = null){
if(self::$pdo == null){
self::PDOConnect($data = null);
}
return self::$pdo;
}
private static function PDOConnect(){
try{
$info = new DBInfo($data);
self::$pdo = new PDO("mysql:host=" . $this->HOSTNAME . ";dbname=" . $this->DATABASE . ";", $this->USERNAME, $this->PASSWORD);
self::$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
self::$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e) {
echo new PDOCustomException($e->getMessage(), null, $e);
}
}
public function close(){
return null;
}
}
Here i've choice to use config directly from your INSERT function to get connection object, or get connexion object in constructor one time and use it many time in QUERY class
So connection instance is stored on $cn
include_once('../configuration.php');
class QUERY
{
private $cn = null;
private $DBAction = null;
public function __construct(){
try {
$cn = new DBAction();
$this->cn = $cn::getInstance();
} catch (\PDOException $ex) {
throw new PDOCustomException($ex->getMessage(), null, $ex);
} catch (\Exception $ex) {
throw new CustomException($ex->getMessage(), null, $ex);
}
}
public function INSERT($table, $data, $conn) {
$config = new Config();
// variable declaration
$columns = "";
$valueset = "";
$values = "";
//loop
foreach ($data as $column => $value) {
$columns = $columns . ', ' . $column;
$valueset = $valueset . ', ?';
$values = $values . ', ' . $value;
}
//trimming the first comma from the result above
$columns = ltrim($columns, ',');
$valueset = ltrim($valueset, ',');
$values = ltrim($values, ',');
//statement
$sql = "INSERT INTO " . $table . "(" . $columns . ") VALUES(" . $valueset . ")";
//convert values to array
$values = explode(',', $values);
//query
$query = $this->cn->prepare($sql)->execute($values);
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
My INSERT statement is not working. The number of rows affected is affected is 0. Here is my code :
<?php
require_once('class.config.php');
class userActions{
public $link;
function __construct(){
$db_connection = new dbConnection();
$this->link = $db_connection->connect();
return $this->link;
}
function registerUsers($username, $password, $ip_address){
$query = $this->link->prepare("INSERT INTO users (user_name,password,ip_address) VALUES (?,?,?)");
$values = array($username, $password, $ip_address);
$query->execute($values);
$counts = $query->rowCount();
return $counts;
}
}
$users = new userActions();
echo $users->registerUsers('bob', 'dave123','127.0.0.1');
?>
What have I done wrong?
EDIT : this is my class.config.php:
class dbConnection{
protected $db_conn;
public $db_host = "localhost:8080";
public $db_user = "root";
public $db_pass = "";
public $db_name = "facebook";
function connect(){
try{
$this->db_conn = new PDO("mysql:host = $this->db_host; dbname = $this->db_name",
$this->db_user, $this->db_pass);
$this->db_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->db_conn;
}
catch(PDOException $e){
return "MySQL error : " . $e->getMessage();
}
}
}
Change your registerUsers function code to below
If you are using mysqli then use below
function registerUsers($username, $password, $ip_address){
$query = $this->link->prepare("INSERT INTO users (user_name,password,ip_address) VALUES (?,?,?)");
$query->bind_param("sss", $username, $password, $ip_address);
$query->execute();
}
EDIT
As I see you are using PDO.
Try to use like anyone of below
function registerUsers($username, $password, $ip_address){
$query = $this->link->prepare("INSERT INTO users (user_name,password,ip_address) VALUES (:username,:password,:ip_address)");
$query->bindParam(':username', $username);
$query->bindParam(':password', $password);
$query->bindParam(':ip_address', $ip_address);
$query->execute();
}
OR
function registerUsers($username, $password, $ip_address){
$query = $this->link->prepare("INSERT INTO users (user_name,password,ip_address) VALUES (:username,:password,:ip_address)");
$query->execute(array('username' => $username, 'password' => $password, 'ip_address' => $ip_address));
}
I would prefer to use bindParam as it is secure and it replaces my_real_escape_string.
this below can can help you to understand how to insert to database via oop programming
databse class:
public static $con;
public static function connect($hostname , $username , $password , $database)
{
self::$con = mysqli_connect($hostname , $username , $password , $database) or die('Error: '.mysqli_connect_error());
}
public static function disconnect()
{
mysqli_close(self::$con);
}
public static function insert($sql , $values)
{
$values = self::safeValues($values);
$sql = self::$con->prepare($sql);
mysqli_set_charset(self::$con , 'UTF8');
self::bindValues($sql , $values);
$save = $sql->execute();
return $save;
}
public function safeValues($values = null)
{
if($values != null)
{
for($i = 0 ; $i < count($values) ; $i++)
{
$values[$i] = trim($values[$i]);
$values[$i] = strip_tags($values[$i]);
mysqli_real_escape_string(self::$con , $values[$i]);
}
}
return $values;
}
public function bindValues($sql, $values = null)
{
if ($values != null)
{
// Generate the Type String (eg: 'issisd')
$types = '';
foreach($values as $value)
{
if(is_int($value))
$types .= 'i';
elseif (is_float($value))
$types .= 'd';
elseif (is_string($value))
$types .= 's';
else
$types .= 'b';
}
// Add the Type String as the first Parameter
$bind_names[] = $types;
// Loop thru the given Parameters
for ($i = 0 ; $i < count($values) ; $i++)
{
// Create a variable Name
$bind_name = 'bind'.$i;
// Add the Parameter to the variable Variable
$$bind_name = $values[$i];
// Associate the Variable as an Element in the Array
$bind_names[] = &$$bind_name;
}
// Call the Function bind_param with dynamic Parameters
call_user_func_array(array($sql,'bind_param') , $bind_names);
}
return $sql;
}
and in your home class you can insert like this:
home class:
DB::connect('localhost' , 'username' , 'password' , 'database');
DB::insert("INSERT INTO table(field1, field2) VALUES (? , ?)" , [ $val1 , $val2 ] );
i hope this can be helpful for you.
So I have solved my code by removing localhost:8080 with 127.0.0.1 in my class.config.php.
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 have a function with 2 arguments. Here it is
function listBoats($con,$table){
//get record set for all boats sort them by their "sort" number
$queryBoat = "SELECT * FROM " .$table. " WHERE `id` <> 'mainPage' ORDER BY `sort` LIMIT 0, 1000";
$result = mysqli_query($con,$queryBoat);
return $result;
}
here is how I'm calling it
$result = listBoats($con,"CSINSTOCK"); //run query to list all the boats in the CSINSTOCK table
I can't get it to work. But If I add the variable $table = "CSINSTOCK" inside the function it does work. Why wont the function pass the "CSINSTOCK" variable through?
I would suggest that you use PDO. Here is an example
EXAMPLE.
This is your dbc class (dbc.php)
<?php
class dbc {
public $dbserver = 'server';
public $dbusername = 'user';
public $dbpassword = 'pass';
public $dbname = 'db';
function openDb() {
try {
$db = new PDO('mysql:host=' . $this->dbserver . ';dbname=' . $this->dbname . ';charset=utf8', '' . $this->dbusername . '', '' . $this->dbpassword . '');
} catch (PDOException $e) {
die("error, please try again");
}
return $db;
}
function getAllData($qty) {
//prepared query to prevent SQL injections
$query = "select * from TABLE where qty = ?";
$stmt = $this->openDb()->prepare($query);
$stmt->bindValue(1, $qty, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $rows;
}
?>
your PHP page:
<?php
require "dbc.php";
$getList = $db->getAllData(25);
foreach ($getList as $key=> $row) {
echo $row['columnName'] .' key: '. $key;
}
If you have the access to your database you should be able to perform your required operations.
I'm having trouble finding good documentation on pdo update prepared statements and even more trouble finding documentation on dynamically updating the database with pdo prepared statements. I've gotten my dynamic insert to work but am having trouble with the update. The error I'm getting is:
Warning: PDOStatement::execute() [pdostatement.execute]:
SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
in
/Users/scottmcpherson/Sites/phpsites/projectx/application/models/db.php
on line 91 error
Here is the class I created minus a couple of methods that are irrelevant to this problem:
<?php
require_once("../config/main.php");
class Database{
protected static $dbFields = array('username', 'password');
public $db;
public $tableName = 'users';
public $id = 1;
public $username = "Jonny";
public $password = "Appleseed";
public function __construct() {
$this->connect();
}
public function connect(){
try {
$this->db = new PDO("mysql:host=".DB_SERVER."; dbname=".DB_NAME, DB_USER, DB_PASS);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
public function properties() {
$properties = array();
foreach (self::$dbFields as $field) {
if (isset($this->field) || property_exists($this, $field)) {
$properties[$field] = $this->$field;
}
}
return $properties;
}
public function propertyValues() {
$property = $this->properties();
$propertyValues = array();
foreach ($property as $key => $value) {
$propertyValues = ":" . implode(", :", array_keys($property));
}
return $propertyValues;
}
public function polishedVals(){
// The end result of this function is:
// username=:username, password=:password
$props = $this->properties();
$phaseOne = array();
foreach ($props as $key => $value) {
$phaseOne[$key] = ":".$key;
}
$phaseTwo = array();
foreach ($phaseOne as $key => $value) {
$phaseTwo[] = "{$key}={$value}";
}
$polishedVals = implode(", ", $phaseTwo);
return $polishedVals;
}
public function update(){
$stmt = "UPDATE ". $this->tableName." SET ";
$stmt .= $this->polishedVals();
$stmt .= "WHERE id=" . $this->id;
$stmt = $this->db->prepare($stmt);
if($stmt->execute($this->properties())) {
echo "yes";
} else {
echo "error ";
}
}
}
$database = new Database();
echo$database->update();
?>
With all the variables replaced with the actual values, the result I'm going for with the update() method would look like this:
public function update(){
$stmt = "UPDATE users SET ";
$stmt .= "username=:username, password=:password ";
$stmt .= "WHERE id=1";
$stmt = $this->db->prepare($stmt);
if($stmt->execute($this->properties())) {
echo "yes";
} else {
echo "error ";
}
}
In addition to spotting this problem, please let me know if you see any other issues with this code. I'm still kind of new to PHP.
Edit: I've now created a new method that adds a : to the beginning of each key in the properties array:
public function colProperties(){
$properties = $this->properties();
$withCols = array();
foreach($properties as $key => $value){
$withCols[":".$key] = $value;
}
return $withCols;
}
So my update() method now looks like:
public function update(){
$stmt = "UPDATE ". $this->tableName." SET ";
$stmt .= $this->polishedVals();
$stmt .= "WHERE id=" . $this->id;
$stmt = $this->db->prepare($stmt);
if($stmt->execute($this->colProperties())) {
echo "yes";
} else {
echo "error ";
}
}
and if I var_dump($this->colProperties) I get:
array(2) { [":username"]=> string(5) "Jonny" [":password"]=> string(9) "Appleseed" }
And still getting the same error.
I don't think that passing parameters to an UPDATE query requires a different method than a SELECT one. The information in the PDOStatement->execute() manual page should apply:
<?php
/* Execute a prepared statement by passing an array of insert values */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->execute(array(':calories' => $calories, ':colour' => $colour));
?>
You are using named parameters so execute() expects an associative array. Use var_dump() to display $this->properties() right before execute():
var_dump($this->properties())
Make sure you keys match exactly.
The error is that in between
$stmt .= $this->polishedVals();
$stmt .= "WHERE id=" . $this->id;
There needs to be a space in between the WHERE clause as the polishedVals() method does not add a space after the implode. So, you'll have something like
UPDATE User SET city=:city, location=:locationWHERE User.id=28
Which causes the error.
Simple bug.