I'm starting to learn how to use OOP within PHP and so far I want to create a Database class that looks like this:
class Database{
//Database connection variables
private $DBHost = "localhost";
private $DBUser = "username";
private $DBPass = "password";
private $DBName = "database3";
public $DBCon;
public function __construct(){
$this->DBCon = new mysqli($this->DBHost,$this->DBUser,$this->DBPass,$this->DBName);
}
public function con(){
return $this->DBCon;
}
public function __destruct(){
$this->DBCon->close();
}
}
And I'm trying to interact with that class from another one called Application:
include('Database.php');
class Application{
public $DB;
public function __construct() {
$DB = new Database();
}
public function InsertName($Username){
var_dump($this->DB->con());
if($this->DB->con()->query("INSERT INTO Test (name) VALUES ($Username);") === TRUE){
echo "Okay";
}else{
echo "Error";
}
}
}
But I get the error Call to a member function con() on a non-object
As a side note, is this an appropriate way to interact with a database in OOP?
Inside the Application class constructor, $DB is being assigned new Database().
This variable is considered a local variable in this case with its scope being the constructor function itself.
To properly assign the new database object to the public $DB property, you will need to access it via the object's $this reference.
public function __construct() {
$this->DB = new Database();
}
This way you will be able to access the proper assigned public property throughout your remaining class methods.
Related
I created a simple database connection class:
class db {
private $db_host = "host";
private $db_user = "user";
private $db_pass = "pass";
private $db_name = "db_name";
public $con;
public function __construct() {
$this->con = mysqli_connect($this->db_host, ... );
...
}
public function query($query) {
return mysqli_query($this->con,$query);
}
}
Now, I would like to use $db->query() within another class instance:
class display {
public function menu() {
this function creates a list based on a result of $db->query('SQL query')
}
plus various other functions to display different things, all using $db->query()
So what is the problem?
First, I got this working by adding 'global $db' to $disply->menu() but this is obviously a big NO NO and needs to be specified within each method.
It is probably clear now that I would like to use $db->query(SQL query) wherever and whenever I need an SQL result, not just within the global scope.
I spent the last couple of hours looking this up but to my surprise most people ask how to use something like $instance->instance->method in global.
Many thanks for your time.
Tom
A simple solution is to inject the $db object when you instance your classes
class Display {
protected $db;
public function __construct($db) {
$this->db = $db;
}
public function menu() {
// here you can use $this->db as if it was the global $db;
}
}
You need to add $db as a parameter everytime you instance your classes
$mydisplay = new Display($db);
There are other ways to achieve the same purpose. For example you can make the $db class a singleton, and add a static method to retrieve the instance from wherever you need. And there are more sophisticated ways such as using pimple to manage your dependency injections as a provider instead of doing it manually.
Im trying to understand objects & classes. But Im having a problem. Im trying to pass a variable from a class into another class.
Why Im doing this is mostly because I want to understand more how classs work but also for future where Im gonna need to send database connection into classes.
Here is my code simplified for the problem:
class databaseConnection
{
public function connect(){
return "localhost";
}
}
class like
{
private $database;
public function __construct(){
$this->database = databaseConnection::connect();
}
public function addLike()
{
return $database;
}
}
$obj = new like;
echo $obj->addLike();
But this doesn't show anything. What i thought the results would be is echo "localhost";
Why isn't this working?
connect is not a static method, you should either change it to static or create an instance.
// if you use databaseConnection::connect();
public static function connect(){
or
$db = new databaseConnection;
$this->database = $db->connect();
And you also need to change
public function addLike()
{
// use $this to access object property
return $this->database;
}
You are calling databaseConnection::connect() as a static method. Modify it to:
public static function connect(){ }
Edit - as #Shankar Damodaran pointed, also add:
public function addLike()
{
return $this->database;
}
First of all you should really follow convention and start naming classes StartingWithCapitalLetter.
Secondly, "::" operator is used to call static methods (to put it simply - you don't have to create object of a class to call them, if they are public).
Normally, to call object's method you use operator "->", like $object->method(arguments);
So in your case, you need to first create an object of your databaseConnection class (because you can't call methods on not-initialized methods) and then call "connect" on it, like that:
$connection = new databaseConnection();
$database = $connection->connect();
To pass a parameter, you need to modify the method declaration
public function connect($parameter){
return "Connecting to " ... $parameter;
}
and call it with
$database = $connection->connect($parameter);
On a sidenote, you should really use parenthesis when creating objects of a class, like:
$obj = new like();
echo $obj->addLike();
Also, as deceze pointed out, you need to access class variable using $this instead of accessing local method variable:
public function addLike()
{
return $this->database;
}
public function addLike()
{
return $this->database;
}
$database and $this->database are two different variables. $database is a local function variable which does not exist, it's not the object property you set before.
I am building an API in PHP and I have a question. I'm using classes, and some of these classes need to access my database. However, I don't want to define variables for the database in every single class in order to open it, or have to send my mysqli object as a parameter of every single class constructor.
What would be the best way to go about this? Do I define a global variable of some kind?
A classic solution would be as follows
Create an instance of dbatabase handler class, either raw mysqli (worse) or better abstraction class (way better)
In the constructor of your application class take this db class instance as a parameter and assign it to a local variable
Use this variable with your class.
A quick example:
class Foo()
{
protected $db;
function __construct($db);
{
$this->db = $db;
}
function getBar($id)
{
return $this->db->getOne("SELECT * FROM bar WHERE id=?i", $id);
}
}
$db = new safeMysql();
$foo = new Foo($db);
$bar = $foo->getBar($_GET['id']);
How about using a static classes?
class mysqli_wrapper {
private static $db = null;
public static function open() {
GLOBAL $opts; // this can be global or setup in other ways
if (!self::$db) {
self::close();
self::$db = null;
}
self::$db = #mysqli_connect('p:'.$opts['hn'], $opts['un'], $opts['pw'], $opts['db']);
return self::$db;
}
public static function query($qry) {
return mysqli_query ( self::$db, $qry );
}
public static function affected_rows() { return #mysqli_affected_rows(self::$db); }
public static function error() { return #mysqli_error(self::$db); }
public static function close() { #mysqli_close(self::$db); }
} // end mysqli_wrapper
mysqli_wrapper::open(); // Here's how to call it
In a system I maintain my app needs to access its own MySQL db, as well as remote Oracle and SQL Server databases, and I use a trait for it. Here's a simplification of my code, just using MySQL:
dbaccess.php
trait DatabaseAccess {
protected $db;
private $host = 'host', $dbName = 'db', $username = 'username', $password = 'pword';
public function connectToMysql() {
$this->db= new mysqli(......);
}
}
then in myclass.php
require 'dbaccess.php';
class MyClass {
use DatabaseAccess;
//class code.....
}
All elements of DatabaseAccess will be available as if you hand-typed them in MyClass.
Note: if you're using PHP < 5.4, then this solution won't be possible.
I currently have a class called Connect with the following code:
class Connect
{
public $sqlHost='host';
public $sqlUser='user';
public $sqlPass='pass';
public $sqlDB='db';
public $db;
public function __construct() {
$this->db = new mysqli($this->sqlHost, $this->sqlUser, $this->sqlPass, $this>sqlDB);
}
}
?>
I also have a class called TODO and I was wondering, how could I go about calling $db located in the Connect class from the TODO class?
imagine you have have two objects called
$connect = new Connect();
$todo = new TODO();
now 1 of 3 things can happen, You can pass the $connect object into a method of $todo or if a Connect object is a member of a TODO object, or create a new connect object.
scenario 1:
class TODO {
public function foo($connect){
// You can get the db object here:
$connect->db
}
}
$todo->foo($connect)
scenario 2:
class TODO {
public $connect;
public function __construct(){
$this->connect=new Connect();
}
public function foo(){
//get db:
$this->connect->db;
}
}
$todo->foo();
scenario 3:
class TODO {
public function foo(){
$connect = new Connect();
$connect->db;
}
}
I'm not sure what you want, but I think its this
$connectInstance = new Connect();
$connectInstance->db...
This way you can access the db variable in a connect object. But first, you have to instanciate the object.
I have several classes in an application that I am currently building, and I want to have one access some of the other's member functions but i can't seem to do it.
The first class is called MySQLDB:
class MySQLDB{
public $connection;
function __construct(){
//connects to database
}
function login($username, $password){
//queries database...
}
}
Then I have a class called Session:
class Session{
//variables
//constructor
function processlogin($username, $password){
$database->login($username, $password);
}
Then after this I have two class declarations:
$database = new MySQLDB();
$session = new Session();
No matter where i put these statements in relation to the classes I still get the same error:
PHP Notice: Undefined variable: database in C:\inetpub\wwwroot\cmu\include\session.php on line 52
PHP Fatal error: Call to a member function login() on a non-object in C:\inetpub\wwwroot\cmu\include\session.php on line 52
I have seen some suggestions that would suggest putting the new database object inside the Session class declaration but I want to avoid doing so because I use the database class several other places in the code and I don't want to open up multiple connections to the database.
since you want to have acces on a globally set variable, you can either gain access to it with global:
function processlogin($username, $password){
global $database;
$database->login($username, $password);
}
or use the variable as a parameter for the contructor and remember the database object reference in the class Session:
class Session{
private $database;
function __construct($database){
$this->$database = $database;
}
function processlogin($username, $password){
$this->database->login($username, $password);
}
}
and then you call:
$database = new MySQLDB();
$session = new Session($database);
this comes in handy, if you use more functions afterwords, that also need access to the database object.
you could pass a reference to the MySQLDB instance in the Session constructor.
class Session{
public $db;
function __construct(&$db=null){
if($db == null)
$this->db = new MySQLDB();
else
$this->db = $db;
}
// ....
}
$database = new MySQLDB();
$session = new Session($database);
You are creating two global variables. If you're doing such thing, you need to declare variables you want to use in function with "global" keyword:
function processlogin($username, $password){
global $database;
$database->login($username, $password);
}
Despite this will work, I highly recommend reading about Dependecy Injection mechanism in which you'd pass $database variable as a parameter to processlogin() method, or set it as a private member of that class in constructor / setter. That way database connection will be interchangeable and you'll get more flexibility in your code.
$database is not defined inside processlogin nor passed as parameter, hence the function has no access to it.
You could pass it as constructor parameter to Session:
class Session {
private $db;
public function __construct($database) {
$this->db = $database;
public function processlogin($username, $password){
$this->$db->login($username, $password);
}
}
$database = new MySQLDB();
$session = new Session($database);