Problem: I have 2 classes, DB class and a User class, that will work if placed in the same class but when i seperate them i cant figure out how to get the user class to connect using the DB class.
I have 'DBinterface' class and a 'user' class.
***dbinterface.php
<? class dbinterface {
var $dbHost,
$dbUser,
$dbName,
$dbPass,
$dbUserTable;
function User() {
$this->dbHost = 'host':
$this->dbUser = 'user';
$this->dbName = 'name';
$this->dbPass = 'pass';
$this->dbUserTable = 'table';
}
} // End dbinterface class definition ?>
***user.php
<?
include('dbinterface.php');
class User {
var $userID,
$userName,
$userPassword;
function registerUser($userName, $userPassword) {
// Connect to database
$dbLink = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass);
if(!$dbLink) die("Could not connect to database. " . mysql_error());
// Select database
mysql_select_db($this->dbName);
// Insert data
$query = "insert into $this->dbUserTable values (NULL, \"$userName\", \"$userPassword\")";
$result = mysql_query($query);
// Test to make sure query worked
if(!$result) die("Query didn't work. " . mysql_error());
// Get the user ID
$this->userID = mysql_insert_id();
// Close database connection
mysql_close($dbLink);
// Assign the values to the data members
$this->userName = $userName;
$this->userPassword = $userPassword;
} // End registerUser() ?>
PS:I have removed security and other mumbojumbo for easy legibility.
any and all help is MUCH appriciated!
Well. I'll try to imagine what are you wanted to do :)
You need one class where you will store db variables, such as username, password and so on and 2nd class which will work with db-class params.
/* file1 */
Class db {
private $_dbLink;
private $_dbHost = 'host';
private $_dbUser = 'user';
private $_dbName = 'name';
private $_dbPass = 'pass';
private $_dbUserTable = 'table';
public function connect ()
{
$this->_dbLink = mysql_connect($this->_dbHost, $this->_dbUser, $this->_dbPass);
if(!$this->_dbLink)
throw new Exception ("Could not connect to database. " . mysql_error());
}
public function getLink()
{
return $this->_dbLink;
}
public function getUserName ()
{
return $this->dbUser;
}
public function getUserPass ()
{
return $this->_dbPass;
}
/* create the same methods for each variable */
}
/* file2 */
Class User {
public function registerUser (/* params */)
{
$db = new db();
$db->connect();
/* your code */
// Select database
mysql_select_db($db->getDb(), $db->getLink());
// Insert data
$query = "insert into ".$db->getTable()." values (NULL, \"$userName\", \"$userPassword\")"; /* here is SQL-injection */
$result = mysql_query($query, $db->getLink());
/* and so on ...... */
}
}
/* file3 */
// include file1
// include file2
$user = new User;
$user->registerUser(/* params */);
This is fast solution. You should learn how to create classes and project architecture. Use php.net for more information. Read about Object-oriented programming. And read about SQL-injections for safer code.
$this inside User class will access only variables or objects and functions inside the 'Class User', you can not access variables or objects inside 'class dbinterface' to access that you have extend that class to your User class. You can try like this
class User extends dbinterface {
}
That will give you results.
Related
I have a class with a connection to a database
$db = new db();
class db {
public $server = 'localhost';
public $user = '';
public $passwd = '******';
public $db = '';
public $dbCon;
function __construct() {
$this->dbCon = mysqli_connect($this->server, $this->user, $this->passwd, $this->db);
}
function __destruct() {
mysqli_close($this->dbCon);
}
}
Now i want to make an other class and using the connection like this:
class Categories (
function GetCategory($cat) {
$myQuery = "SELECT * FROM test GROUP BY $cat";
$results = mysqli_query($this->dbCon, $myQuery);
return $results;
}
)
How can i use the connection in a other class?
Can somebody help me out whit this?
Make the $dbCon in your db class a static variable, so you can access it from category's using db::$dbcon as the connection variable. You could also make a static function returning the static dbcon variable, usefull tot check if it is actually a link and not null.
This is just one solution of many possibilities, but probably the easiest to implement because it isn't likely you need more connections to a db, so a static is perfect for it.
A static is nothing more then a variable living in the namespace it is defined in, you don't need to initialize the class in order to access it. It's value is shared across all instances of the object, so creating multiple DB class instances allows you tot just return a static if it was set in a previous DB class instance.
class db{
static $link;
static function connect(){
if(self::$link = mysqli_connect(....)){
return self::$link;
} else {
die('could not connect to db');
}
}
static function getcon(){
return isset(self::$link) ? self::$link : self::connect();
}
}
class Categories{
function GetCategory($cat){
$myQuery = "SELECT * FROM test GROUP BY $cat";
return mysqli_query(db::getcon(), $myQuery);
}
}
Create an object of the db class in the categories class. Then use that object to query the db accordingly. Also make sure you use a static variable in the db class. SO that the connection variable is created once and will be used all along the application.
Your db class may look like this
class db {
public $server = 'localhost';
public $user = '';
public $passwd = '******';
public $db = '';
public static $dbCon;
function __construct() {
$this->dbCon = mysqli_connect($this->server, $this->user, $this->passwd, $this->db);
}
function __destruct() {
mysqli_close($this->dbCon);
}
}
Your categories class may look like this
class Categories {
$connection=db::$dbCon;
if(!$connection){
$db=new db();
$connection=db::$dbCon;
}
function GetCategory($cat) {
$myQuery = "SELECT * FROM test GROUP BY $cat";
$results = mysqli_query($this->connection, $myQuery);
return $results;
}
}
This question already has answers here:
How to initialize static variables
(10 answers)
Closed 6 years ago.
I am teaching myself PHP and am playing around with different projects to learn as much as possible. Right now I am working on a login script and everything works as expected. I originally wrote the script with just functions and no classes but then decided to incorporate classes to help myself learn them. I need some input on the following class. I don't feel switching to a class has accomplished anything because I simply inserted the function into the class. I know there is a better way to do this but am having trouble figuring it out.
Also, in each function I call the database connection class to establish a connection, is there a way to extend the database connection and use a variable for the connection so I don't have to call the class for each and every function?
I tried
<?php
include('dbClass.php');
class login_user extends Database {
public $db = Database::getInstance();
public $conn = $db->getConnection();
and I get the following error
Fatal error: Constant expression contains invalid operations in /Applications/MAMP/htdocs/login_project/includes/classes/login_userClass.php on line 5
dbClass.php
<?php
class Database {
private $_connection;
private static $_instance; //The single instance
private $_host = SERVER;
private $_username = USER;
private $_password = PASS;
private $_database = DB;
/*
Get an instance of the Database
#return Instance
*/
public static function getInstance() {
if(!self::$_instance) { // If no instance then make one
self::$_instance = new self();
}
return self::$_instance;
}
// Constructor
private function __construct() {
$this->_connection = new mysqli($this->_host, $this->_username,
$this->_password, $this->_database);
// Error handling
if(mysqli_connect_error()) {
trigger_error("Failed to conencto to MySQL: " . mysql_connect_error(),
E_USER_ERROR);
}
}
// Magic method clone is empty to prevent duplication of connection
private function __clone() { }
// Get mysqli connection
public function getConnection() {
return $this->_connection;
}
}
login_userClass.php
<?php
class login_user {
//see if the user exists
function does_user_exist($username){
$db = Database::getInstance();
$conn = $db->getConnection();
$stmt = $conn->prepare("SELECT user_name FROM users WHERE user_name = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->store_result();
return $stmt->num_rows;
}
//get the user hash and if create session variables and log users in.
function get_user_hash($username, $password){
$db = Database::getInstance();
$conn = $db->getConnection();
$stmt = $conn->prepare("SELECT id, user_name, user_password, user_email, user_registered FROM users WHERE user_name = ? LIMIT 1");
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->bind_result($id, $user, $pass, $email, $user_registered);
while($stmt->fetch()){
if(password_verify($password, $pass)){
$_SESSION['user_id'] = $id;
$_SESSION['user'] = $user;
$_SESSION['email'] = $email;
$_SESSION['registered_on'] = $user_registered;
$_SESSION['loggedin'] = true;
header("Location: http://".$_SERVER['HTTP_HOST']."/user.php");
exit;
} else {
return false;
}
}
}
}
you need to place initialization to some static method and call it after class definition
How to initialize static variables
Having trouble understanding classes and inheritance:
core.php:
$servername = "****";
$database = "****";
$username = "****";
$password = "****";
try {
$pdo = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
class Database {
protected $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
}
}
class User extends Database {
private $ip;
private $sessionId;
public function __construct($ip, $sessionId) {
$this->ip = $ip;
$this->sessionId = $sessionId;
}
public function getSessionInfo () {
$stmt = $this->pdo->prepare(".."); <-- error here
....
}
}
When calling:
require_once 'api/core.php';
$database = new Database($pdo);
$user = new User($_SERVER['REMOTE_ADDR'], $_SESSION['info']['id']);
In this contest $database, and $user variables are not related to each other:
require_once 'api/core.php';
$database = new Database($pdo);
$user = new User($_SERVER['REMOTE_ADDR'], $_SESSION['info']['id']);
Thus, calling prepare() on $user won't work.
You need a mechanism, at least like this , although not a good practice to assign Database to a User:
$user->setDatabase($database);
Instead create a static Database object, initiate it before User initiation, and call it statically within User object, or any other object, make it available for all objects.
A quick fix would look like this, where User doesn't extend Database, because it's wrong. User is not a Database.
$database = new Database();
$user = new User();
$user->setDatabase($database); //sets $db variable inside User
//User.php
namespace MyApp;
class User{
private Database $db;
public function setDatabase($db){
$this->db = $db;
}
public function doSomething(){
$this->db->getPdo()->prepare('..');
}
}
//Database.php
namespace MyApp;
class Database{
private $pdo; //returns PDO object
function __construct(){
//create pdo connection
$this->pdo = ..
}
function getPdo(){
return $this->pdo;
}
}
Database should be injected to objects or used by objects, you shouldn't be extending Database just to have it. If you want to do it properly, in an object-oriented way.
Remember PHP doesn't allow multiple inheritances by extend. Tomorrow, you might want to have a Person class that every User will extend, but since you did it wrong in the beginning, and wasting precious extend on Database, it won't be possible. And by not having a control of how many database instances you have created, you will run into issues. You need to know for sure that you have only a single connection object for one database, if of course the opposite is a must - which in your case I doubt.
Of course this will change if you have multiple database requirements, and more sophisticated app structure.
You are receiving this error because User Instance has pdo empty. try this code
$servername = "****";
$database = "****";
$username = "****";
$password = "****";
try {
$pdo = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
class Database {
protected $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
}
}
class User extends Database {
private $ip;
private $sessionId;
public function __construct($pdo, $ip, $sessionId) {\
parent::__construct($pdo)
$this->ip = $ip;
$this->sessionId = $sessionId;
}
public function getSessionInfo () {
$stmt = $this->pdo->prepare("..");
....
}
}
then
require_once 'api/core.php';
$user = new User($pdo, $_SERVER['REMOTE_ADDR'], $_SESSION['info']['id']);
hope it helps.
I have one DB class in which I am calling mysqli connect in constructor, I want to use this connection in another class. How I can do that, Do i have to reinitialize class first inside the class II ?? Or do I have to Inherit DB Class to class 2 ??
appreciate any guidance.
Thanks in advance,
Sambhav
Below are Rough outline of both the classes.
CLASS I - DB Class
class Db {
private $dbHost = "";
private $dbUser = "";
private $dbPass = "";
private $dbDatabase = "";
function __construct() {
$mysqli = new mysqli($this->dbHost, $this->dbUser, $this->dbPass, $this->dbDatabase);
if ($mysqli->connect_errno) {
echo "Error in connecting to database" . $mysqli->connect_error;
}
//echo "connected to database";
}
}
class II - The Class trying to use db connection
class MyClass {
private $details = array();
public function getDetails() {
$query = "SELECT `user` FROM `db`.`table`";
$result = $mysqli->query($query);
while ($row == $result->fetch_assoc()) {
//.........
}
return $details;
}
}
You can use a protected property within the class that is trying to use Db, for example;
class MyClass {
protected $objDb;
public function connectToDb() {
$this->objDb = new Db();
}
Then, within your getDetails method, use $this-> to "access" the Db class.
$result = $this->objDb->query($query);
And usage;
$objMyClass = new MyClass();
$objMyClass->connectToDb();
$objMyClass->getDetails();
Alternatively, you could put connectToDb method within your __construct()
Here is the full code: http://harrydenley.com/stackoverflow-25112589/ (Tested on my server and all works. I had to make a few changes, which you can see in the post)
Currently, my website runs procedural PHP. I would like to achieve to have a database class that can be used for other classes.
STATUS QUO:
On every page I include my dp.php before my header.php, the content and footer.php appear. My db.php looks like this:
// Credentials
$dbhost = "localhost";
$dbname = "dbname";
$dbuser = "dbuser";
$dbpass = "dbpassword";
// Connection
global $db;
$db = new mysqli();
$db->connect($dbhost, $dbuser, $dbpass, $dbname);
$db->set_charset("utf8");
// Check Connection
if ($db->connect_errno) {
printf("Connect failed: %s\n", $db->connect_error);
exit();
}
GOAL:
Having a database object that I can integrate into the EventData class that I have been building. The desired function of this class is that it will allow me to easily access data of my events table on any page. My EventData-class.php looks like this:
Class EventData {
private $_db;
private $_event_id;
public function __construct($eventID) {
$this -> _event_id = $eventID;
}
public function getValue($fieldname) {
// Build query for getting event details
$query = 'SELECT * FROM events WHERE id=' . $this -> _event_id . '';
// Do Search
$results = $db->query($query);
// Store all event details available in variables
while ($result = $results->fetch_assoc()) {
$value = $result[$fieldname];
}
// Return value
return $value;
}
}
I am new to OOP and am interested in learning how I need to modify both db.php and EventData-class.php in order to work.
The answer is brief and needs some your effort to improve or encode the idea.
First of all create a collection of items, something like this
class EventCollection {
protected $items = array(); // I keep protected so only addItem, removeItem etc. can be used to handle data
public $database = NULL;
public function addItem(EventData $item){
$this->items[] = $item;
$item->collection = $this; // this allows your EventData object to refer to its container
}
public function clear(){
$this->items = array();
}
public function __construct(mysqli $datb){ // inject mysqli object
$this->database = $datb;
}
public function removeItem... etc.
}
Having prepared the collection class, just update your EventData (consider creating a child class) by $collection field:
class EventData {
private $_db; // throw this away, not necessary
private $_event_id;
public $collection = NULL;
// etc.
Then in your main code create a $db variable as you do. Then create a (empty) collection:
$myEventCollection = new EventCollection($db);
and add items by
$myEvent = ....;
$myEventCollection->add($myEvent);
To refer to $db value inside the EventData class use something like this
class EventClass { ....
public function updateEvent(){
$this->collection->database->query('UPDATE ...');