I am trying to change my database from MySQL to PDO. It is difficult and have to solve a lot of errors.
I don't know how to solve this error.
Fatal error: Call to undefined function UNIX_TIMESTAMP() in /... on line 63.
This is the part with the error
function create_album($album_name, $album_description) {
global $database;
$database->query("INSERT INTO albums(album_id, id, timestamp, name, description)
VALUES (':album_id', '".$_SESSION['id']."',
UNIX_TIMESTAMP(), ':album_name', ':album_description')", array('$_SESSION[id]' => ':session_id',
':timestamp' => UNIX_TIMESTAMP(), ':album_name' => $album_name, ':album_description' => $album_description));//this is line 63
mkdir('uploads/'.$album_name, 0744);
mkdir('uploads/thumbs/'.$album_name, 0744);
}
Why is there a fatal error, do I use unix_timestamp wrong here? And how can I solve this problem?
Thanks.
UNIX_TIMESTAMP() isn't a PHP function. Furthermore, you've already got it in your SQL and there's no :timestamp parameter in the SQL string. So just lose the ':timestamp' => UNIX_TIMESTAMP() and you should be good.
Also, your session_id part is messed up. First you're dumping the session id directly into the SQL string, and then you're adding it to the parameter array, but with the value and key reversed.
UNIX_TIMESTAMP is a MySQL function, not a PHP one. You don't need to bind a param to UNIX_TIMESTAMP, you can just use it in your query.
Get rid of the ':timestamp' => UNIX_TIMESTAMP(), this is your issue. First UNIX_TIMESTAMP is not a PHP function, and :timestamp is nowhere in your query.
Also, ':session_id' should be the key.
UPDATE: You need to use prepare/execute instead of query to run prepared statements.
$stmt = $database->prepare("INSERT INTO albums(id, timestamp, name, description) VALUES (':session_id', UNIX_TIMESTAMP(), ':album_name', ':album_description')");
$stmt->execute(array(
':session_id' => $_SESSION[id],
':album_name' => $album_name,
':album_description' => $album_description
));
I'm assuming album_id is AUTO_INCREMENT. If not, you should add it to the query.
UNIX_TIMESTAMP() is not a PHP function, is from MYSQL. Instead use time()
Rocket Hazmat,
the database comes from member.php;
require_once('config.inc.php');
require_once("database.class.php");
require_once("member.class.php");
require("album.func.php");
require("image.func.php");
require("thumb.func.php");
/* Start an instance of the Database Class */
$database = new database("xxx", "xxx", "xxx", "xxx");
/* Create an instance of the Member Class */
$member = new member();
the database.class.php is;
class database {
public $pdo = null;
public $statement = null;
* Database Constructor
*
* This method is used to create a new database object with a connection to a datbase
*/
public function __construct() {
/* Try the connections */
try {
/* Create a connections with the supplied values */
$this->pdo = new PDO("mysql:host=" . Config::read('hostname') . ";dbname=" . Config::read('database') . "", Config::read('username'), Config::read('password'), Config::read('drivers'));
/*
* Database Query
*
* This method is used to create a new database prepared query
*
* #param string $query The prepared statement query to the database
* #param array|string $bind All the variables to bind to the prepared statement
* #return return the executed string
*/
public function query($query, $bind = null, $fetch = 'FETCH_ASSOC') {
/* Prepare the query statement */
$this->statement = $this->pdo->prepare($query);
/* Bind each value supplied from $bind */
if($bind != null) {
foreach($bind as $select => $value) {
/* For each type of value give the appropriate param */
if(is_int($value)) {
$param = PDO::PARAM_INT;
} elseif(is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif(is_null($value)) {
$param = PDO::PARAM_NULL;
} elseif(is_string($value)) {
$param = PDO::PARAM_STR;
} else {
$param = FALSE;
}
/* Bid value */
if($param) {
$this->statement->bindValue($select, $value, $param);
}
}
}
/* Execute Query & check for any errors */
if(!$this->statement->execute()){
$result = array(
1 => 'false',
2 => '<b>[DATABASE] Error - Query:</b> There was an error in sql syntax',
);
return $result;
}
/* Return all content */
if($fetch == 'FETCH_ASSOC') {
$result = $this->statement->fetch(PDO::FETCH_ASSOC);
} elseif($fetch == 'FETCH_BOTH') {
$result = $this->statement->fetch(PDO::FETCH_BOTH);
} elseif($fetch == 'FETCH_LAZY') {
$result = $this->statement->fetch(PDO::FETCH_LAZY);
} elseif($fetch == 'FETCH_OBJ') {
$result = $this->statement->fetch(PDO::FETCH_OBJ);
} elseif($fetch == 'fetchAll') {
$result = $this->statement->fetchAll();
}
return $result;
}
}
Related
I'm working for a company that uses this Mysqli php class to do mysql calls.
The problem is, the previous programmer wasn't great about preventing unbounded queries. So there are things dispersed throughout the code like the following:
$db -> where('id',$_POST['id']);
$db -> delete('table');
This code is supposed to only delete one record where id = $_POST['id']. However, if $_POST['id'] is empty, we've got problems. It then deletes the entire table. One solution to this problem would be to find all the places in the code where delete or update functions are called and then make sure that the where variable is actually set.
if(isset($_POST['id']) && $_POST['id']!=''){
$db -> where('id',$_POST['id']);
$db -> delete('table');
}
But, that would take a lot of work because I know there are about 200 instances in the code. I'm hoping there might be a way to alter the following 2 functions to prevent them from executing unbound queries in the first place. Any help is appreciated!!
/**
* Update query. Be sure to first call the "where" method.
*
* #param string $tableName The name of the database table to work with.
* #param array $tableData Array of data to update the desired row.
*
* #return boolean
*/
public function update($tableName, $tableData)
{
if ($this->isSubQuery)
return;
$this->_query = "UPDATE " . self::$_prefix . $tableName ." SET ";
$stmt = $this->_buildQuery (null, $tableData);
$status = $stmt->execute();
$this->reset();
$this->_stmtError = $stmt->error;
$this->count = $stmt->affected_rows;
return $status;
}
/**
* Delete query. Call the "where" method first.
*
* #param string $tableName The name of the database table to work with.
* #param integer $numRows The number of rows to delete.
*
* #return boolean Indicates success. 0 or 1.
*/
public function delete($tableName, $numRows = null)
{
if ($this->isSubQuery)
return;
$this->_query = "DELETE FROM " . self::$_prefix . $tableName;
$stmt = $this->_buildQuery($numRows);
$stmt->execute();
$this->_stmtError = $stmt->error;
$this->reset();
return ($stmt->affected_rows > 0);
}
public function where($whereProp, $whereValue = 'DBNULL', $operator = '=', $cond = 'AND')
{
// forkaround for an old operation api
if (is_array($whereValue) && ($key = key($whereValue)) != "0") {
$operator = $key;
$whereValue = $whereValue[$key];
}
if (count($this->_where) == 0) {
$cond = '';
}
$this->_where[] = array($cond, $whereProp, $operator, $whereValue);
return $this;
}
You should catch the bad value when it's being passed to the where function, not later. That way it's easier to follow stack traces.
public function where($whereProp, $whereValue = 'DBNULL', $operator = '=', $cond = 'AND')
{
if (is_null($whereValue) || trim($whereValue) == '') {
throw new Exception('Cannot pass null or empty string as a condition to MysqliDb::where')
}
// ...
}
You could check through the _where protected property array inside of the delete function too, but it's not good practice to silently fail a method by doing a simple return out of the function. If you insist, though:
public function delete($tableName, $numRows = null)
{
foreach ($this->_where as $w) {
if (is_null($w[3]) || trim($w[3]) == '') {
return;
// or alternatively throw new Exception('...')
}
}
// ...
}
What about returning if this (the where clause) is empty?
https://github.com/joshcam/PHP-MySQLi-Database-Class/blob/b3754d20bcebf07d65d552b2257696539a1cb144/MysqliDb.php#L1074
if (count($this->_where) == 0) {
return;
}
please update to a latest stable version. this issue is fixed there.
where('val', unset) wont count as no condition.
I'm facing strange error with Prepared Statements with DataStax php driver 1.0.0-rc and Cassandra 2.2.3. I got an Exception on this line:
$statement = $this->session->prepare("SELECT ? FROM ? WHERE ? = ?");
I am seeing this error:
"error_code":33562624
"error_message":"Bind variables cannot be used for keyspace names"
Below a stub of class used to comunicate with Cassandra:
class ClsCassandra extends ClsDbObject
{
private $hostname="";
private $username="";
private $password="";
private $keyspace="";
private $poi_table="";
private $poi_table_key_field="";
private $poi_table_content_field="";
private $cluster = NULL;
private $session = NULL;
private $threads = 1;
function __construct()
{
...
...
//
// i set up all the properties above
//
...
...
}
public function runQuery(&$error)
{
try
{
$this->cluster = Cassandra::cluster()
->withContactPoints($this->hostname)
->withCredentials($this->username, $this->password)
->withIOThreads($this->threads)
->build();
$this->session = $this->cluster->connect($this->keyspace);
// error on next line...
$statement = $this->session->prepare("SELECT ? FROM ? WHERE ? = ?");
$results = $this->session->execute($statement, new Cassandra\ExecutionOptions(array(
'arguments' => array($this->poi_table_content_field, $this->poi_table, $this->poi_table_key_field, $keypattern)
)));
}
catch(Cassandra\Exception $ce)
{
$error->setError($ce->getCode(), $ce->getMessage(), $ce->getTraceAsString());
$this->log(LOG_LEVEL, $error->getErrorMessage(), __FILE__, __LINE__, __CLASS__);
return false;
}
return true;
}
...
...
...
}
If I use Simple Statemetn with standard select query instead it works.
Any suggestions?
You are seeing this error because you can only bind variables to the WHERE clause. The prepared statement mechanism isn't just a glorified string formatter. It has rules about what can and cannot be bound, and how you have to bind things to remove any ambiguity when sending to Cassandra.
You'll need to try something like this:
$statement = $this->session->prepare(
"SELECT key1, key2, col1, col2 FROM yourKeyspaceName.yourTableName WHERE key1 = ? AND key2 = ?");
$results = $this->session->execute($statement, new Cassandra\ExecutionOptions(array(
'arguments' => array($key1,$key2)
)));
I am still working on my own database class with pdo:
class Database {
private $databaseConnection;
public function __construct($path = "", $dbUsername = "", $dbPassword = ""){
$parts = explode('.',$path);
$documentType = array_pop($parts);
if(($path == "") || ((strcmp($documentType, "sq3") !== 0) && (strcmp($documentType, "sqlite") !== 0))) {
throw new OwnException("The Database must bee .sq3 or .sqlite and Path must be stated");
}
$this->databaseConnection = new PDO('sqlite:' . $path, $dbUsername, $dbPassword);
$this->databaseConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->databaseConnection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$this->databaseConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
self::query('CREATE TABLE IF NOT EXISTS User(
id INTEGER PRIMARY KEY AUTOINCREMENT,
username VARCHAR(40) NOT NULL UNIQUE,
numberoflogins INTEGER DEFAULT 0,
bannedstatus BOOLEAN DEFAULT FALSE,
dateofjoining TIME
)');//password field coming soon
//self::query('CREATE TABLE...');
//self::query('CREATE TABLE...');
}
private function query($sql, $params = NULL){
$pdoStatement = $this->databaseConnection->prepare($sql);
$pdoStatement->execute(array_values((array) $params));
return $pdoStatement;
}
public function getObjects($objectTable, $searchedForAttribute, $attributeValue){
$pdoStatement = $this->databaseConnection->prepare("SELECT * FROM $objectTable WHERE $searchedForAttribute = ?");
$pdoStatement->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, $objectTable);
$pdoStatement->execute(array($attributeValue));
$resultObjects = array();
while($resultObject = $pdoStatement->fetch()){
array_push($resultObjects, $resultObject);
}
if(empty($resultObjects)){
return false;
}
return $resultObjects;
}
public function getObject($objectTable, $searchedForAttribute, $attributeValue){
//...returns only the first Object from getObjects()
}
public function insertObject($object){
$objectTable = get_class($object);
$objectData = $object->getAttributes();
return $this->query("INSERT INTO $objectTable("
. join(',', array_keys($objectData)) . ")VALUES("
. str_repeat('?,', count($objectData)-1). '?)', $objectData);
}
public function updateAttribute($objectTable, $setData, $searchedAttribute, $searchedAttributeValue){
...
}
public function updateObject($object){
...
}
public function attributeRemoveObject($objectTable, $searchedForAttribute, $attributeValue){
...
}
public function __destruct(){
unset($this->databaseConnection);
}
}
as you can see there is still no data validation for the functions (and no exception handling, work in progress) such like getObjects() so the variables $objectTable, $searchedForAttribute and $attributeValue going direct into the query. This means no protection against SQL injections.
So I thought it would be quite helpful if I use a static function to validate data before inserting into query:
public static function validate($unsafeData){
//validate $unsafeData
return $safeData
}
Because I want to have the ability to search for usernames with similar names and stuff bin2hex() and hex2bin() is a bad choice and for some attributes like the username it is easy to find some starting points for the validation. For instance I would search for empty space, ', " and =...
But how should I validate the content of a forumpost which contains a lot of signs used for SQL queries to? I mean it could also be a a post about sql itself.
I saw a lot of examples for SQL Injections but all of them missing the point that the main manipulation could also be in the content box.
So how does a forum prevent SQL Injections and Errors referring to the content of a post ?
Your weakest point is here:
public function insertObject($object){
$objectTable = get_class($object);
$objectData = $object->getAttributes();
return $this->query("INSERT INTO $objectTable("
. join(',', array_keys($objectData)) . ")VALUES("
. str_repeat('?,', count($objectData)-1). '?)', $objectData);
}
The best way to avoid SQL injection is using PDO::bindParam. It doesn't matter if a string field contains valid SQL as long as you use prepared queries and bound parameters:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pquery = $pdo->prepare(
'INSERT INTO table(column1, column2) VALUES(:column1, :column2)');
// PDO::PARAM_INT, PDO::PARAM_STR, PDO::PARAM_BOOL, etc.
$pquery->bindValue(':column1', $column1, PDO::PARAM_INT); // error if $column1 isn't integer value
$pquery->bindValue(':column2', $column2, PDO::PARAM_STR); // string are sanitized
$pquery->execute();
For an arbitrary object you have to use some sort of metadata to select the correct PDO::PARAM_X value (default is PDO::PARAM_STR):
<?php
class User
{
public $username = 'foo\'; DROP TABLE User; --';
public $email = 'bar#gmail.com';
public $age = 500;
}
function getColumnType()
{
return PDO::PARAM_STR; // just for demo
}
$object = new User;
$ref = new ReflectionObject($object);
$table = $ref->getShortName(); // to avoid FQN
$properties = $ref->getProperties(ReflectionProperty::IS_PUBLIC);
$params = []; $columns = [];
foreach ($properties as $property) {
$params[] = ':'.($columns[] = $property->getName());
}
// in memory db for demo
$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('create table User(id INTEGER PRIMARY_KEY, username VARCHAR(250) NOT NULL,email VARCHAR(250) NOT NULL,age INT)');
// your answer
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pquery = $pdo->prepare("INSERT INTO $table(".implode(',', $columns).") VALUES(".implode(',', $params).")");
foreach ($properties as $property) {
$paramName = ':'.$property->getName();
$paramValue = $property->getValue($object);
$paramType = getColumnType($object, $property); // return PDO::PARAM_X
$pquery->bindValue($paramName, $paramValue, $paramType);
}
$pquery->execute();
// check
$all = $pdo->prepare('select * from User');
$all->execute();
var_dump($all->fetchAll(PDO::FETCH_CLASS, 'User'));
Output:
array(1) {
[0] =>
class User#10 (4) {
public $id =>
NULL
public $username =>
string(25) "foo'; DROP TABLE User; --"
public $email =>
string(13) "bar#gmail.com"
public $age =>
string(3) "500"
}
}
You must implement getColumnType to get the correct column data type, for example, parsing annotated comments. But at this point you better use some ORM like Eloquent or Doctrine.
I am very new to PHP Object Orientated Programming so was wondering if I could get some good advice on a database object I created.
I call the class db and include my class into every page load and initiate the database object using $db = new db. I then call the method inside this for each action I may need (building a menu from the database, getting login information etc.) with different parameters depending on what it is i want to do.
It takes its first parameter as the query with the ? symbol as replacements for values I want to bind, the second parameter is the values to bind to it in an array that is then looped through inside the prepared_statement method and the third parameter is the type ( FETCH_ARRAY returns an array of a SELECT statements rows, NUM_ROWS returns the amount of rows affected and INSERT returns the last inserted ID).
An example of how I would call this function is below:
$db->prepared_execute( "SELECT * FROM whatever WHERE ? = ? ", array( 'password', 'letmein' ), NUM_ROWS );
The second and third parameters are optional for if there are no parameters to be bound or no return is needed.
As I am new to OOP I am finding it hard to get my head around exactly when to use correctly and what are public, private, static functions/variables and design patterns (Singleton etc.).
I've read many tutorials to get as far as I hav but I feel now I need to take it here to get further answers or advice on where to go next with OOP and with this class I've built.
It works as it is which for me is a good starting place except for any error handling which I will add in next but I want to make sure I am not making any obvious design errors here.
The code for the class is below:
class db {
var $pdo;
public function __construct() {
$this->pdo = new PDO('mysql:dbname=' . DB_NAME . ';host=' . DB_HOST . ';charset=utf8', DB_USER, DB_PASS);
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public function prepared_execute( $query, $bind_values = null, $type = null ) {
$preparedStatement = $this->pdo->prepare( $query );
if( $bind_values ) {
$i = 1;
foreach( $bind_values as $bind_value ) {
$preparedStatement->bindValue($i, $bind_value);
$i++;
} }
$preparedStatement->execute();
if( $type == FETCH_ARRAY ) { return $preparedStatement->fetchAll(); }
elseif( $type == NUM_ROWS ) { return $preparedStatement->rowCount(); }
elseif( $type == INSERT ) { return $this->pdo->lastInsertId(); }
else{ return true; }
}
Your code is a bit outdated. You should use one of the visibility keywords instead of var to declare your properties. In this case you probably want to use protected so that it cant be modified from outside the class but so that any future sub classes can modify it internally. Youll also probably want to add a getter in-case you need to work with PDO directly (which you will - see my final statements below my class example).
Its bad to hard code you PDO connection information in the class. You should pass these in as parameters same as you would if using PDO directly. I would also add the ability to pass in a pre-configured PDO instance as well.
While not required, its a good idea to conform to PSR-0 through PSR-2; Sepcifically in your case im speaking about Class and method naming which should both be camelCase and the first char of the class should be capital. Related to this your code formatting is also ugly particularly your block statements... If thats jsut an issue with copy and paste then ignore that comment.
So overall i would refactor your code to look something like this:
class Db {
protected $pdo;
public function __construct($dsn, $user, $pass, $options = array()) {
if($dsn instanceof PDO) {
// support passing in a PDO instance directly
$this->pdo = $dsn;
} else {
if(is_array($dsn)) {
// array format
if(!empty($options)) {
$dsn['options'] = $options;
}
$dsn = $this->buildDsn($options);
} else {
// string DSN but we need to append connection string options
if(!empty($options)) {
$dsn = $this->buildDsn(array('dsn' => $dsn, 'options' => $options));
}
}
// otherwise just use the string dsn
// ans create PDO
$this->pdo = new PDO($dsn, $user, $pass);
}
// set PDO attributes
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public function getConnection()
{
return $this->pdo;
}
protected function buildDsn($options) {
if($isDbParts = isset($options['dbname'], $options['hostname']) || !($isDsn = isset($option['dsn']))) {
throw new Exception('A dsn OR dbname and hostname are required');
}
if($isDsn === true) {
$dsn = $options['dsn'];
} else if {
$format = '%s:dbname=%s;host=%s';
$driver = isset($options['dbtype']) ? $options['dbtype'] : 'mysql';
$dsn = sprintf($format, $options['dbtype'], $options['dbname'], $options['host']);
}
if(isset($options['options'])) {
$opts = array();
foreach($options['options'] as $name => $value) {
$opts[] = $name . '=' . $value;
}
if(!empty($opts)) {
$dsn .= ';' . implode(';', $opts);
}
}
return $dsn;
}
public function preparedExecute( $query, $bind_values = null, $type = null ) {
$preparedStatement = $this->pdo->prepare( $query );
if( $bind_values ) {
$i = 1;
foreach( $bind_values as $bind_value ) {
$preparedStatement->bindValue($i, $bind_value);
$i++;
}
}
$preparedStatement->execute();
if( $type == FETCH_ARRAY ) {
return $preparedStatement->fetchAll();
}
elseif( $type == NUM_ROWS ) {
return $preparedStatement->rowCount();
}
elseif( $type == INSERT ) {
return $this->pdo->lastInsertId();
}
else {
return true;
}
}
}
Lastly, unless this is just for educational purposes I wouldnt do this. There are a ton of different queries that have varying part assemblies which arent considered here so at some point this is not going to support what you need it to do. Instead i would use Doctrine DBAL, Zend_Db or something similar that is going to support greater query complexity through its API. In short, dont reinvent the wheel.
I have developed something similar and it can helps you.
public function select($sql, $array = array(), $fetchMode = PDO::FETCH_ASSOC){
$stmt = $this->prepare($sql);
foreach ($array as $key => $value){
$stmt->bindValue("$key", $value);
}
$stmt->execute();
return $stmt->fetchAll();
}
public function insert($table, $data){
ksort($data);
$fieldNames = implode('`,`', array_keys($data));
$fieldValues = ':' .implode(', :', array_keys($data));
$sql = "INSERT INTO $table (`$fieldNames`) VALUES ($fieldValues)";
$stmt = $this->prepare($sql);
foreach ($data as $key => $value){
$stmt->bindValue(":$key", $value);
}
$stmt->execute();
}
I have been turning and twisting this to the best of my non-existing PDO knowledge, but still without any luck.
the code:
function write($id, $data) {
global $dbcon;
$id = mysql_real_escape_string($id);
$data = mysql_real_escape_string($data);
$sql = $dbcon->exec("INSERT INTO `sessions`
(`session_id`, `session_data`,
`session_expire`, `session_agent`,
`session_ip`, `session_referrer`)
VALUES
(\"".$id."\", \"".$data."\",
\"".time()."\",\"".($this->session_encryption($_SERVER['HTTP_USER_AGENT']))."\",
\"".($this->session_encryption($_SERVER['REMOTE_ADDR']))."\", \"".($this->session_encryption((isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_^~#&|=+;!,(){}[].?%*#'))))."\")
ON DUPLICATE KEY UPDATE
`session_data` = \"".$data."\",
`session_expire` = \"".time()."\"");
return true;
}
Give me the following error:
Fatal error: Call to a member function exec() on a non-object
on the
$sql = $dbcon->exec(
line.
I have been trying to solve this all evening, but without any luck.
This is my PDO connection script:
require_once(INC_PATH.'/config.php');
$dsn = "$db_type:host=$db_host;port=$db_port;dbname=$db_name;charset=$db_charset";
try{
$dbcon = new PDO($dsn, $db_user, $db_pass);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//$dbcon = null; //Close database connection.
}
catch(PDOException $e){
echo $e->getMessage();
}
Hope one of you kind souls out there can help me, I would deeply appreciate it!
Thanks.
UPDATE:
I have a global.php file which looks like this:
//Load database
require_once(INC_PATH.'/database.php');
//Load session handler
require_once(INC_PATH.'/class_sessions.php');
$Sessions = new SessionManager();
session_start();
The database.php is included before the sessions class, and when I view the website, it does not give any errors on this part of the sessions class (which is before the write function:
function read($id) {
global $dbcon;
$data = '';
$id = mysql_real_escape_string($id);
$sql = $dbcon->prepare("SELECT
`session_data`
FROM
`sessions`
WHERE
`session_id` = '".$id."'");
$sql->execute();
$a = $sql->columnCount();
if($a > 0) {
$row = $sql->fetchObject();
$data = $row['session_data'];
}
return $data;
}
Are you sure your connection script is getting executed? Try checking if $dbcon is set. Also, you may be missing global $dbcon within the connection script.
By the way, since you're already using PDO, might I recommend you use placeholders in your query:
$sql = "INSERT INTO `sessions`
(`session_id`, `session_data`, `session_expire`,
`session_agent`, `session_ip`, `session_referrer`)
VALUES
(:session_id, :session_data, :session_expire,
:session_agent, :session_ip, :session_referrer)
ON DUPLICATE KEY UPDATE
`session_data` = :session_data,
`session_expire` = :session_expire";
$params = array(
':session_id' => $id,
':session_data' => $data,
':session_expire' => time(),
':session_agent' => $this->session_encryption($_SERVER['HTTP_USER_AGENT']),
':session_ip', => $this->session_encryption($_SERVER['REMOTE_ADDR']),
':session_referrer' => $this->session_encryption((isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_^~#&|=+;!,(){}[].?%*#';
);
$stmt = $dbcon->prepare($sql);
if ($stmt->execute($params) === FALSE) {
// handle error
}
First check that the global object is not being overwritten by another function. I strongly suggest you use Dependency injection instead of globals.
$Sessions = new SessionManager($dbcon);
And inside the Session Management class you can do something like
class SessionManager
{
protected $db;
public function __construct($db) { $this->db = $db; }
public function read($id)
{
$stmt = $this->db->prepare("SELECT session_data
FROM sessions
WHERE session_id = ?");
$stmt->execute(array($id));
return $stmt->fetchColumn();
}
}
And secondly, since you are using PDO, you dont need to call mysql_real_escape_string(), use prepared statements and placeholders :)