PDO Object and Array - php

I have followed PHP Academy's OOP Tutorial over here
The DB class has been made in a way to fetch database results as an Object
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;
}
This is important cause the user login is done like this
public function login($username = null, $password = null){
$user = $this->find($username);
if($user){
if($this->data()->password === Hash::make($password, $this->data()->salt)){
Session::put($this->_sessionName, $this->data()->id);
return true;
}
}
return false;
}
Now when i want to implement foreach to get results row-wise, they are asking for an Array
$result = $product->getData($_GET['id']);
if(!empty($result)){
foreach ($result as $row) {echo $row['id'];}}
getData Function
public function getData($_id){
return $this->_db->get('products', array('id', '=', $_id))->results();
}
results function is in DB class
public function results(){
return $this->_results;
}
When I change Fetch All to get Both OBJ and ARRAY, User cant log in.
What should i do? Which function to change?
Sorry for Bad English
Thanks in Advance

Related

Why isn't my foreach loop displaying my mysql data?

I am trying to extend the function of this tutorial on youtube, and I have run into some issues. Here is the particular chunk of code I am currently struggling with:
public function listProjects() {
$projects = DB::getInstance()->get('projects', array('projectStatus', '=', 'active'));
if($projects->count()) {
echo 'This query senses rows, but returns data it does not';
foreach($projects as $project) {
echo $project->projectName;
}
}
}
This is a method of my "Project" class, and it uses methods from the DB class, with relevant code here:
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 $this;
}
public function get($table, $where) {
return $this->action('SELECT *', $table, $where);
}
So in my index.php, I write this code:
$projectList = new Project;
$projectList->listProjects();
To try and retrieve all of my "projects" stored in the database. I put the "This query senses rows, but returns data it does not" echo in order to determine if rows were being counted, which they are, because that statement is echoed, but my foreach statement is not working correctly. The field in the projects table that I am trying to access is projectName. I would eventually like to display all relevant project info, but I'm sure I could figure that out once I get it to display anything from the database.
This:
foreach($projects as $project) {
echo $project->projectName;
}
should be:
foreach($projects as $project) {
echo $projects->projectName;
}

Returning lastInsertId() from database class

