I would like to make a CRUD class, for inserting, updating and deleting data, in the __contruct function, I don't want to call the connection, I would only specify the connection name, then I am getting this error:
PHP Fatal error: Call to a member function prepare
() on a non-object in crud.php on line 60
<?php
/* Start (config.php)
This part of code is only to show you that the connection name is "connexion" which is called in config.php
$connexion = new PDO('mysql:host='.$db_host.';dbname='.$db_name, $db_user, $db_passwd
, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES '.$db_charset.'')); //SET NAMES utf8
$connexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
EnD */
classDB.php
require_once('config.php');
final class crud {
public function __construct($connexionName) {
$this->connexionName = $connexionName;
}
public final function insert($tableName, $fields=array()){
$this->tableName = $tableName;
$this->fields = $fields;
foreach ($this->fields as $kf => $vf) {
$inKeys[] = $kf;
$inKeysDotted[] = ':' . $kf;
$insertedKeys = implode(', ', $inKeys);
$insertedKeysDotted = implode(', ', $inKeysDotted);
}
echo '<br />';
$sql = "INSERT INTO $this->tableName ($insertedKeys) VALUES ($insertedKeysDotted)";
$insertItems = $this->connexionName->prepare("$sql"); // THIS IS LINE 60
echo 'insert '.$insertItems.'<br />';
} // end insert()
} // end CRUD
$con = new crud($connexion);
echo '<br />';
$con->insert('ban_ip', array('visitor_type'=>'5', 'ip'=>'111.222.333.444'));
?>
Thanks in advance
Related
I got an error when I want to consume a Rest API using postaman and docker.
The error is marked in this line of code: Error in php Connection Error: could not find driver
<?php
class Materias {
// DB stuff
private $conn;
private $table = 'materias';
// Materias Properties
public $clave_materia;
public $nombre_materia;
public $semestre;
public $creditos;
// Constructor with DB
public function __construct($db) {
$this->conn = $db;
}
// Get Materias
public function read() {
// Create query
$query = 'SELECT * FROM ' . $this->table;
// Prepare statement
$stmt = $this->conn->prepare($query);
// Execute query
$stmt->execute();
return $stmt;
}
// Get Single Materia
public function read_single() {
// Create query
$query = 'SELECT * FROM ' . $this->table . 'WHERE clave_materia = ?';
// Prepare statement
$stmt = $this->conn->prepare($query);
// Bind clave_materia
$stmt->bindParam(1, $this->clave_materia);
// Execute query
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
// Set properties
$this->nombre_materia = $row['nombre_materia'];
$this->semestre = $row['semestre'];
$this->creditos = $row['creditos'];
}
// Create Post
public function create() {
// Create query
$query = 'INSERT INTO ' . $this->table . ' SET clave_materia = :clave_materia, nombre_materia = :nombre_materia, semestre = :semestre, creditos = :creditos';
// Prepare statement
$stmt = $this->conn->prepare($query);
// Clean data
$this->clave_materia = htmlspecialchars(strip_tags($this->clave_materia));
$this->nombre_materia = htmlspecialchars(strip_tags($this->nombre_materia));
$this->semestre = htmlspecialchars(strip_tags($this->semestre));
$this->creditos = htmlspecialchars(strip_tags($this->creditos));
// Bind data
$stmt->bindParam(':clave_materia', $this->clave_materia);
$stmt->bindParam(':nombre_materia', $this->nombre_materia);
$stmt->bindParam(':semestre', $this->semestre);
$stmt->bindParam(':creditos', $this->creditos);
// Execute query
if($stmt->execute()) {
return true;
}
// Print error if something goes wrong
printf("Error: %s.\n", $stmt->error);
return false;
}
// Update Post
public function update() {
// Create query
$query = 'UPDATE ' . $this->table . '
SET nombre_materia = :nombre_materia, semestre = :semestre, creditos = :creditos
WHERE clave_materia = :clave_materia';
// Prepare statement
$stmt = $this->conn->prepare($query);
// Clean data
$this->nombre_materia = htmlspecialchars(strip_tags($this->nombre_materia));
$this->semestre = htmlspecialchars(strip_tags($this->semestre));
$this->creditos = htmlspecialchars(strip_tags($this->creditos));
$this->clave_materia = htmlspecialchars(strip_tags($this->clave_materia));
// Bind data
$stmt->bindValue(':nombre_materia', $this->nombre_materia);
$stmt->bindValue(':semestre', $this->semestre);
$stmt->bindValue(':creditos', $this->creditos);
$stmt->bindValue(':clave_materia', $this->clave_materia);
// Execute query
if($stmt->execute()) {
return true;
}
// Print error if something goes wrong
printf("Error: %s.\n", $stmt->error);
return false;
}
// Delete Post
public function delete() {
// Create query
$query = 'DELETE FROM ' . $this->table . ' WHERE clave_materia = :clave_materia';
// Prepare statement
$stmt = $this->conn->prepare($query);
// Clean data
$this->clave_materia = htmlspecialchars(strip_tags($this->clave_materia));
// Bind data
$stmt->bindParam(':clave_materia', $this->clave_materia);
// Execute query
if($stmt->execute()) {
return true;
}
// Print error if something goes wrong
printf("Error: %s.\n", $stmt->error);
return false;
}
}
Error:
Connection Error: could not find driver<br />
<b>Fatal error</b>: Uncaught Error: Call to a member function prepare() on null in /var/www/html/models/Materias.php: 24
Stack trace:
#0 /var/www/html/api/materias/read.php(17): Materias->read()
#1 {main
}
thrown in <b>/var/www/html/models/Materias.php</b> on line <b>24</b><br />
**bd connection**
<?php
class Database {
// DB Params
private $host = 'localhost';
private $db_name = 'reticula';
private $username = 'root';
private $password = 'test ';
private $conn;
// DB Connect
public function connect() {
$this->conn = null;
try {
$this->conn = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->db_name, $this->username, $this->password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo 'Connection Error: ' . $e->getMessage();
}
return $this->conn;
}
}
This is where you call matters
<?php
// Headers
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
include_once '../../config/Database.php';
include_once '../../models/Materias.php';
// Instantiate DB & connect
$database = new Database();
$db = $database->connect();
// Instantiate blog post object
$materias = new Materias($db);
// Blog post query
$result = $materias->read();
// Get row count
$num = $result->rowCount();
// Check if any posts
if($num > 0) {
// Post array
$materias_arr = array();
// $posts_arr['data'] = array();
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
extract($row);
$materias_item = array(
'clave_materia' => $clave_materia,
'nombre_materia' => $nombre_materia,
'semestre' => $semestre,
'creditos' => $creditos
);
// Push to "data"
array_push($materias_arr, $materias_item);
// array_push($posts_arr['data'], $post_item);
}
// Turn to JSON & output
echo json_encode($materias_arr);
} else {
// No Posts
echo json_encode(
array('message' => 'No Posts Found')
);
}
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 am currently practicing OOP, creating a MySQLi class that will have atleast the basic MySQLi functions (insert, select, update, etc). This is what I have got so far:
if(!class_exists('dbc')) {
class dbc {
public function __construct($host = host, $username = username, $password = password, $database = database) {
// Make the constants class variables
$this->host = host;
$this->username = username;
$this->password = password;
$this->database = database;
$this->connection = new mysqli($this->host, $this->username, $this->password, $this->database);
if($this->connection->connect_errno) {
die('Database connection error!');
return false;
}
}
public function __deconstruct() {
if($this->connection) {
$this->connection->close();
}
}
public function insert($table, $variables = array()) {
if(empty($table) || empty($variables)) {
return false;
}
$sql = "INSERT INTO $table ";
$fields = array();
$values = array();
foreach($variables as $field => $value) {
$fields[] = "'" . $field . "'";
$values[] = "'" . $value . "'";
}
$fields = '(' . implode(', ', $fields) . ')';
$values = '(' . implode(', ', $values) . ')';
$sql .= $fields . ' VALUES ' . $values;
$query = $this->connection->query($sql);
if(!$query) {
echo mysqli_error($this->connection);
}
echo $sql;
}
}
}
As you can see, I create the connection via the details from the config file, I then send a query through the established connection. But for some reason when I attempt to create a MySQLi insert query, I just get the same error over, and over again:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''name', 'option') VALUES ('Sub Title', 'This is a test website')' at line 1
I even echoed out the sql query, which appeared to be the correct format:
INSERT INTO options ('name', 'option') VALUES ('Sub Title', 'This is a test website')
I have spent hours of Googling, trial and error, etc, trying to fix this, and have had no luck, and as it's 12:30am, I'm tired and may be missing something critical, so if anyone knows what is causing this problem, it'll be greatly appreciated for a solution, etc.
Thanks,
Kieron
The column names in the first set of parenthesis should not be quoted:
INSERT INTO options (name, option) VALUES ('Sub Title', 'This is a test website')
// ^^^^ ^^^^^^
Though you can use backticks ` around the column names e.g. `name`, `option`.
Your connection is definitely not working as you are missing the $ on these 4 lines infront of the parameter names
$this->host = host;
$this->username = username;
$this->password = password;
$this->database = database;
Should be
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->database = $database;
Also the name you have used for your class deconstructor is incorrect it should be
public function __destruct() () {
yours will not cause an error but it will not run automatically on class destruction with your name.
#Marty is correct about the use of backticks and not single quotes around your query syntax, but I dont see how the connection gets made based on the first error I mentioned, and therefore how you get a sensible SQL error reported, however something may be going on that is not obvious from the code you showed us.
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.
This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 10 years ago.
I'm new to php oop.here i wanted to do database connectivity with singleton class but i got error like this:
Fatal error: Call to a member function getOne() on a non-object in C:\xampp\htdocs\singleton\new\singleton_db.php
here i have given two file
1.singleton_db.php
<?php
class database
{
public $query;
public $results;
public $conn;
public static $database;
//connect to the database
public function __construct()
{
$this->conn = mysql_connect('localhost','root','');
if ($this->conn)
{
mysql_select_db('test1');
}
}
public static function instance()
{
if (!isset(self::$database)) {
self::$database = new database();
}
return self::$database;
}
function getOne($sql) {
$result = $this->conn->getOne($sql); //Error in this line
if(database::isError($result)) {
throw new Exception($result->getMessage(), $result->getCode());
}
return $result;
}
function startTransaction() {
//autoCommit returns true/false if the command succeeds
return $this->conn->autoCommit(false);
}
function commit() {
$result = $this->conn->commit();
if(database::isError($result)) {
throw new Exception($result->getMessage(), $result->getCode());
}
$this->conn->autoCommit(true);
return true;
}
function abort() {
$result = $this->conn->rollback();
if(database::isError($result)) {
throw new Exception($result->getMessage(), $result->getCode());
}
return true;
}
//returns numerically indexed 1D array of values from the first column
public function insert($table, $arFieldValues) {
$fields = array_keys($arFieldValues);
$values = array_values($arFieldValues);
// Create a useful array of values
// that will be imploded to be the
// VALUES clause of the insert statement.
// Run the mysql_real_escape_string function on those
// values that are something other than numeric.
$escVals = array();
foreach($values as $val) {
if(! is_numeric($val)) {
//make sure the values are properly escaped
$val = "'" . mysql_real_escape_string($val) . "'";
}
$escVals[] = $val;
}
//generate the SQL statement
$sql = " INSERT INTO $table (";
$sql .= join(', ', $fields);
$sql .= ') VALUES(';
$sql .= join(', ', $escVals);
$sql .= ')';
$hRes = mysql_query($sql);
if(! is_resource($hRes)) {
$err = mysql_error($this->conn) . "\n" . $sql;
throw new Exception($err);
}
return mysql_affected_rows($hRes);
}
}
2.data.php
<?php
require_once('singleton_db.php');
try {
$db = database::instance();
} catch (Exception $e) {
// No point continuing...
die("Unable to connect to the database.");
}
$sql = "SELECT count(1) FROM mytable";
$count = $db->getOne($sql);
print "There are $count records in mytable!<br>\n";
// start a transaction
$db->startTransaction();
// do an insert and an update
try {
$arValues = array();
$arValues['id'] = '#id#';
$arValues['myval'] = 'blah blah blah';
$newID = $db->insert('mytable', $arValues);
print "The new record has the ID $newID<br>\n";
// update the record we just created
$arUpdate = array();
$arUpdate['myval'] = 'foobar baz!';
$affected = $db->update('mytable', $arUpdate, "id = $newID");
print "Updated $affected records<br>\n";
// write the changes to the database
$db->commit();
} catch (Exception $e) {
// some sort of error happened - abort the transaction
// and print the error message
$db->abort();
print "An error occurred.<br>\n" . $e->getMessage();
}
?>
What could I do to fix this ?
Your problem is you haven't defined the
getOne();
method properly. The property
$this->conn
Is just the result of mysql_connect() function which is a "MySQL link identifier on success, or FALSE on failure". It is not an object, and such, you can not ask it for the getOne(); method.