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();
}
Related
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.
Hello Im getting this error
Call to a member function query() on null
Fatal error: Call to a member function query() on null
Call to member function query() on Null
But neither seems to solve my problem
I have db class
class DB
{
private $link;
public function __construct()
{
$this->link = new mysqli(HOSTNAME, USERNAME, PASSWORD, DBNAME);
if ($this->link->connect_error)
{
exit('Some of the database login credentials seem to be wrong.' . $this->link->connect_error);
}
}
}
Then I attempt to query the database with this class
class UserModel extends DB
{
private $db;
public function __construct()
{
$this->getUser();
}
public function getUser()
{
$query = $this->db->query("SELECT * FROM users");
var_dump($query);
}
}
These files are in site/app/model/file.php
I instantiate db in my site/index.php
You have a couple of errors here:
As you define own construct in UserModel class, parent __construct, where $link var is defined, is not run. You can add parent::__construct(); to child constructor.
In your parent class you have $link variable, not $db. And $link is private, so it's not avaialble in child classes.
Fixed code is
class DB
{
protected $link; // protected here
public function __construct()
{
$this->link = new mysqli(HOSTNAME, USERNAME, PASSWORD, DBNAME);
if ($this->link->connect_error)
{
exit('Some of the database login credentials seem to be wrong.' . $this->link->connect_error);
}
}
}
class UserModel extends DB
{
public function __construct()
{
// call parent construct and define $this->link
parent::__construct();
$this->getUser();
}
public function getUser()
{
// use $this->link
$query = $this->link->query("SELECT * FROM users");
var_dump($query);
}
}
Transform
private $link
To
protected $link
This allows the child class to have access to such variable.
And of course, make use of the $this->link instead of the $this->db
I am getting the following error:
Fatal error: Using $this when not in object context in
C:\xampp\htdocs\practice\classes\pagination.php on line 20
My workflow is the following:
From pagination2.php page i initialized all the class instances:
require_once '../core/init.php';
$pagination=new Pagination();
$user=new User();
$data=$user->data();
$pagenum=$pagination::getAllContent('userpost',$data->user_id);
echo $pagenum;
pagination.php page contains pagination class
class Pagination{
private $_db;
public function __construct(){
$this->_db=DB::getInstance();
print_r($this->_db);
}
public static function getUserContentOffset($table,$offset,$id){
$val=array();
$val[]=$id;
$pointerDB=$this->_db->fetchPostByOffset($table,$offset,$val);
return $pointerDB->results();
}
public static function getAllContent($table,$id){
$val=array();
$val[]=$id;
print_r($val);
$pointerDB=$this->_db->fetchAllPost($table,$val); // error is here
return $pointerDB->countit();
}
}
$this->_db should bear the instance of DB class.Then why i am getting the error when i call a method of DB class using $this->_db
DB.php
class DB{
private static $_instance=null;
private $_pdo,$_query,$_error=false,$_results,$_count=0;
public function __construct(){
try{
$this->_pdo=new PDO('mysql:host='.Config::get('mysql/host').';dbname='.Config::get('mysql/db'),Config::get('mysql/username'),Config::get('mysql/password'));
}catch(PDOException $e){
die($e->getMessage());
}
}
public static function getInstance(){
if(!isset(self::$_instance)){
self::$_instance=new DB();
}
return self::$_instance;
}
public function fetchAllPost($table,$val=array()){
$sql="SELECT title FROM ".$table." WHERE users_user_id = ?";
return $this->query($sql,$val);
}
}
$this is not available in static methods. Static Methods don't have any Object associated with them, hence there is no $this reference available inside a static method. So you can declare a static properties and use it in your static function. Now your calling DB instance should be on static property so that you can access it in your static functions.
class Pagination{
private static $_db;
public function __construct(){
self::$_db = DB::getInstance();
}
public static function getUserContentOffset($table,$offset,$id){
$val=array();
$val[]=$id;
$pointerDB=self::$_db->fetchPostByOffset($table,$offset,$val);
return $pointerDB->results();
}
public static function getAllContent($table,$id){
$val=array();
$val[]=$id;
$pointerDB = self::$_db->fetchAllPost($table,$val); // error is here
return $pointerDB->countit();
}
}
Now you can try it this way
$pagintation = new Pagination();
$pagenum = $pagination->getAllContent('userpost',$data->user_id);
Hope it helps.
You are using static functions which don't have an instance to reference to.
Trying using self:: instead.
self::$_db
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 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).