I am trying to query a database using pdo, but I cant figure out the problem. I have created an init file for my db details and server details and config file for configuration and index file and DB file.
index.php
<?php
require_once 'core/init.php';
$user = Db::getInstance()->get('users',array('username', '=' , 'raja' ));
if($user->count())
{
echo "No user";
}
else{
echo "OK!";
}
?>
Db.php
<?php
class Db
{
private static $_instance = null;
private $_pdo,
$_query,
$_error=false,
$_results,
$_count=0;
private 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 query($sql,$params=array())
{
$this->_error = false;
if($this->_query = $this->_pdo->prepare($sql))
{
$x=1;
if (count($params))
{
foreach ($params as $param )
{
$this->_query->bindValue($x,$param);
$x++;
}
}
if ($this->_query->execute())
{
$this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
}
else
{
$this->error=true;
}
}
return $this;
}
public function action($action,$table,$where=array())
{
if(count($where) === 3)
{
$operators = array('=','<','>','>=','<=');
$field = $where[0];
$operator = $where[1];
$value = $where[2];
if(in_array($operator,$operators))
{
$sql = "{$action}FROM{$table} WHERE {$field} {$operator} ?";
if($this->query($sql,array($value))->error()){
return $this;
}
}
}
return false;
}
public function get($table,$where)
{
return $this->action('SELECT *', $table, $where);
}
public function delete($table,$where)
{
return $this->action('DELETE ', $table,$where);
}
public function error()
{
return $this->_error;
}
public function count()
{
return $this->_count;
}
}
?>
It reports a fatal error about not finding the count object:
Fatal error: Call to a member function count() on a non-object in
C:\xampp\htdocs\Student Management system\index.php on line 6
You want to declare the object -- just calling an instance from part of the object class returns just that, a non-complete object part. You're calling the function as if it's just a function rather than if it is part of the class as a whole, so then referencing any other parts of the class as a whole the logic is lost because PHP only views it as a get function alone.
To solve:
<?php
require_once 'core/init.php';
//here
$user = new Db();
$userSelect = $user->get('users',array('username', '=' , 'raja' ));
...
From this, $user is your object.
Sinlgeton
If you want to instead create the connection as a singleton, then each reference to a class method (~function) must be referenced with the singleton syntax - the reference to count() should therefore need to be rewritten into a Singleton syntax using :: instead of -> .
please read http://www.phptherightway.com/pages/Design-Patterns.html
Related
I've got a big problem:
I'm writing a new WebApp without a Framework.
I'm using xampp and sublime text.
I dont know how can i solve this problem.
An example how my DB.php written
class DB{
private static $_baglan = null;
private $_pdo,
$_query,
$hatalar = false,
$sonuc,
$_sayac = 0;
public function __construct(){
try{
$this -> _pdo = new PDO('mysql:host=' . Config::getir('mysql/host') . ';dbname=' . Config::getir('mysql/db'), Config::getir('mysql/kullanici_adi'), Config::getir('mysql/sifre') );
// echo 'baglandi';
}catch(PDOException $e){
die($e->getMessage());
}
}
public static function baglan(){
if (!isset(self::$_baglan)) {
self::$_baglan = new DB();
// echo 'baglandi';
}
return self::$_baglan;
}
public static function query($sql, $parametre=array()){
$this->_hatalar = false; // line 32
if ($this->_query = $this->_pdo->prepare($sql)) {
$x = 1;
if (count($parametre)) {
foreach ($parametre as $param) {
$this->_query->bindValue($x, $parametre);
$x++;
}
}
if ($this->_query->execute()) {
$this->sonuc=$this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_sayac=$this->_query->rowCount();
}else{
$this->_hatalar=true;
}
}
return $this;
}
public function eylem($eylem, $tablo, $where=array()){
if (count($where)===3) {
$operatorler = array('=', '<', '>', '>=', '<=');
$alan = $where[0];
$operator = $where[1];
$deger = $where[2];
if (in_array($operator, $operatorler)) {
$sql = "{$eylem} FROM {$tablo} WHERE {$alan} {$operator} ?";
if (!$this->query($sql, array($deger))->hatalar()) {
return $this;
}
}
}
return false;
}
public function getir($tablo, $where){
return $this->eylem('SELECT *', $tablo, $where);
}
public function sil($tablo, $where){
return $this->eylem('DELETE', $tablo, $where);
}
public function hatalar(){
return $this->hatalar();
}
}
In my index.php I'm loading maybe
require_once 'core/init.php';
// echo Config::getir('mysql/host');
// calismadi $kullanici = DB::baglan() -> query("SELECT kullanici_adi FROM uye WHERE kullanici_adi = ?", array('oguzhan'));
$kullanici = DB::baglan()->getir('uye', array('kullanici_adi', '=', 'oguzhan'));
if ($kullanici->hatalar()) {
echo 'Kullanıcı yok';
}else{
echo 'Var';
}
Why is the error coming?
Your problem can be solved by removing the static keyword from the query method.
You can only use $this on instantiated objects. self or static references the class itself, not any instantiated objects of the class.
class Person{
private $name;
public function __construct(string $name){
$this->name = $name;
}
public function greet(){
echo 'Hello my name is ' . $this->name;
}
}
$person = new Person('Thomas');
$person->greet(); // prints 'Hello my name is Thomas'
$this works in this example because we first instantiated the object using the new keyword. We are also not using the static keyword on the of the methods and variables.
self and static act only on the class itself and not on the instantiated object. The difference between self and static is explained here.
Here is an example of self usage, notice the use of the static keyword on the methods and variables of the class:
class StaticClass{
private static $variable = '';
public static function change(string $variable){
self::$variable = $variable;
}
public static function print(){
echo self::$variable;
}
}
StaticClass::change('Hello');
StaticClass::print(); // print 'Hello'
My limited PHP knowledge is rather old. When I used to create websites I always had a config.php file which contained some defines and a $_DB global variable. Then in every function_xyz.php file I included this config file.
Now I want to finally move on and use classes. But I can't figure out a proper way to have access to mysql in functions of my classes without inclusion of the so called config.php file on top of each file.
Imagine I have a class called User.php:
class User {
private $firstName;
private $familyName;
private $emailAddress;
public function __construct($username, $password) {
//check if user with name and pass exist in DB
// stuff....
//If user exist, populate member variables
$this->emailAddress = ...
}
public function getEmail(){
return $this->emailAddress;
}
}
I know it is not the best example or practice...but how can I have a global MySQL access in all my classes without being required to have the config file included.
What is the best practice nowadays?
Make a global Instance:
//db.php include once
class DB {
#bind connenction in it
}
#make instance
$db = new DB($config);#use for User Instances
and then:
class User {
private $db;
private $firstName;
private $familyName;
private $emailAddress;
public function __construct($db) {
$this->db=$db;
}
public function validate($username, $password,$db) {
//check if user with name and pass exist in DB
//If user exist, populate member variables
$this->emailAddress = ...
}
public function getEmail(){
return $this->emailAddress;
}
}
$user = new User($db);
Is one way.
But you telling to less about how you want to use the classes.
I would go with PHPAcademy's login/register tutorial. He have DB class that handles almost anything you need. Here is sample of his code, slightly modified by me, but all credits to Alex Garrett.
<?php
class DB {
private static $_instance = null;
private $_pdo,
$_query,
$_error = false,
$_results,
$_count = 0;
private 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 query($sql, $params = array()) {
$this->_error = false;
if($this->_query = $this->_pdo->prepare($sql)) {
$x = 1;
if(count($params)) {
foreach($params as $param) {
if (is_int($param)) {
$this->_query->bindValue($x, $param, PDO::PARAM_INT);
} else {
$this->_query->bindValue($x, $param);
}
$x++;
}
}
if($this->_query->execute()) {
$this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
}
else {
$this->_error = true;
print_r($this->_query->errorInfo());
}
}
return $this;
}
public function action($action, $table, $where = array()) {
if(count($where) === 3){
$operators = array('=', '>', '<', '>=', '<=', '!=');
$field = $where[0];
$operator = $where[1];
$value = $where[2];
if(in_array($operator, $operators)) {
$sql = "{$action} FROM {$table} WHERE {$field} {$operator} ?";
if(!$this->query($sql, array($value))->error()) {
return $this;
}
}
} else if (count($where) === 0) {
$sql = "{$action} FROM {$table}";
if(!$this->query($sql)->error()) {
return $this;
}
}
return false;
}
public function get($table, $where) {
return $this->action('SELECT *', $table, $where);
}
public function delete($table, $where) {
return $this->action('DELETE', $table, $where);
}
public function getAll($table) {
return $this->action('SELECT *', $table);
}
public function first() {
return $this->results()[0];
}
public function last() {
$i = count($this->results()) - 1;
return $this->results()[$i];
}
public function insert($table, $fields = array()) {
if(count($fields)) {
$keys = array_keys($fields);
$values = '';
$x = 1;
foreach ($fields as $field) {
$values .= '?';
if($x < count($fields)) {
$values .= ', ';
}
$x++;
}
$sql = "INSERT INTO {$table} (`" . implode('` , `', $keys) . "`) VALUES({$values})";
if (!$this->query($sql, $fields)->error()) {
return true;
}
}
return false;
}
public function update($table, $where, $parametar, $fields) {
$set = '';
$x = 1;
foreach ($fields as $name => $value) {
$set .= "{$name} = ?";
if ($x < count($fields)) {
$set .= ', ';
}
$x++;
}
if (is_int($parametar)) {
$sql = "UPDATE {$table} SET {$set} WHERE {$where} = {$parametar}";
} else {
$sql = "UPDATE {$table} SET {$set} WHERE {$where} = '{$parametar}'";
}
if (!$this->query($sql, $fields)->error()) {
return true;
}
return false;
}
public function results() {
return $this->_results;
}
public function error() {
return $this->_error;
}
public function count() {
return $this->_count;
}
}
Then you can query database like DB::getInstance()->getAll('tableName')->results();. Change DB credentials in __construct, or watch his videos (which I recomend).
I've been following a tutorial about oop php on youtube. He made a method to fetch only the first result of a query. I tried to grab all results, but I get a warning message : Trying to get property of non-object
Also when I var_dump(); my object holding the result (which I assumed), it returns null.
What am I doing wrong?
This is the full code:
DB class:
class DB {
private $_results;
public function query($sql, $params = array()) {
$this->_error = false;
if ($this->_query = $this->_pdo->prepare($sql)) {
$x = 1;
if (count($params)) {
foreach ($params as $param) {
$this->_query->bindValue($x, $param);
$x++;
}
}
if ($this->_query->execute()) {
$this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
} else {
$this->_error = true;
}
}
return $this;
}
// First result only:
public function first() {
return $this->results()[0];
}
// All results as I thought:
public function first() {
return $this->results();
}
public function results() {
return $this->_results;
}
}
Project Class:
class Project {
private $_db,
$_data;
public function __construct() {
$this->_db = DB::getInstance();
}
public function find($user = null) {
if ($user) {
$data = $this->_db->get('user_project', array('uid', '=', $user));
if ($data->count()) {
$this->_data = $data->all();
return $this->data()->id;
}
}
}
public function data() {
return $this->_data;
}
}
I tried to access it by doing this:
$project = new Project();
var_dump($project->find($user->data()->id)); // $user->data()->id is just the id of a user
Thanks for pointing me the right direction, I've figured it out.
$this->_data = $data->results();
return $this->_data;
Then I had to loop through it. Solved.
User::updatemain($set, $where);
This gives Fatal error: Using $this when not in object context
My user class extends from Dbase class and here is user class function:
public static function activate($set, $where) {
return $this->updatemain($set, $where);
here is dbase class (some part of):
private function query($sql = null, $params = null) {
if (!empty($sql)) {
$this->_last_statement = $sql;
if ($this->_db_object == null) {
$this->connect();
}
try {
$statement = $this->_db_object->prepare($sql, $this->_driver_options);
$params = Helper::makeArray($params);
$x = 1;
if (count($params)) {
foreach ($params as $param) {
$statement->bindValue($x, $param);
$x++;
}
}
if (!$statement->execute() || $statement->errorCode() != '0000') {
$error = $statement->errorInfo();
throw new PDOException("Database error {$error[0]} : {$error[2]}, driver error code is {$error[1]}");
exit;
}
//echo $sql;
return $statement;
} catch (PDOException $e) {
echo $this->formatException($e);
exit;
}
}
}
public function updatemain($set, $where) {
return $this->query($sql, $params);
}
this is part of Dbase class
You are calling static method so there is no $this in that context.
If you want to call other static method from given class then use self::method() but if you want to call non-static method you've got problem. First you have to create new object.
When you use static methods, you can't use $this inside
public static function activate($set, $where) {
return self::updatemain($set, $where);
}
Or you have to use singelton design
EDIT
Best solution - rewrite your class to one point access to DB object. And create Model classes to DB access. See my example code below:
core AppCore
<?php
class AppCore
{
public static $config = array();
public static $ormInit = false;
public static function init($config)
{
self::$config = array_merge(self::$config, $config);
}
public static function db($table)
{
// ORM - see http://idiorm.readthedocs.org/en/latest
if (!self::$ormInit) {
ORM::configure(self::$config['db']['connection']);
ORM::configure('username', self::$config['db']['username']);
ORM::configure('password', self::$config['db']['password']);
self::$ormInit = true;
}
return ORM::for_table($table);
}
}
User model
<?php
class UserModel
{
const TABLE = 'user';
public static function findById($u_id)
{
$result = AppCore::db(self::TABLE)->where('u_id', $u_id)->find_one();
return $result ? $result->as_array() : null;
}
}
AppCore init section
AppCore::init(array(
'db' => array(
'connection' => "mysql:dbname={$db};host={$host}",
'username' => $user,
'password' => $pass
),
));
i hope it help make your code better
So I have a class:
<?php
class Database extends PDO implements DatabaseCore
{
private $connections;
private $runQueryType = array('select'=>array(),
'update'=>array(),
'insert'=>array(),
'delete'=>array());
private $activeDB;
private $databaseKeys = array();
function __construct()
{
global $databases;
foreach ($databases as $key=>$value) {
$this->openConnection($value['dsn'], $value['user'], $value['password'], $key);
array_push($this->databaseKeys, $key);
$this->enumerateQueryRights($key, $value['rights']);
Query::initQuery();
}
}
function __destruct()
{
foreach ($this->databaseKeys as $key) {
unset($this->connections->$key);
}
}
function enumerateQueryRights($key, array $rights = array())
{
foreach ($rights as $r) {
array_push($this->runQueryType[$r], $key);
}
}
public function getConnection($key = 'mysqli')
{
//ERROR_HERE: PHP says $this is not an object at this point??
return $this->connections->$key;
}
function parseConnectionInfo()
{
}
function getRightByKey($key, $op = 'select')
{
return in_array($key, $this->runQueryType[$op]);
}
function closeConnection($key)
{
if (isset($this->connections->$key)) {
unset($this->connections->$key);
return TRUE;
} else {
return FALSE;
}
}
function getConnectionInfo($key)
{
}
function getConnectionKeys()
{
return array_values($this->databaseKeys);
}
function openConnection($dsn, $user, $password, $key = 'mysqli')
{
try {
$this->connections->$key = new PDO($dsn, $user, $password);
$this->connections->$key->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE);
$this->connections->$key->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
throw new Exception('Error: connection to Database');
error_log($key . '_CONNECT_ERROR' . "\t" . $e);
set_message('We\'ve encountered an error. To try again, please log into Powerschool.', 'error');
mail('Jason.ott#bps101.net', 'Error connecting to '.$key, $e);
die('We can\'t connect to our database, an administrator has been notified');
}
}
public function getError()
{
}
}//class
In the function getConnection($key = 'mysqli') I have the
return $this->connections-$key;
The error that php throws is right at that point:
Fatal error: Using $this when not in object context in /var/www/html/projects/fees/library/class/database.inc on line 40 (if I counted right, look for the comment in the code, ERROR_HERE)
I'm really not sure why $this is not considered an object at that point in the script. Any advice would be greatly appreciated and if you need more info, please ask.
How are you calling getConnection() ? Are you trying to call it as a static method?
eg are you doing something like this:
$conn = Database::getConnection();
If that's how you're calling it, then no, you can't use $this in that context, because it's static; it isn't referencing an object. You'd need the connections property to be static as well.