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.
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);
}
}
I learning oop and want to use pdo to execute mysql query. I have a query inside function that I want to execute. When I do this I get an error:
Fatal error: Call to a member function exec() on a non-object
What I'am doing wrong?
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
function testDuplicate($model) {
$SQL = "SELECT product_id FROM " . DB_PREFIX . "product WHERE model LIKE '" .$model . "'";
$result = $conn->exec($SQL);
if ($result->rows) return false;
return true;
}
function testDuplicateCat($cat) {
$SQL = "SELECT category_id FROM " . DB_PREFIX . "category WHERE category_id = '" .$cat . "'";
$result = $conn->exec($SQL);
if ($result->rows) return false;
return true;
}
foreach ($xml->PRODUCT as $child) {
if(testDuplicate($child->ID)){
...
}
}
This issue is raised because the $conn variable inside the testDuplicate function is not defined inside the scope of the function.
You could do this:
function testDuplicate($model) {
global $conn;
...
}
However it is not advice able to do so, its better to use static variables.
function getconn(){
static $conn;
if(!isset($conn)){
$conn = new PDO(...);
}
return $conn;
}
function foobar(){
$result = getconn()->query($sql);
while($row = $result->fetch()){
$ids[] = $row['category_id'];
}
return sizeof($ids) > 0 ? $ids : false;
}
if(($list = foobar()) == false){
echo "products " . var_export($list) . ' are duplicate values';
}
Why? Because you cannot simply overwrite the connection variable, even by accident or by using someone elses code. There are better alternatives but this is just a quick and safe example.
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 am very new to programming with PHP and am working on a fun little game to help myself learn. I got some code help from others on pulling a character's stats from the DB but am having trouble getting it to work. I just get "server error" when I try to run it right now. The Database information is fine, and I previously had a working function that pulled from the DB, but wanted to universalize it through a class function. Here is what I have so far.
DB class:
<?php
class db_class
{
//db connection portion
protected $mysqli;
private $db_host = 'XXXXXXX';
private $db_user = 'Filler';
private $db_password = 'Filler';
protected $db_name = 'Filler';
//db connection portion
public function __construct($db_host = null, $db_user = null, $db_password = null, $db_name = null) {
if (!empty($db_host)) {
$this->db_host = $db_host;
}
// validate other parameters similarly
//database connection object
$mysqli = new mysqli($this->db_host, $this->db_user, $this->db_password, $this->db_name);
if ($mysqli->connect_error) {
throw new Exception('Connect Error: ' . $mysqli->connect_errno . ', ' . $mysqli->connect_error);
} else {
$this->mysqli = $mysqli;
}
}
public function getPlayerStats($id) {
if (empty($id)) {
throw new Exception ('An empty value was passed for id');
}
// verify this is integer-like value
$id = (string) $id;
$pattern = '/^\d+$/';
if (!preg_match($pattern, $id) !== 1) {
throw new Exception ('A non-integer value was passed for id');
}
$id = (int) $id;
$query = "SELECT id, name, strength, defense, level, health, type, experience FROM characters WHERE id = :id";
$stmt = $this->mysqli->prepare($query);
$stmt->bind_param('i', $id);
$result = $stmt->execute();
if (false === $result) {
throw new Exception('Query error: ' . $stmt->error);
} else {
$obj = new stdClass();
$stmt->bind_result($obj->id, $obj->name, $obj->strength, $obj->defense, $obj->level, $obj, health, $obj->type, $obj->experience);
$stmt->fetch();
$stmt->close();
return $obj;
}
}
}
?>
DB class function call:
<?php
include "db_class.php";
echo "made it out here1";
$classobject = new db_class();
echo "made it out here2";
$results = $classobject->getPlayerStats('1');
print_r($results);
echo "made it out here3";
$id = "id: " . $results['id'];
$name = "name: " . $results['charname'];
$strength = "strength: " . $results['strength'];
$defense = "defense: " . $results['defense'];
$health = "health: " . $results['health'];
$level = "level: " . $results['level'];
$type = "type: " . $results['type'];
$experience = "experience: " . $results['experience'];
echo "<br/>";
echo "made it out here4";
?>
It is difficult to debug this code since I'm used to just putting in breaklines and running through coding errors in things like VBA in compilers, so any debugging tips would be greatly helpful. What am I doing wrong here? Thanks in advance!
You wrote
public __construct($db_host = NULL, ...
but constructors are functions. You need
public function __construct($db_host = NULL, ...
Your db_class constructor accepts four parameters. This instantiation passes none.
$classobject = new db_class();
So you end up with junk in your connection string. Sort that out and you'll be on your way.
You can avoid a lot of debugging by building minimal versions that work. For example, you can write this first.
<?php
class db_class{
public function __construct($db_host = NULL, $db_user = NULL, $db_password = NULL, $db_name = NULL) {
}
}
?>
If that works, check it in to version control, then add a little code to it. (How do you know whether it works? Test it.)
I have this (from someone else derived from my first attempt at a database class):
require_once( "declarations.php" );
class Database{
private static $mysqli;
private static $dbName = '';
private static $username = '';
private static $password = '';
private static $host = 'localhost';
private static $prefix = '';
public function __construct(){
if( self::$host & self::$username & self::$password & self::$dbName )
{
self::$mysqli = new mysqli( self::$host, self::$username, self::$password, self::$dbName );
if (self::$mysqli->connect_error) {
die('Connect Error (' . self::$mysqli->connect_errno . ') '
. self::$mysqli->connect_error);
}
}
else
{
echo "You forgot to fill in your database connection details";
}
}
public function Query( $query ){
$query = self::$mysqli->real_escape_string( $query );
if ($query = self::$mysqli->prepare($query)) {
$query->execute();
$query->store_result();
$stmt = $query->result;
//$query->mysql_num_rows = $stmt->num_rows();
$query->close();
return $stmt;
}
}
public function Close()
{
self::$mysqli->close();
}
}
This is how i'm calling it:
include_once( "system/database.php" );
$query = "SELECT * FROM app";
$dbr = new Database();
//Change this here since your method is query and not $mysqli
while( $row = $dbr->Query( $query )->fetch_object() ){
echo '<td>'. $row['id'] . '</td>' ;
echo '<td>'. $row['title'] . '</td>' ;
}
Database::Close();
I am getting an error Call to a member function fetch_object() on a non-object in on the while loop.
Any ideas?
fetch_object works with result set returned after query is executed with methods like: mysql_query or use fetch_assoc instead with
$query->execute();
$result = $query->get_result();
while ($myrow = $result->fetch_assoc()) {
//Your logic
}
Well, your first attempt resulted with totally unusable code.
There are 2 critical faults and one serious one.
As I told you already, doing $query = self::$mysqli->real_escape_string( $query ); is useless and harmful at once. You have to get rid of this line. Completely and forever.
Preparing a query without binding variables is totally useless.
You have to check for mysql errors.
So, at the very least your query() function have to be
public function query($query)
{
$res = self::$mysqli->query($query);
if (!$res)
{
throw new Exception(self::$mysqli->error);
}
return $res;
}
But again - this function is not safe as it's not not implementing placeholders to substitute data in the query.