I have 2 classes looking like this:
class db {
protected $db;
function __construct() {
$this->connect();
}
protected function connect() {
$this->db = new MySQLi(db_host, db_user, db_pass, db_name) or die($this->db->error);
$this->db->set_charset('utf8');
}
}
and
class sample extends db {
protected $js_base_dir;
public function __construct($js_base_dir = js_dir) {
$this->js_base_dir = $js_base_dir . "/";
}
....
I want to use $this->db inside second class, but __construct in sample class overrides first classes construct function. How to get $this-> db inside second class? Am I doung something wrong? if yes what's proper way?
You can call parent class method, using parrent::methodName(). Similarly, you can use this to invoke parent's constructor method as well as
parent::__construct();
Usage:
public function __construct($js_base_dir = js_dir) {
parent::_construct();
$this->js_base_dir = $js_base_dir . "/";
}
Apart from the manual read this article for extended explanation.
Try this:
public function __construct($js_base_dir = js_dir) {
parent::__construct();
$this->js_base_dir = $js_base_dir . "/";
}
Related
I once used to have my database connection in a file and included it on the pages that I needed it. Inside of this file, I also extended the PDO class with a new method, run(), which allows me to write shorthand PDO queries and worked fine:
class MyPDO extends PDO {
public function run($sql, $bind = NULL) {
$stmt = $this->prepare($sql);
$stmt->execute($bind);
return $stmt;
}
}
$conn = new MyPDO("mysql:charset=utf8;host=$host;dbname=$name", $user, $pass);
I'm now trying to neaten up my files and the code within them, by using classes. So, this database connection file became two classes:
class MyPDO extends PDO {
public function run($sql, $bind = NULL) {
$stmt = $this->prepare($sql);
$stmt->execute($bind);
return $stmt;
}
}
class Connection {
private $_config = NULL;
public $conn = NULL;
public $error = NULL;
public function __construct(array $config) {
$this->_config = $config;
$this->getPDOConnection();
}
private function getPDOConnection() {
if ($this->conn == NULL) {
$this->conn = new MyPDO("mysql:charset=utf8; host=".$this->_config['host']."; dbname=".$this->_config['name']."", $this->_config['user'], $this->_config['pass']);
[...]
}
}
[...]
}
At this point in time, I'm not using an autoload function to load the classes. There are only two classes needed for this particular file, so I'm requiring them manually. I'm also led to believe that including the connection class manually, allows the PDO class to be extended with MyPDO.
require API_ROOT . 'core/database/connection.class.php';
require API_ROOT . 'core/users/user.class.php';
I've tested the connection and it has indeed connected.
The problem I'm having, is using the new MyPDO method named run() inside of another class, in this case user.class.
Inside of user.class, I'm simply trying to authenticate a user and therefore need to use the run() method.
I call the user class like this:
$db = new Connection($config['database']);
$user = new User($db, $config);
And inside of the user.class, I want to use run() and do so by calling $this->db->run:
class User {
private $db = NULL;
private $config = NULL;
public function __construct($db = NULL, $config = NULL) {
$this->db = $db;
$this->config = $config;
}
public function login($email = '', $password = '', $remember_me = '') {
$user_profile = $this->db->run(" <--------------
[...]
", [$email])->fetch(PDO::FETCH_ASSOC);
}
}
But I receive the following error when I run this:
Uncaught Error: Call to undefined method Connection::run()
I understand what the error means, that there is no method called run() inside of my connection class but why does it think that method is in there? What am I doing wrong here?
#Quasimodo'sclone is correct, you need to fetch it from the conn variable as they demonstrated. If it's not working, you are doing something wrong on the implementation elsewhere because run() is a method of conn because conn is the class MyPDO which defines the run() method:
$this->db equals class Connection which creates instance of MyPDO in the __construct() and assigns it to $this->conn in the getPDOConnection() method – therefore $this->db->conn->run() is what you are looking for.
Your getPDOConnection() should maybe be renamed to setPDOConnection() then have the getPDOConnection() retrieve $this->conn:
public function getPDOConnection()
{
return $this->conn;
}
Then your User class would actually use:
$this->db->getPDOConnection()->run(...etc);
It would make it a little clearer.
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 have an issue accessing top level variables from sub-level class.
Here's an example...
Application.php:
class Application {
var $config;
var $db;
function __construct() {
include_once('Configuration.php');
include_once('Database.php');
$this->config = new Configuration;
$this->db = new Database;
}
}
Configuration.php:
class Configuration {
var $dbhost = 'localhost';
}
Database.php:
class Database {
function __construct() {
echo parent::config->dbhost;
}
}
It is clear to me that usage of parent is wrong here as the subclass does not extend the parent class, but how do I access it?
Thank you.
You should create a Base class that in its construct creates a $db link. Then let all classes that require database access extend that class. Your nomenclature here with "parent class" is incorrect.
class Base {
private $db; // Make it read-only
function __construct() {
$this->db = DB::connect(); // It's a good practice making this method static
}
function __get($property) {
return $this->$property;
}
}
class Application {
public $config;
function __construct() {
parent::__construct();
require_once 'Configuration.php';
require_once 'Database.php';
$this->config = new Configuration();
}
function random_function() {
$this->db(....) // Has full access to the $db link
}
}
The parent notation is used to access the parent of the object in the object hierarchy. What you are doing here is trying to get at the caller, not the parent
The way that you would do this is to pass in an instance of your configuration to the database object.
class Database {
protected $config;
public function __construct(Configuration $config){
$this->config = $config;
}
public function connect(){
//use properties like $this->config->username to establish your connection.
}
}
The parent notation is used when you extend a class and make a child class to call methods on the parent .
class MySuperCoolDatabase extends Database {
protected $is_awesome;
public function __construct(Configuration $config){
// do all the normal database config stuff
parent::__construct($config);
// make it awesome
$this->is_awesome = true;
}
}
This defines a child class, which is a type definition that serves the same role as the base class with a slightly different implementation. Instances of this can still be said to be a Database.... just a different kinds of database.
Well, although I think that Orangepills answer is better. If you dont want to use it and since all variables are public, you could simply pass the variable like this:
class Application {
var $config;
var $db;
function __construct() {
include_once('Configuration.php');
include_once('Database.php');
$this->config = new Configuration;
$this->db = new Database($this->config->dbhost);
}
}
class Configuration {
var $dbhost = 'localhost';
}
class Database {
function __construct($dbhost) {
echo $dbhost;
}
}
I have db class which looks like that
class db {
protected $db;
public function __construct() {
$this->connect();
}
protected function connect() {
$this->db = new MySQLi(db_host, db_user, db_pass, db_name) or die($this->db->error);
$this->db->set_charset('utf8');
}
}
Every class inside my PHP app extends this db class
Like
class registration extends db {
var $validation;
function __construct() {
parent::__construct();
$this->validation = new validation();
...
And validation looks like that
class validation extends db {
var $ajax, $common;
function __construct() {
parent::__construct();
...
Getting error message "Too many connections". I feel that, this is not right approach: I'm every time reconnecting to db. So what's right way in your opinion? Is that possible to define('db', ...) 1 time and use everywhere inside app?
registration and validation are classes the use db but are not a sub-class of it.
Your code should look like:
$db = new DB();
$db->connect();
$registration = new Registration($db);
class Registration {
private $db;
public function __construct(DB $db) {
$this->db = $db;
...
You pass a reference to an instance of $db to all classes that require it.
The reason you're opening too many connections is probably because currently each class makes it's own connection to your database, and that is not what you want to do, or need to do.
You want to use composition here instead. Also might consider investigating Singleton pattern.
To elaborate, using composition, each class in your library will have an instance of the db class rather than be an instance of the db class.
Singleton will make the db class enforce only one instance of the class is ever created which is useful for shared resources like database connections. Have a look at this link for further reading on the topic.
http://php.net/manual/en/language.oop5.patterns.php
EDIT: Adding some code
Turning the db class into a Singleton
<?php
class db
{
static private $_oInstance = null;
protected $db;
private function __construct()
{
$this->connect();
}
static public function getInstance()
{
if(self::$_oInstance === null)
self::$_oInstance = new db();
return self::$_oInstance();
}
protected function connect()
{
$this->db = new MySQLi(db_host, db_user, db_pass, db_name) or die($this->db->error);
$this->db->set_charset('utf8');
}
}
Revising the rest of your classes to compose the db instance rather than extend the db class
class registration
{
private $_oDb;
public $validation;
function __construct()
{
parent::__construct();
$this->_oDb = db::getInstance();
$this->validation = new validation();
}
// ...
}
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();
}
}