I tried to do a simple CRUD using a class connectDB to connect to a MySQL database. Then when I try to execute the method delRecipe of the class RecipesModel the system show me an error.
Fatal error: Call to undefined method connectDB::prepare()
Is the right way to call the method prepare()? Why is not recognized?
Here is the code of connectDB (file connectDB.php)
class connectDB {
private $address='localhost';
private $db_name='db-name';
private $user='root';
private $pswd='psswd';
private $sql;
public function __construct() {
$this->sql = new mysqli($this->address,$this->user,$this->pswd,$this->db_name);
if (mysqli_connect_error()) {
die('Error de Conexion: '. mysqli_connect_errno().' - '.mysqli_connect_error());
}
return $this->sql;
}
public function __destruct() {
if(!mysqli_close($this->sql)) {
die('ERROR!:'.$this->sql->error);
}
}
public function execute($query) {
$res = $this->sql->query($query);
if ($res) {
return $res;
}
else {
die('ERROR!:'.$this->sql->error);
}
}
}
And the class that delete the row.
<?php
require_once('connectDB.php');
class RecipesModel {
private $db;
public function __construct() {
$this->db = new connectDB();
}
public function delRecipe($id) {
if (is_numeric($id)) {
$sql = 'DELETE FROM t_platos WHERE ID_pl= ?';
$this->db->prepare($sql);
return $this->db->execute(array($id));
}
}
}
$recipe = new RecipesModel();
$res = $recipe->delRecipe(1);
?>
Your misunderstanding is this:
return $this->sql;
You can't return something of your choice in a constructor. The value returned by a constructor is always the object instance of that class.
Your connectDB class does not have a method called prepare().
You're probably trying to call $this->db->sql->prepare(), since in connectDB you store the actual database connection into $this->sql. However, since the $sql property is private, you can't do that.
You'll either need to make $sql a public property, or create a method in your connectDB class to act as a proxy.
Related
I am new to the class programming in php ,Here is my database class.
class Database
{
private $_connection;
private static $_instance; //The single instance
private $_host = 'localhost';
private $_username = 'root';
private $_password = '';
private $_database = 'admission_portal';
//connect to database
public function connectDb()
{
try {
$this->_connection = new \PDO("mysql:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password);
/*** echo a message saying we have connected ***/
echo 'Connected to database';
} catch (PDOException $e) {
echo $e->getMessage();
}
}
//run the query
public function run($sql)
{
$result=$this->_connection->prepare($sql);
return $result->execute();
}
}
I am extending this to core class to do some database operations.
class Core extends Database
{
//get all the universities
public function getData()
{
Database::connectDb();
$sql = 'SELECT * FROM `adm_universities`';
$r=Database::run($sql);
print_r($r->fetchAll(PDO::FETCH_OBJ));
}
}
Now i am invoking getData function like this way.
$db=new Core();
$db->getData();
But i will get this
Fatal error: Call to a member function fetchAll() on boolean.
What is the error in my code?please help me
You need to return the $result only in the run() method:
public function run($sql)
{
$result=$this->_connection->prepare($sql);
$result->execute();
return $result;
}
Returning the $result->execute(); is returning true because the execute() succeeded. You need to return the current state of $result.
See if that works.
Im getting a Fatal error: Call to undefined method PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection::prepare() on a phpunit test where I'm preparing a PDO statement. If the default database connection is a copy of the pdo object that successfully connects, wouldn't it have access to its methods?
My Class and the function in question:
class User
{
protected $db;
public function __construct($db)
{
$this->db = $db;
}
public function deleteItem($itemId)
{
$sql = "
DELETE FROM Users WHERE id = ?";
$sth = $this->db->prepare($sql);//this is the failed line works on other tests
return $sth->execute(array($itemId));
}
My Test:
class RosterDBTest extends PHPUnit_Extensions_Database_Testcase
{
public function getConnection()
{
$pdo = new PDO('mysql:host=localhost;dbname=users','root','root');
return $this->createDefaultDBConnection($pdo,"users");
}
public function getDataSet()
{
return $this->createFlatXMLDataset(
dirname(__FILE__) . '/users.xml');
}
public function setup()
{
$this->db = $this->getConnection();
}
public function testRemoveUser()
{
$testUser = new User($this->db);
$expectedUsers = 123;
$testUser->deleteItem(91);
$totalUsers = $testUsers->getAllUsers();
$this->assertEquals( $expectedUsers,count($totalUsers), 'Did not delete User 91' );
}
I've just been stuck on a similar problem where I had my abstract database testcase class. Solved it by changing
public function setup()
{
$this->db = $this->getConnection();
}
to
public function setup()
{
$this->db = $this->getConnection()->getConnection();
}
Not sure if this helps with this but hopefully will help someone.
I keep on getting this error
Call to a member function prepare() on a non-object in ..on line 134.
database.php
require_once("connect.php");
class Database {
private $connect;
function one() {
$connectdb = $this->connect;
$forms = new Forms();
$forms->two();
}
}
forms.php
require_once("connect.php");
class Forms {
private $connect;
function two() {
$connectdb = $this->connect;
$construct = $connectdb->prepare("SELECT child.*, parent.name as pname, parent.information as pinformation
FROM strings child LEFT JOIN strings parent on child.pageid=parent.id WHERE child.sid=:id AND child.submittype='2'");
$executequery = $construct->execute(array(':id'=>$id));
}
}
The error happens on the line with the query. My guess is something to do with the private variable $connect. How do I solve this?
you need to instantiate first a new object of the Class Database and assign it to $connect:
$this->connect = new Database();
and then you might use it:
$connectdb = $this->connect;
Connect in your Forms class is not a database connector.
class Forms {
private $connect;
public function __construct(){
$this->connect = Database::getConnection(); // we will define this method below
}
function two() {
$connectdb = $this->connect;
$construct = $connectdb->prepare("....query....");
$executequery = $construct->execute(array(':id'=>$id));
}
}
The database connector:
class Database {
private static $connect;
public static function getConnection(){
if (self::$connect){
return self:$connect;
}
self::$connect = new mysqli(...) or what ever connection u use
}
}
I have
class Check
{
public function __construct()
{
$this->db = new Database();
}
public function query()
{
$login = Session::get("login");
$sth = $this->db->prepare('SELECT admin FROM accounts WHERE login=:login');
$sth->execute(array(':login' => $login));
$result = $sth->fetch(PDO::FETCH_NUM);
return $result[0];
}
public static function admin()
{
echo self::query();
}
}
I have Database class in another place with PDO connection.
class Database extends PDO
{
public function __construct()
{
parent::__construct('mysql:host=localhost;dbname=name','root','pass');
$this->query('SET NAMES utf8');
}
}
So after Check::admin() code I get error:
Undefined property: View::$db
Why?
You are using a static method, that wants to use a instance variable.
Your admin method calls the query method, and the query method is using the db instance variable. As your class is not instantiated, the db variable does not exists.
My suggestion would be to make the admin method non static and use your code like this:
$mycheck = new Check();
$mycheck->admin();
or, if you are on php 5.4 and want to stick with a oneliner:
(new Check())->admin();
update
note: Do not create the db class in the constructor, but inject it:
public function __construct(Database $db)
{
$this->db = $db;
}
Sorry this is not direct answer for your question but your code has some issues so take some time and examine this and ask if it's not clear for you.
<?php
class Check {
protected $_db;
public function __construct(Database $db) {
$this->_db = $db;
}
public function query(ISession $sessionData) {
//WHY IS THE SESSION STATIC?
//$login = Session::get("login");
$sth = $this->_db->Connection()->prepare('SELECT admin FROM accounts WHERE login=:login');
$sth->execute(array(':login' => $sessionData->get("login")));
$result = $sth->fetch(PDO::FETCH_NUM);
return $result[0];
}
public function admin(ISession $sessionData) {
// REALLY BAD TO ECHO HERE
echo $this->query($sessionData);
}
}
class Database {
private $_name;
private $_password;
private $_connStr;
private $_settings;
private $_pdo;
public function __construct($connstr, $name, $password, array $settings = array()) {
$this->_name = $name;
$this->_password = $password;
$this->_connStr = $connstr;
$this->_settings = $settings;
}
public function Connection() {
if ($this->_pdo == NULL) {
$this->_pdo = new PDO($this->_connStr, $this->_name, $this->_password);
}
return $this->_pdo;
}
/* other fancy methods */
public function Close() {
$this->_pdo = NULL;
}
public function __destruct() {
$this->Close();
}
}
And i don't see why you need a Check class for all this becouse if i were you i would create somethinf like this:
$currentSession = Session::GetCurrent();
$currentSession->User()->IsInRole('admin');
Note that the session is not static and if i would write a more complete solution i would avoid Session::GetCurrent() call becouse the current session would be a field in some class' instance (HttpApplication for example).
I have a database class that I made that uses PDO to connect to my queries, I'm calling it in my main classes constructor as an object.
class MyClass
{
protected $db;
public __constructor()
{
$this->db = new Database();
}
}
class Themes extends MyClass
{
public $avatar;
public $theme_name;
public $theme_by;
public $theme_by_email;
public $theme_by_website;
public $theme_description;
public $theme_thumb;
public $theme_source;
public $theme_css;
public $theme_js;
public $theme_uploaded_on;
public function __construct()
{
parent::__construct();
$this->get_theme();
$this->get_avatar();
}
public function get_theme()
{
$sql = "SELECT *
FROM `user_themes`
WHERE `user_id` = " . $this->session->get('user_id');
if($this->db->row_count($sql))
{
$result = $this->db->fetch_row_assoc($sql);
$this->theme_name = $result['theme_name'];
$this->theme_by = $result['theme_by'];
$this->theme_by_email = $result['theme_by_email'];
$this->theme_by_website = $result['theme_by_website'];
$this->theme_description = $result['theme_description'];
$this->theme_source = $result['theme_source'];
$this->theme_css = $result['theme_css'];
$this->theme_js = $result['theme_js'];
$this->theme_uploaded_on = $result['theme_uploaded_on'];
}else{
die('no results');
}
}
}
My problem is that if I include my extended classes that calls the constructor of MyClass then I get this error:
Fatal error: Call to a member function rowCount() on a non-object in db.class.php on line 98
which points to this line in my db.class.php
class Database {
private static $PDO;
private static $config;
public function __construct() {
if (!extension_loaded('pdo'))
die('The PDO extension is required.');
self::$config = config_load('database');
self::connect();
}
...
public function row_count($statement)
{
return self::$PDO->query($statement)->rowCount(); //Line 98
}
}
If I comment out parent::__construct() from my extended classes then I'm ok and get no errors.
Try my site in FireFox, Chrom, Opera, and Safari
http://www.helixagent.com
I seem to be ok in Firefox 3.6 but all those other browsers throw me the error I mentioned...
Change your row_count-method to this:
public function row_count($statement)
{
self::$PDO->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
try {
$stmt = self::$PDO->query($statement);
$result = $stmt->rowCount();
return $result;
} catch (PDOException $e) { echo $e->getMessage(); }
return false;
}
Now you'll at least get an idea what is wrong.
Your constructor should be called __construct(), not __constructor(). So your code likely fails when calling the parent constructor.
Also, when the query()-method fails, false is returned instead of an object on which you can invoke rowcount() on. You should add a check to see if the query is successful.
This extract is from here (http://php.net/manual/en/language.oop5.basic.php)
What is the difference between $this and self ?
Inside a class definition, $this refers to the current object, while self refers to the current class.
It is necessary to refer to a class element using self, and refer to an object element using $this .
Therefore in your function row_count(...) you should use $this->PDO->query(...
[EDIT]
You could try declare $this->db = null; in your child classes before you call your parent class construct.
class MyOtherClassB extends MyClass
{
public __construct()
{
$this->db = null;
parent::__construct();
}