I am using a database class picked up from a tutorial on codecourse.com (I am just starting the migration from procedural to pdo) and I am slowly extending it to fit my needs. However, the one thing I cannot manage is to return the lastInsertId() to be used globally.
Using the register example from that tutorial
$user = new User();
$salt = Hash::salt(32);
try {
$user->create(array(
'username' => Input::get('username'),
'password' => Hash::make(Input::get('password'), $salt),
'salt' => $salt,
'firstname' => Input::get('first_name'),
'lastname' => Input::get('last_name'),
'joined' => date('Y-m-d H:i:s'),
'group' => 1
));
} catch(Exception $e) {
die($e->getMessage());
}
It is at this point that I want to get the lastInsertId() - the one of the just registered user. I am not sure whether it comes out of the Database class via the insert function
require_once 'core/init.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 insert ($table, $fields = array()) {
$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;
}
echo $sql;
}
return false;
}
public function update ($table, $id, $fields = array()) {
$set = '';
$x = 1;
foreach ($fields as $name => $value) {
$set .= "{$name} = ?";
if ($x < count($fields)) {
$set .= ', ';
}
$x++;
}
$sql = "UPDATE {$table} SET {$set} WHERE id = {$id}";
if (!$this->query($sql,$fields)->error()) {
return true;
}
}
return false;
}
public function first () {
return $this->results()[0];
}
public function results () {
return $this->_results;
}
public function count () {
return $this->_count;
}
public function error () {
return $this->_error;
}
}
Or the User class via the create function
class User {
private $_db,
$_data,
$_sessionName,
$_cookieName,
$_isLoggedIn;
public function __construct($user = null) {
$this->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
$this->_cookieName = Config::get('remember/cookie_name');
if (!$user) {
if (Session::exists($this->_sessionName)) {
$user = Session::get($this->_sessionName);
if ($this->find($user)) {
$this->_isLoggedIn = true;
} else {
//Logged out
}
}
} else {
$this->find($user);
}
}
public function update($fields=array(), $id = null) {
if (!$id && $this->isLoggedIn ()) {
$id = $this->data()->id;
}
if (!$this->_db->update('users', $id, $fields)) {
throw new Exception('There was a problem updating the account!');
}
}
public function create($fields) {
if (!$this->_db->insert('users', $fields)) {
throw new Exception('There was a problem creating an account!');
}
}
public function find($user=null) {
if ($user) {
$field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if ($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username=null, $password=null, $remember = false) {
if(!$username && !$password && $this->exists()) {
Session::put($this->_sessionName, $this->data()->id );
} else {
$user = $this->find($username);
if ($this->data()->password === Hash::make($password, $this->data()->salt)) {
Session::put($this->_sessionName, $this->data()->id);
if ($remember) {
$hash = Hash::unique();
$hashCheck = $this->_db->get('users_session', array('user_id', '=', $this->data()->id));
if (!$hashCheck->count()) {
$this->_db->insert('users_session', array(
'user_id' => $this->data()->id,
'hash' => $hash
));
} else {
$hash = $hashCheck->first()->hash;
}
Cookie::put($this->_cookieName, $hash, Config::get('remember/cookie_expiry'));
}
return true;
}
return false;
}
}
public function hasPermission ($key) {
$group = $this->_db->get('groups', array('id', '=', $this->data()->group));
if($group->count()) {
$permissions = json_decode($group->first()->permissions, true);
if ($permissions[$key] == true) {
return true;
}
}
return false;
}
public function exists () {
return (!empty($this->_data)) ? true : false;
}
public function logout () {
Session::delete($this->_sessionName);
}
public function data () {
return $this->_data;
}
public function isLoggedIn () {
return $this->_isLoggedIn;
}
}
I have tried in both but whenever I try to echo the lastInsertId() back out, nothing is returned. Any advice would be greatly welcomed. If the problem might be outside of these areas, I have uploaded the entire script to https://github.com/MargateSteve/login.
Thanks in advance
Steve
The insert() method of a database class should return insert id. Here is a relevant part for it:
public function insert ($table, $fields = array()) {
$this->query($sql,$fields);
return $this->_db->lastInsertId;
}
while create() method of a User class should create a user instance.
public function create($fields) {
$id = $this->_db->insert('users', $fields);
$this->find($id);
}
Note that insert() method is vulnerable to SQL injection.
And now you can use your newly created user all right
$user = new User();
$user->create(array(
'username' => Input::get('username'),
'password' => Hash::make(Input::get('password')),
'firstname' => Input::get('first_name'),
'lastname' => Input::get('last_name'),
'joined' => date('Y-m-d H:i:s'),
'group' => 1
));
echo $user->data['id'];
I hope you are looking not for the code to copy and paste but for the understanding. And I hope you understand the logic above.
Add a public variable to your DB class that will hold the last inserted record ID:
class DB {
public $lastInsertId = null;
In the same DB class modify the query method, where the actual insert happens so that you can grab the ID from PDO:
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->lastInsertId = $this->_pdo->lastInsertId();
$this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
} else {
$this->_error = true;
}
}
return $this;
}
On the code above this is the important line:
$this->lastInsertId = $this->_pdo->lastInsertId();
You are assigning the value of PDO::lastInsertId() to your lastInsertId instance variable, that way you can access it from wherever you instantiate a DB object.
Now, modify the user class to hold a variable called id as well, do not name it lastInsertId because its confusing; in this context you have one single instance of a user which represents a single user and hence id simply refers to this instance user id:
class User {
public $id = null;
Modify in this same User class the create method as well to grab the lastInsertId value from your db object instance:
public function create($fields) {
if (!$this->_db->insert('users', $fields)) {
throw new Exception('There was a problem creating an account!');
}
$this->id = $this->_db->lastInsertId;
}
Then you can access the user ID in your register.php file simply accesing the user instance variable e.g. $user->id :
try {
$user->create(array(
'username' => Input::get('username'),
'password' => Hash::make(Input::get('password'), $salt),
'salt' => $salt,
'firstname' => Input::get('first_name'),
'lastname' => Input::get('last_name'),
'joined' => date('Y-m-d H:i:s'),
'group' => 1
));
Session::flash('home', "You have registered with user ID $user->id");
Redirect::to('index.php');
} catch(Exception $e) {
die($e->getMessage());
}

Fatal Error call to member function count() is non object

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

Fetch all results with OOP Php

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.

OOP Object of class __PHP_Incomplete_Class

hello i have this code for login and register in PHP OOP
<?php
class DB {
public static $instance = null;
private $_pdo = null,
$_query = null,
$_error = false,
$_results = null,
$_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'), array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
//$this->query('SET NAMES utf8');
} catch(PDOExeption $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 get($table, $where) {
return $this->action('SELECT *', $table, $where);
}
public function delete($table, $where) {
return $this->action('DELETE', $table, $where);
}
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 insert($table, $fields = array()) {
$keys = array_keys($fields);
$values = null;
$x = 1;
foreach($fields as $value) {
$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, $id, $fields = array()) {
$set = null;
$x = 1;
foreach($fields as $name => $value) {
$set .= "{$name} = ?";
if($x < count($fields)) {
$set .= ', ';
}
$x++;
}
$sql = "UPDATE {$table} SET {$set} WHERE id = {$id}";
if(!$this->query($sql, $fields)->error()) {
return true;
}
return false;
}
public function results() {
// Return result object
return $this->_results;
}
public function first() {
return $this->_results[0];
}
public function count() {
// Return count
return $this->_count;
}
public function error() {
return $this->_error;
}
public function lastInsertId(){
return $this->_pdo->lastInsertId();
}
public function __sleep(){
return array();
}
}
and i save the user login data in session, everything works fine in localhost, but in my web server i have a problem in the line $this->_query->bindValue($x, $param);
Catchable fatal error: Object of class __PHP_Incomplete_Class could not be converted to string in
i know that is something wrong with my session but i cant find whats the problem, and this is my session class
<?php
class Session {
public static function exists($name) {
return (isset($_SESSION[$name])) ? true : false;
}
public static function get($name) {
return $_SESSION[$name];
}
public static function put($name, $value) {
return $_SESSION[$name] = $value;
}
public static function delete($name) {
if(self::exists($name)) {
unset($_SESSION[$name]);
}
}
public static function flash($name, $string = null) {
if(self::exists($name)) {
$session = self::get($name);
self::delete($name);
return $session;
} else if ($string) {
self::put($name, $string);
}
}
}
please tell me if you can what i can to do with that error thank you very much.
and this is the code where i store my session
public function login($username = null, $password = null, $remember = false) {
if(!$username && !$password && $this->exists()) {
Session::put($this->_sessionName, $this->data()->id);
} else {
$user = $this->find($username);
if($user) {
if($this->data()->password === Hash::make($password, $this->data()->salt)) {
Session::put($this->_sessionName, $this->data()->id);
if($remember) {
$hash = Hash::unique();
$hashCheck = $this->_db->get(Config::get('mysql/tbl_user_sessions'), array('user_id', '=', $this->data()->id));
if(!$hashCheck->count()) {
$this->_db->insert(Config::get('mysql/tbl_user_sessions'), array(
'user_id' => $this->data()->id,
'hash' => $hash
));
} else {
$hash = $hashCheck->first()->hash;
}
Cookie::put($this->_cookieName, $hash, Config::get('remember/cookie_expiry'));
}
return true;
}
}
}
return false;
}
i just do var_dump of my session['user']
array(1) {
["user"]=> &object(__PHP_Incomplete_Class)#1 (6) {
["__PHP_Incomplete_Class_Name"]=> string(4) "User"
["_db":"User":private]=> object(__PHP_Incomplete_Class)#2 (1) {
["__PHP_Incomplete_Class_Name"]=> string(2) "DB"
}
["_sessionName":"User":private]=> string(4) "user"
["_cookieName":"User":private]=> string(4) "hash"
["_data":"User":private]=> object(stdClass)#3 (7) {
["id"]=> string(3) "144"
["username"]=> string(5) "admin"
["password"]=> string(64) "0611affa6664e471b939cd3197b49e0c3b47d146fc12a472c4275dbd85a7cd67"
["salt"]=> string(32) "458a0dbfbd9bdca381e50b8d753329ea"
["name"]=> string(12) "Artur Papyan"
["joined"]=> string(19) "2013-11-29 07:41:54"
["group"]=> string(1) "1"
}
["_isLoggedIn":"User":private]=> bool(true)
}
}
It looks as though you are attempting to output the result to a string, which it cannot do as the class returns an object.
Also, Referring to DB.php line 38 is a red herring, as it is displaying the error message to the called function.
$this->_query->bindValue($x, $param);
Instead look to where your code is calling the class, and how you are attempting to bind your variables within your code it's self, instead of the actual call to DB.php file.

Categories