My question is rather simple and after checking a few bits and bobs on here I feel its best to ask a new question.
Lets say I have 2 classes
class FirstClass {
function test() {
return "info";
}
}
class SecondClass {
function test() {
return "info";
}
}
Then I have my mysqli object
$mysqli = new mysqli(host, user, password, db);
What do i need to do to be able to use the mysqli object inside the functions inside the classes.
This is my 2 thoughts so far although I haven't placed it on a site for testing yet.
class FirstClass {
global $mysqli;
function test() {
$mysqli->query("some query");
return "info";
}
}
or
class FirstClass {
function test() {
global $mysqli;
$mysqli->query("some query");
return "info";
}
}
I am pretty sure I can setup a construct if need be but I just need to know which way is the best way/only way to share the mysqli object.
Thanks
EDIT:
So I have done a hell of a load of learning and now have a lot more experience with passing info in and out.
Here is a latest working example type that I use.
namespace Page;
use mysqli;
class edit extends details{
protected $db;
//this function is actually in the details class but there is no point in demoing 2 classes
function __construct(mysqli $con){
$this->db = $con;
}
}
To expand what Kneel told you in comments and to counter the other answer
class foo {
function __construct($mysqli){
$this->mysqli = $mysqli;
}
function test() {
return $this->mysqli->query("some query");
}
}
is what it have to be.
You should create a mysqli instance somewhere outside the class and then pass it in coustructor.
You could use __construct() to initialize your MYSQLi. You can then access it around your class with $this.
class FirstClass {
public function __construct(){
$this->mysqli = new mysqli("host", "user", "password", "db");
}
function test() {
$this->mysqli->query("some query");
return "info";
}
}
If you wanted to use it in your second class too, you could construct it in the same way or extend your first class.
class SecondClass extends FirstClass {
public function __construct(){
parent::__construct();
}
function test() {
return "info";
}
}
Related
Below is the db connection class, but I am going to improve it by extending the PDO class itself:
<?php
class db{
private static $instance = NULL;
public function __construct() {
}
public static function getInstance() {
if (!self::$instance)
{
self::$instance = new PDO("mysql:host=localhost;dbname=dbmvc", 'root', '');;
self::$instance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
return self::$instance;
}
private function __clone(){
}
}
?>
extended class:
<?php
class Model extends db{
final public function fetchInfo()
{
global $pdo, $db;
$query = $db->prepare("SELECT name FROM table");
$query->execute();
$result = $query -> fetchAll();
foreach( $result as $row )
{
echo $row['name'];
}
}
}
?>
But I have errors when I call this method:
$model=new Model();
$model->fetchInfo();
error is:
Call to a member function prepare() on a non-object in C:\xampp\htdocs\mvc\model\model.class.php on line 11
I am new to PDO, and I trying to figure it out but I can't find solution anywhere, can anyone help. Tnx!
This issue has nothing to do with PDO per se, but with object-oriented programming.
You declare global $db which you should be using self::$db or else making a distinct instance variable.
You didn't initialize $db before you called a method on it. You should set it to self::getInstance().
You declare a reference to a variable global $pdo which you never define and never use. This is just sloppy coding.
A model is not a database instance. You should prefer composition over inheritance in this case.
If you would like to see a very nice example of objects such as these I recommend reviewing this Database Class from the PHP-Login script by panique on GitHub. As well as this Model class from the same set of scripts. I hope this helps :D
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.
My basic problem is I am having trouble accessing a class from within another class. Here is what I have set up so far:
My DB class:
class db {
public static $mysqli;
public function __construct(){}
static function con(){
if(!self::$mysqli){
self::$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
}
return self::$mysqli;
}
}
This works all fine and dandy when I just call it from a function like such:
function defineSettings(){
if ($query = db::con()->prepare(...my query...)) {
$query->execute();
$query->bind_result($1, $2, $3);
$query->fetch();
$query->close();
}
db::con()->close();
}
However, I am having trouble accessing this db->con() method from within another class' method. I have tried extending it to a new class, but maybe I am doing it wrong. An example of how to use this from a new class would be much appreciated! Thanks!
Not 100% sure if I understood your question, but the class below should show how you can get the db object from the Db class, and then use it in another function
class Example2 {
private $db;
public function test() {
if (!$this->db) {
$this->db = db::con();
}
//Do your stuff
}
public function test2() {
$this->db->close();
}
}
I have two classes which both extend from SQL class
like this:
class SQL {
private $db_connect_id;
function connect($ad, $db, $us, $pa){
$this->db_connect_id = mssql_connect($ad, $us, $pa);
mssql_select_db ($db, $this->db_connect_id) or die('sql error');
}
function sql_query($query = ""){
unset($this->query_result);
if($query != ""){
$this->num_queries++;
$this->query_result = #mssql_query($query, $this->db_connect_id) or die('error query');
}
if($this->query_result){
unset($this->row[$this->query_result]);
unset($this->rowset[$this->query_result]);
return $this->query_result;
}
}
}
class WEB extends SQL {
function __construct(){ $this->connect(params) }
function __destruct(){ $this->disconnect() }
}
class AUTH extends SQL {
function __construct(){ $this->connect(params) }
function __destruct(){ $this->disconnect() }
}
the problem is that if I call both of them
$WEB = new WEB();
$AUTH = new AUTH();
the $WEB won't work anymore. It loses its connection with the database and it changes the db_connect_id with the db_connect_id from AUTH...
I think this is a stupid question and I'm too tired, but I have to finish.
Where I'm doing wrong?
Thank you
http://php.net/manual/en/function.mssql-connect.php
There is fourth param new_link that must be passed as true (because default is false).
It's impossible to tell from the limited code you've posted, but I think it's pretty clear that you have some singleton-like behavior going on i.e., all instances of SQL and its subclasses are sharing references.
Maybe if you replaced bla bla with the actual code we could narrow it down for you.
There is nothing wrong with the code as presented in your question.
The problem you are describing is symptomatic of using a static property of the SQL class, possibly to hold a database connection resource.
A static property is shared between all instances of a class, which is the behaviour you appear to be describing.
This type of design will work the way you want:
class SQL {
private $database;
function connect() {
$this->datavbase = ....;
};
}
class WEB extends SQL {
function __construct(){ $this->connect(params) }
function __destruct(){ $this->disconnect() }
}
class AUTH extends SQL{
function __construct(){ $this->connect(params) }
function __destruct(){ $this->disconnect() }
}
This type of design will not work the way you want:
class SQL {
private static $database;
function connect() {
$this->datavbase = ....;
};
}
class WEB extends SQL {
function __construct(){ $this->connect(params) }
function __destruct(){ $this->disconnect() }
}
class AUTH extends SQL{
function __construct(){ $this->connect(params) }
function __destruct(){ $this->disconnect() }
}
Should have asked someone this a long time ago.
What is the best way to use other classes within another class?
For instance, lets say I have an application class:
class Application
{
public function displayVar() {
echo 'hello world';
}
}
and a database class
class Database
{
// connects to db on construct
public function query() {
// queries db
}
}
now, i want to add a function to my application class that uses a function from the db class
class Application
{
public function displayVar() {
echo 'hello world';
}
public function getVar() {
global $db;
$sql = foo;
$db->query($sql);
}
}
so then I have
$db = new Database();
$app = new Application();
$app->getVar('var');
Is there a better way of doing this? Really what I am looking for is the standard way of doing it, not another way of rigging it.
There are a couple of ways of doing that. Global variables is certainly one way and the most looked down upon too. You can create a Singleton and all other classes that need database access would call upon this singleton.
final class Database {
private static $connection;
public static function getInstance() {
if(self::$connection == NULL) {
self::$connection = // init your database connection
}
return self::$connection;
}
}
And use this database connection object in whatever class needs it.
class Application {
public function displayVar() {
echo 'hello world';
}
public function getVar() {
$db = Database::getInstance();
$sql = foo;
$db->query($sql);
}
}
This is all well for a start and a great step beyond using global variables, but you can do better with Dependency Injection. Dependency Injection is a simple concept that if a class has any external dependencies, such as the database connection in your example, you explicitly pass those to the needy class in its constructor or a method. So the new code would look something like Jonathan's solution. A major advantage of using dependency injection is in unit testing, where you can easily replace this actual database object with a mock object and pass it to whoever needs it.
class Application {
private $db;
public function __construct(Database $db) {
$this->db = $db;
}
public function displayVar() {
echo 'hello world';
}
public function getVar() {
$sql = foo;
$this->db->query($sql);
}
}
For smaller projects, you can easily do it yourself. For large projects, there are various DI frameworks available for PHP
$db could be a property of your Application class. Any reference to it from within an instance of Application would be done via $this - $this->db
class Application {
private $db = null;
public function setDB($name) {
$this->db = new Database($name);
}
}
Include the class file (or set up autoinclude) in each PHP file that needs the class in question. Then instantiate it as needed.
If you need to have a "common" instance of an object, you can look at the Singleton and Factory patterns:
Singleton Pattern
Factory Pattern