adding functionality to session_start() - php

Hi I want to add some functionality to the session_start function in php. I know I can write a custom function to replace session_start() but that goes too far. I just want to have some additional code trigger, not remove the old code.
Edit: Specifically I want the session ID to be written into a sql table.

You could simply create a function wrapper around session_start() that you use.
function my_session_start() {
session_start();
$session_id = session_id();
// write $session_id to database by whatever method you choose
}
// usage
my_session_start();
Or if you want to extend on sessionHandler you could do something like this:
class mySessionHandler extends sessionHandler {
// perhaps a property to store db connection or DB object as needed for writing session id to database
protected $db = null;
public function __construct($db = null) {
if(is_null($db)) {
throw new Exception('Give me a database');
}
// maybe some other validation (could also use type hinting in parameter
$this->db = $db;
}
public function open($save_path, $session_id) {
parent::open($save_path, $session_id);
// not shown - use $this->db to insert $session_id to database
}
}
// usage
$session_handler = new mySessionHandler($db);
session_set_save_handler($session_handler, true);
session_start();
Here you are only overriding the open() method to add the session id to the database.

Related

Call function within class without variable being used in PHP

So I am basically re-doing some code on an existing system, mainly the database functions and I am putting them in a class rather than a function (currently the mysqli_connect DSN information is set in global variables and is being used every single time a query is being done which is why I am trying to clean this up but I am not trying to re-do this entire system all right now).
Current system has many PHP files that will include the main dbconnect.php file with a function of something like function db_query($query,$DSN){} and we have in almost every single other file the actual SQL query being written out and then passed off as db_query($query); and that is it.
I have moved over to something along the lines of the below code:
dbconnect.php
class Db {
protected static $connection;
function __construct() {
if (! isset($GLOBALS['DEBUG'])) { $GLOBALS['DEBUG'] = 0; }
}
public function connect() {
if(!isset(self::$connection)) {
self::$connection = new mysqli($GLOBALS['DSN']);
}
if(self::$connection === false) {
return false;
}
unset($GLOBALS['DSN']); //unset so that login info is not roaming around anymore now that the connection has been established
return self::$connection;
}
public function db_query($query) {
$connection = $this->connect();
$result = $connection->query($query);
return $result;
}
}
otherphpfile.php
include_once 'dbconnect.php';
(new Db()); //I have also tried new Db();
$query = "SELECT * FROM table;";
db_query($query); //I have to try to do it like this since 99.9% of the system is already using this method and I don't want to have to go through all the code and update it with something like:
$db = new Db();
$db->db_query($query);
I understand that $db = new Db(); $db->db_query($query); is correct but I am trying to do it like this new Db(); without a variable assigned to it because all of the other functions for dbconnect.php are written without a variable in front of the function call such as db_query($query); like they are right now without me having to go and update all of them to $db->db_query($query);.
I hope this makes sense and any suggestions would be great without compromising the benefit of using classes to begin with (AKA setting public static functions is just not worth it)
Thank you
Part of refactoring is to update code. Honestly, any IDE would make replacing the usage of db_query() a breeze. You can replace the db_query( with (new Db())->db_query(. Since you are already storing the connection statically, I suggest making the class methods also static. Having something like Db::query(...) would be less redundant and more readable.

How to save global variable data in one function and echo them in another function

here is my problem. I am trying to create one big file (full of functions) which will call the object functions. I want to create some SUPERGLOBAL variable which will contains everything about that called class (even between functions) class like "user". What data? Just something like user's ID, Name, Email, Level from database so I don't need to using SQL SELECT from USERS in almost every function in this file.
This is how my core.php file looks like (it's cut just to explain what am I trying to do)
//File -- core.php
require_once "pdo.php"; //Includes the $db -- pdo connection to database
require_once "user.php"; //Including the object
$GLOBAL["user"] = new USER($db);
function login($email, $pswd){
$GLOBAL["user"]->login($email, $pswd); //LOGIN and also in this class function are written the data like $GLOBAL["user"]->ID, etc
//do something more
}
function ShowLoggedUser(){
echo $GLOBAL["user"]->ID; //But now here it's not working -> it's empty, nothing there
echo $GLOBAL["user"]->Email;
//etc
}
And the thing is, that's I in the object USER I am setting the public data like
//file -- user.php
class USER
{
//Public data
public $Name;
public $Level;
public $ID;
public $Email;
private $DB;
function __construct($DB_con)
{
$this->DB = $DB_con;
}
public function login ($email, $password)
{
//Some SQL and verifying user with DB
//if everything is ok do this:
foreach($result as $data){ //Results from SQL -- details about user
$this->ID = $data["ID"];
$this->Name = $data["Name"];
$this->Email = $data["Email"];
}
return "some message";
}
The function Login is the key of this file, if the login won't be used, then the user is kicked out of this file (it's file just for logged users), so there is 100% guaranty that's the data in class are written and they really shows up when I echo them in the function "login". But anywhere else it's just totally empty...
Thank you for any help / tips!

Undefined variable in OOP PHP

I'm trying to make the transition to OOP PHP to help clean up the cluster of code I'm currently working with.
I'm using PHPass to hash passwords in my database but with this OOP approach, I can't get my head around how to call it in my class' login function.
As far as I can see, in all the places I've tried calling it, it's always declared before my class is initialised but it's still telling my it's undefined or a non-object.
db_config.php
...
require_once("PasswordHash.php"); // Location no.1 to try it
$password_hash = new PasswordHash(8, FALSE);
include_once("DB.php");
$db = new DB($db_connection);
...
init.php
//require_once("PasswordHash.php"); // Location no.2 to try it
//$password_hash = new PasswordHash(8, FALSE);
require_once("db_config.php")
..Other init stuff..
DB.php
class DB {
...
public function login() {
// global $password_hash; -> if uncommented I get an error saying it's a non-object
// Error here
$password_accepted = $password_hash->CheckPassword($p, $hp);
}
...
}
login.php
require_once("init.php");
$db->login();
I still haven't got my head fully around how class scope works in PHP so I have a feeling I'm missing something.
You need to pass the hash into the class as the class has only an internal scope.
$formData = array();
$formData['email'] = 'user#email.com';
require_once("PasswordHash.php"); // Location no.1 to try it
$formData['password_hash'] = new PasswordHash(8, FALSE);
include_once("DB.php");
$db = new DB($db_connection, $formData);
and in DB.php:
class DB {
// Stores the user input form data for use within the class?
private $formData;
// Runs when the class is constructed
public function __construct($formData)
{
// When the class is constructed then store this for local/interal use
$this->$formData = $formData;
}
public function login() {
// The boolean result of of checking of an internal method
// that compares user credentials against the database information?
$password_accepted = $this->CheckPassword(
$this->formData['email'],
$this->formData['password_hash']
);
}
private function CheckPassword($email, $pass) {
// Do query and bind in $user and $pass
// Return true if everthing passes
}
}
Edit: I exaggerated the use of passing the variables into classes and methods to help you to wrap your head around this aspect of things but you could also do something like:
...
$password_accepted = $this->CheckPassword();
}
private function CheckPassword() {
// Do query and bind in $this->formData['email'] and $this->formData['password_hash']
// Return true if everthing passes
}
}
Just inject the hash instance the same way you already do with the db_connection.
class DB {
...
public function __construct($db_connection, $password_hash) {
// you probably already have something like
$this->connection = $db_connection;
// now do the same for the hash object
$this->pwhash = $password_hash;
}
public function login() {
...
$password_accepted = $this->pwhash->CheckPassword($p, $hp);
...
}
}
(slightly offtopic: Database and Hash ...along with Cipher, EMail and Buffer these are my least liked classes for beginners to fiddle with)

PHP - Call To Undefined Method

I have a PHP class with a few functions defined, this class is responsible for database access:
class database {
function open($params) {
// code here to open the db
}
function close() {
// code here to close the db
}
function count_users() {
// code here counts the number of user records
// Return -1 for testing
return -1;
}
function insert_user($user) {
// code here inserts a user record
}
function select_user($user_id) {
// code here selects a user record
}
}
I have accessor classes defined as follows:
require_once("database.php");
class user {
public $user_id;
public $email_address;
// etc, etc
}
class db_user {
static function select_user($user_id) {
$db = new database();
$db->open();
$user = NULL;
$result = $db->select_user($user_id);
// Test the result and decode user record into $user, etc
$db->close();
return $user;
}
static function count_users() {
$db = new database();
$db->open();
$count = $db->count_users();
$db->close();
return $count;
}
}
My issue occurs when I attempt to count the number of users through db_user::count_users(); which always fails with a Fatal Error: call to undefined method database::count_users
If I dump the database class methods using get_class_methods, I can see that the count_users function isn't present in the list but I have no idea why.
I'm very much a PHP n00b so there maybe something really obvious I'm not doing. My db_user and user classes have many other functions which pull data back through the database class and all of these succeed - just this one function.
Please help!
UPDATE
Ok, so, having removed a couple of functions from the database class and re-uploaded the file to the live server, it appears that it is somehow being "cached" as when I dump the methods belonging to the database object, the removed methods are still displayed in the list.
The count_users function is also not present in the method list yet when I inspect the file uploaded to the server, it is there in code.
Is there any way of removing this caching???
Try as follows:
class user extends database {
//code user class goes here
}
or
class user extends db_user {
//code user class goes here
}
simple problem solved.
You can store you instance of Database to the variable.
class db_user {
public static $db;
static function openDatabase(){
self::$db = new database();
self::$db->open();
}
static function select_user($user_id) {
$user = NULL;
$result = self::$db->select_user($user_id);
// Test the result and decode user record into $user, etc
self::$db->close();
return $user;
}
static function count_users() {
$count = $db->count_users();
self::$db->close();
return $count;
}
}
The issue, it would appear, is related to another version of the "database.php" file hiding in a sub-folder which must have been copied there by mistake.
Having removed this troublesome file, all now works as expected.
Thanks for your help.
Tried running your code in on-line phptester tool - first complained about missing $params in $db->open(), removing the argument (or passing the $params) it works fine on php 5.2,5.3,5.4. No complaints about count_users().

OOP efficiency when using a class in another class

I have a class called DB (class.pdo.php) that does all the handling on mysql queries using PDO and another class called user that I use to manage a login system.
My question relates to always having to instantiate the $db in every public function of users so I can use DB. Is this efficient? Shouldn't I be instantiating DB inside the __construct() of users?
This is my code
require_once("../../class.pdo.php");
class user {
private $db = null;
public function __construct(){
/* Empty? */
}
public function find_by_email($email){
$db = new db();
$db->query('SELECT * FROM users WHERE email = :email LIMIT 1');
$db->bind(':email',$email);
$result = $db->single();
return $result;
}
public function create($email,$password,$first_name,$last_name){
$db = new db();
$db->query("INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (:email,:password,:first_name,:last_name,NOW())");
$db->bind(':email',$email);
$db->bind(':password',$password);
$db->bind(':first_name',$first_name);
$db->bind(':last_name',$last_name);
$result = $db->execute();
return $db->lastInsertId();
}
[more similar functions ommited]
Well, despite of some comments suggesting the use of the Singleton pattern, I totaly disagree in using it for this purpose.
Your application will not always use a single connection to just one database.
Let me show you how I'd do this:
class DbConnector {
private $dbh;
private $dsn;
public function __construct($dsn) {
$this->dsn = $dsn;
}
private function connect() {
if($this->dbh === null) {
$this->dbh = new PDO($this->dsn);
}
}
public function disconnect {
if($this->dbh !== null) {
$this->dbh = null;
}
}
public function query($sql) {
$this->connect();
//... do the rest
}
public function fetchAll($sql) {
$this->connect();
//... do the rest
}
public function insert($table, $values) {
$this->connect();
//... do the rest
}
public function update($table, $values, $cond) {
$this->connect();
//... do the rest
}
public function delete($table, $cond) {
$this->connect();
//... do the rest
}
}
class User {
private $dbConn;
public function __construct(DbConnector $dbConn) {
$this->dbConn = $dbConn;
}
public function create($email,$password,$first_name,$last_name){
$this->dbConn->query("INSERT INTO users(email,password,first_name,last_name,created_at VALUES (:email,:password,:first_name,:last_name,NOW())");
$this->dbConn->bind(':email',$email);
$this->dbConn->bind(':password',$email);
$this->dbConn->bind(':first_name',$email);
$this->dbConn->bind(':last_name',$email);
$this->dbConn->execute();
return $this->dbConn->lastInsertId();
}
// ...
}
Results:
No singleton used = testable.
Connection to the database is just openned when needed
Your connection is persistent. If you open and close connections in every method, you loose the capability of creating transactions.
What about using the Singleton pattern to create one object for the connection and use it everytime you need it, instead of creating new objects all the time?
I would do something similar with lazy loading: don't initiate in the constructor unless you're sure you actually need the connection every time an object is created but absolutly don't create a new object on each method call. Instead, save the resulting object into an object var which is checked on each method call and initiates the connection if missing.
class user {
protected $_db = null;
private function _init_db() { $this->_db = new XXX; }
public function create( $x, $y, $z ) {
if ( ! $this->_db ) $this->_init_db();
# use $this->_db ..
}
public function find_by_email( $x, $y, $z ) {
if ( ! $this->_db ) $this->_init_db();
# etc
}
}
This has the advantages of avoiding global static state (singletons..) and only creates the connection / object at the very last moment so you're sure you actually need it and it's not just a useless connection.
Speaking of efficiency, the main problem with your code is that it establishes new connection for the every method called. This one is indeed inefficient to the point of killing your database server. And it's incomparable to the other problem you have.
So, in general, you can have whatever way you want - either get somehow an instance of db class in the every function or use a class variable - but either way have to use single PDO instance throughout whole application.
Also I find your functions quite inefficient from the amount of code point of view, and would have optimized them this way
public function create($email,$password,$first_name,$last_name){
$sql = "INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (?,?,?,?,NOW())";
$this->db->query($sql);
$result = $db->execute(func_get_args());
return $db->lastInsertId();
}
From a object point of view, I'd leave database instantiating within the methods, rather than an entire class.
Each method should only see the variables and data it needs, in order to perform its function.
For instance, a createUser() method would need to see variables or properties such as $username, $usergroupId, as well as $database etc.
However, you may have a function which is called randomPassword(), which generates a random password from numbers and letter.
This randomPassword() function doesn't need the database object and therefore, an already initialised database connection in the object scope would be wasteful.
It would be better only to create the new database object in methods that required it.
In addition, in my application, I don't create a new database connection each time I used new database. Instead, I've opted for a singleton PDO database object which keeps the connection active.
I can then just call the database object statically to retrieve an existing connection. Therefore, if, in the process of running my application I need to have 20 database objects, my application then only returns the same object, and the same connection.

Categories