Inheriting database connection in PHP OOP - php

My abstract class Database is made for database interaction and any child of this class (UserDatabase, ActionDatabase, EventDatabase) inherits its database connection which is defined as static.
abstract class Database {
public static $connection;
public function __construct( ) {
...
$this->connection = mysql_connect( $host, $username, $password );
}
}
class UserDatabase extends Database {
public function verify( ) {
if ( $this->connection == parent::$connection ) {
print "true";
} else {
print "false";
print "this:" . $this->connection . " parent:" . parent::$connection;
}
}
}
$instance = new UserDatabase( );
$instance->verify( );
// this prints false, as parent::$connection is empty
Does that mean, that my database connection is only set up and stored in memory once and passed on to subclasses as reference without being replicated for each instance?
Is this how you would implement you OOP-correct database interface?

Ignoring your code for a moment and looking only at your description of how this scheme should work... Yes, the database connection would only be set up once for each PHP script and would not be duplicated for each instance.
Whether this is a good idea or not depends on what your subclasses are. Each class should have one responsibility. As long as the subclasses' only responsibility is DB interaction, you're probably fine. (Look at the Repository Pattern for an explanation of how this is commonly done.) If your User class extends Database so that it can store itself, you've crossed a line and are writing classes that will have too many dependencies and responsibilities.
As for your code... Almost every line of your code is wrong. You cannot initialize class variables to the results of a function. Your SQL is wrong. The line $connection ? "connected" : "not connected"; does nothing. Almost none of that should be done in a constructor. Etc.

That pattern is OK if you're doing nothing else with those classes but database interactions.
Otherwise you may be better off with a Database class that's created once that you can "getInstance()" of each time. Singleton Design Pattern.
http://www.tonymarston.net/php-mysql/singleton.html

Related

How to fix Message: SQLSTATE[08004] [1040] Too many connections

I am using below code for database connection
class Database extends PDO{
function __construct(){
try {
parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
} catch(PDOException $e){
Logger::newMessage($e);
logger::customErrorMsg();
}
}
}
every thing like login , fetching data was working fine . Now suddenly I am having a exception error message
Message: SQLSTATE[08004] [1040] Too many connections
Code: 1040
How to fix this error ?
I have a model class there I am creating new database.
class Model {
protected $_db;
public function __construct(){
//connect to PDO here.
$this->_db = new Database();
}
}
and every model I make , I am extending from model class.
Because your Model class instantiates a new Database object in its constructor, each time you instantiate a Model (or any class extending it), you are in effect opening a new database connection. If you create several Model objects, each then has its own independent database connection, which is uncommon, usually unnecessary, not a good use of resources, but also actively harmful as it has used up all the server's available connections.
For example, looping to create an array of Model objects:
// If a loop creates an array of Model objects
while ($row = $something->fetch()) {
$models[] = new Model();
}
// each object in $models has an independent database connection
// the number of connections now in use by MySQL is now == count($models)
Use dependency injection:
The solution is to use dependency injection and pass the Database object into the Model::__construct() rather than allow it to instantiate its own.
class Model {
protected $_db;
// Accept Database as a parameter
public function __construct(Database $db) {
// Assign the property, do not instantiate a new Database object
$this->_db = $db;
}
}
To use it then, the controlling code (the code which will instantiate your models) should itself call new Database() only once. That object created by the controlling code must then be passed to the constructors of all models.
// Instantiate one Database
$db = new Database();
// Pass it to models
$model = new Model($db);
For the use case where you actually need a different independent database connection for a model, you can hand it a different one. In particular, this is useful for testing. You can substitute a test database object, or a mock object.
// Instantiate one Database
$db = new Database();
$another_db = new Database();
// Pass it to models
$model = new Model($db);
$another_model = new Model($another_db);
Persistent connections:
As mentioned in the comments, using a persistent connection is possibly a solution, but not the solution I would recommend. PDO will attempt to reuse an existing connection with the same credentials (as all yours will have), but you don't necessarily want the connection to be cached across script execution. If you did decide to do it this way, you need to pass the attribute to the Database constructor.
try {
// Set ATTR_PERSISTENT in the constructor:
parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS, array(PDO::ATTR_PERSISTENT => true));
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
}
The relevant documentation is here: http://php.net/manual/en/pdo.connections.php#example-950
Singleton solution:
Using a singleton pattern (also not recommended), you could at least reduce this to a search/replace in the model code. The Database class needs a static property to keep a connection for itself. Models then call Database::getInstance() instead of new Database() to retrieve the connection. You would need to do a search and replace in the Model code to substitute Database::getInstance().
Although it works well and isn't difficult to implement, in your case it would make testing a little more difficult since you would have to replace the entire Database class with a testing class of the same name. You can't easily substitute a test class on an instance by instance basis.
Apply singleton pattern to Database:
class Database extends PDO{
// Private $connection property, static
private static $connection;
// Normally a singleton would necessitate a private constructor
// but you can't make this private while the PDO
// base class exposes it as public
public function __construct(){
try {
parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
} catch(PDOException $e){
Logger::newMessage($e);
logger::customErrorMsg();
}
}
// public getInstance() returns existing or creates new connection
public static function getInstance() {
// Create the connection if not already created
if (self::$connection == null) {
self::$connection = new self();
}
// And return a reference to that connection
return self::$connection;
}
}
Now you would need to change only the Model code to use Database::getInstance():
class Model {
protected $_db;
public function __construct(){
// Retrieve the database singleton
$this->_db = Database::getInstance();
}
}

Singleton v Single Instance DB Connection in PHP

I'm moving onto teaching myself OOP in PHP.
I'm creating a couple of little web apps and have followed a lot of tutorials that either create the database (using PDO) via a Singleton, or via passing the global around. I've read that these are pretty much the same thing and are both to be avoided like the plague.
So I've watched the Google Tech Talks on clean code, and read almost every SO article on dependency injection and the like. I have a couple of questions.
The clean code videos suggest you shouldn't do 'work' in your constructors. Is this 'work' in reference to business logic. Ie. If my class's job is to create another object, is that an OK kind of 'work'?
For example, in trying to conform to single repsonibility classes I created three.
Class DB - which actually connects to the database.
Class DBFactory - which creates the DB object which connects to the database.
Class DBInstance - which returns a single instance of the DBFactory created PDO object.
Please note that I'm trying to create a single instance, without creating a Singleton pattern.
So I try and pass my dependencies for each class up the chain. I find myself in a position where I have to create all of the objects (from DB down) so I can inject the dependencies. For some reason I thought it would work the other way, I'd create the first object, which would create the second for me etc. I'm clearly missing something?
Hopefully this helps others as well - there seems to be a myriad of questions relating to this stuff and databases but very little good examples.
(I should mention this does work, I do get a list of hotel names out of the database!)
TestCode.php
include './classes/DB.php';
include './classes/DBFactory.php';
include './classes/DBInstance.php';
include './classes/Location.php';
$db = new DB;
$dbfactory = new DBFactory($db);
$dbinstance = new DBInstance($dbfactory);
$dbh = $dbinstance->getDbInstance();
//Example business logic
$location_names = Location::getLocationNames($dbh);
print_r($location_names);
Class DB.php:
class DB {
private $_dbhost = 'myhost';
private $_dbname = 'myname';
private $_dbuser = 'myuser';
private $_dbpass = 'mypass';
private $_error;
public function connect() {
try {
return new PDO("mysql:host=$this->_dbhost;dbname=$this->_dbname",
$this->_dbuser, $this->_dbpass);
}
catch (PDOException $e) {
$this->_error = 'Error! ' . $e->getMessage() . '<br />';
die();
}
}
public function getError() {
if (isset($this->_error)) {
return $this->_error;
}
}
}
Class DBFactory.php
class DBFactory {
private $_dbh;
public function __construct(DB $db) {
$this->_dbh = $db;
}
public function Create() {
return $this->_dbh->Connect();
}
}
Class DBInstance.php
class DBInstance {
private static $_dbinstance;
public function __construct(DBFactory $dbfactory) {
if (!isset(self::$_dbinstance)) {
self::$_dbinstance = $dbfactory->Create();
}
}
public function getDbInstance() {
return self::$_dbinstance;
}
}
Your code seems to do what you want it to.. but maybe we can use less object instantiation using inheritance and maybe we can avoid static properties in instanciated classes.
Also in regard to using a pattern of dependency injection that is able to handle multiple connections, but support using a single instance of it. exemple first, classes after
$params = array
('host'=>'localhost',
'db'=>'ice',
'user'=>'kopitar',
'pass'=>'topnet',
'charset'=>'utf8'); // passing the charset explicitely is great
$handle = new handle($params);
$db = $handle->getInstance();
we can either pass the $db to our functions
$location_names = Location::getLocationNames($db);
or the whole $handle. as long as $handle is not reconstructed, it will always return the same database connection.
$location_names = Location::getLocationNames($handle);
if I want to reconstruct I need the whole $handle
$handle->__construct(/* params but with another database infos */);
$db2 = $handle->getInstance();
As for the classes, I think we want the params to arrive from the instanciated class, so we can change them later.
class db {
function __construct($params) {
foreach ($params as $param => $value) {
$this->{$param} = $value; // assigns the connections infos
}
}
protected function connect() {
$dsn = 'mysql:host='.$this->host.';dbname='.$this->db.';charset='.$this->charset;
return new PDO($dsn,$this->user,$this->pass);
}
}
the factory creates a connection from params and passes it to something else, good factory
class factory extends db {
protected function create() {
return $this->connect();
}
}
now we want to have our object to keep it's connection as long as we do not rebuild it. so we give it to instance
class instance extends factory {
function instantiate() {
$this->instance = $this->create();
}
}
and last but not least, our handle which returns the instance. it could be in instance class.....................
but I feel like having four and find no real reason not to.
class handle extends instance {
function __construct($params) {
db::__construct($params);
$this->instantiate(); // when we construct a handle, we assign an instance to the instance property
}
function getInstance() {
return $this->instance;
}
}
KISS
Don't make things more complex than they are, of course this is just my opinion, but as I see it you are building a complex solution for a problem that someone else says might exist is some cases.
Php is not multi threaded so there goes one of the biggest arguments overboard. (in very rare-occasions it might be)
I'm using singletons for my database connections for about 15 years now and never ever had a problem with them, I do play around with different connections having one singleton handle several connection instances, but whatever... it works great and everyone that looks at the code.. understands it directly.
I'm not using globals because they can be overwritten and are kind of hard to predict (when it holds the correct object, and when/why they don't)
Use OOP to make your code cleaner, easier to work with and more flexible.
Don't use it to fix problems that aren't there and make your code more complex because others tell you to.
An very simple example of a db-connection singleton class handling several different connections.
class singleton{
private static $_instances=array();
public static function getInstance($connectionName){
if(!isset(self::$_instance[$connectionName]){
self::$_instance[$connectionName]=self::_getConnection($connectionName);
}
return self::$_instance[$connectionName];
}
}
just my 2 cents
Why do you have a factory if you have a singleton? This is needless.
This is a never-ending debate, but I'm advocate of do not use singletons for database connections.
As far as in most applications, you have only one data channel, you can consider your database connection unique, but this might not be always true.
In deed, the effort made to create a singleton database connection is even bigger than just create a regular one.
Also, your class DB is not configurable, therefore, you need to change it when your connection parameters change. And I think DB is a very bad name for this.
I'd rather call this Storage and do something like:
inteface Storage {
public function insert($container, array $data);
public function update($container, array $data, $where);
public function delete($container, $where);
public function getAll($container);
public function getOne($identifier);
}
final class PdoStorage implements Storage {
private $dbh;
private $dsn;
private $user;
private $pswd;
public function __construct($dsn, $user, $pswd) {
$this->dsn = $dsn;
$this->user = $user;
$this->pswd = $pswd;
}
// Lazy Initialization
private function connect() {
if ($this->dbh === null)
$this->dbh = new PDO($this->dsn, $this->user, $this->pswd);
}
public function insert($container, array $data) {
$this->connect();
// ... omitted for brevity
}
}
Now, when you need a database storage, you do:
$someObj = new SomeClass(new PdoStorage(...));
Now you might be wondering if you will need to create an PdoStorage for each single object that depends on it.
The answer is: no!
Now you can use a factory to simplify your life.
class SomeFactory {
private $defaultStorage;
public function __construct(Storage $storage) {
$this->defaultStorage = $storage;
}
public function create($type) {
// Somehow fetches the correct class to instantiate and put it into $class variable , for example... and then
return new $class($this->defaultStorage); // Or you'd better do this with reflection
}
}
$factory = new SomeFactory(new PdoStorage(...));
$factory->create('SomeClass');
This way, you can have just one database connector or more if you need.

Is extending classes good practice?

I have a PDO connection in my database class and recently I have been using this as an extension for other classes i.e. class Users extends Database this allows me to always keep a Database connection without having to have a function in my Users class.
However somebody pointed out that I shouldn't be doing this as its bad practice, why exactly is this bad practice? And how can I connect to my database class in my user class without extending?
Currently I have the call to the database inside my viewall() function I tried to put this in a __construct() function however it insisted on having parameters
I've tried the below code however I get the error message as follows:
Fatal error: Call to undefined method Database::prepare() in E:\xampp\htdocs\attendance\class.Register.php on line 13
Any ideas on how I can call on my database?
This is my code:
class.Connect.php
<?php
// Database connection PDO
class Database {
public function __construct() {
// Connection information
$host = 'localhost';
$dbname = 'attendance';
$user = 'root';
$pass = '';
// Attempt DB connection
try
{
$this->pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//echo 'Successfully connected to the database!';
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function __destruct()
{
// Disconnect from DB
$this->pdo = null;
//echo 'Successfully disconnected from the database!';
}
}
?>
class.Register.php
<?php
require 'class.Connect.php';
class Register {
public function viewall() {
$pdo = new Database();
$stmt = $pdo->prepare('SELECT * FROM users');
$stmt->execute();
$stmt->fetch();
}
}
$run = new Register();
$run->viewall();
?>
Simple rule of thumb: if a class extends another, then that class is that parent class (only slightly altered or extended). You can pass this child class instead of the parent class. Example:
class Foo { }
class Bar extends Foo { }
function baz(Foo $foo) { }
baz(new Bar);
This works, baz() expects a Foo but also accepts a Bar, because Bar is a Foo.
Now, is your Users a Database? No. Your users are not a database. Your users use a database. If at all, you should use composition:
class User {
protected $database;
public function __construct(Database $database) {
$this->database = $database;
}
}
A class should be what its responsibilities are. The responsibility of a user management class is to manage user data. Part of that may involve talking to a database, but that doesn't mean the user management class is a database. If User extends Database, that means it can do everything the Database class can do (and more). That means you could use the User class everywhere instead of the Database class, and that doesn't make any sense. Keep responsibilities separate.
Now, it's still debatable whether that is the right structure or not, but it goes into the right direction. But you may really want to have a User class, which represents one user. You then have a UserManager or UserORM or UserStorage or whatever, which is concerned with retrieving and storing User objects in a database. This class in turn uses a Database to do just that. That keeps responsibilities clear and separated. The User class represents user data, the Database class interacts with the database, the UserORM/Manager/whatever in the middle negotiates between the two.
There may be several ways to connect to a database such that you have a connection everywhere in your application. For a good practice, you can do it easily by using another class which can handle your datbase operations and you extend all your classes which require db operations from that class.
First change your Database class a little and pass the arguments for database connection as below :
<?php
// Database connection PDO
class Database {
public function __construct($host, $dbname, $user, $pass) {
// Connection information
// Attempt DB connection
try
{
$this->pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//echo 'Successfully connected to the database!';
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function __destruct()
{
// Disconnect from DB
$this->pdo = null;
//echo 'Successfully disconnected from the database!';
}
}
?>
Now create another class lets call it ObjectModel as below
class ObjectModel
{
protected $db
public function __construct()
{
$this->db = new Database($host, $dbname, $user, $pass) //ofcourse you can get the db connections details and database name from a config file
}
// you can have more db operations functions like insert, update, delete etc
}
SO the ObjectModel class will be handling all your CRUDs and other db operations and running queries also. Now if you want to use the $db object, you can use it directly in the ObjectModel class and also in child classes of OBjectModel as below:
class Users extends ObjectModel
{
public function getUsers()
{
//$this->db-> whatever operation you want to do you can do it using this db object
}
}
Remember that the ObjectModel has an object of the Database class called $db, so if your Database class is using PDO, then your ObjectModel $db object will have all those operations ie, using PDO.
I hope this will help for you also, as i am using such ObjectModel class for my classes and it saves me a lot of time to write codes again and again :) .
Happy Coding ;)
Is extending classes good practice?
Well, yes, if you do it right and for the right reason.
The concept of inheritance (class extensions) in object-oriented programming is working like the same as if you had those objects in real world.
In real world when you use the world Car, then by convention you usually mean all the cars and you consider common attributes in it, for example, wheels, engine, steering, throttle, brake etc.
but there are some cars that have those attributes and some additional too, for example a Fire Truck Car also has some extra attributes as a ladder attached, some tubes for water throwing etc.
The same could be considered for the "behavior" of some objects, for example, a car can move, and by that we mean you have wheels rotation on the road in order to move (modeled by Car move method).
Also, a firetruck may have an extended behavior, for example can move up and down the ladder it has. This can be modelled by having the method moveLadder() in the FireTruckCar class.
If you wanted to represent these concepts in PHP classes (OOP), you could do:
class Car {
protected $wheels;
protected $engine;
//Rest attributes of Car.
public function __construct($wheels, $engine) {
$this->wheels = $wheels;
$this->engine = $engine;
//Initialize more attributes.
}
function move(){
$this->wheels->rotate();
}
//.....
}
class FireTruckCar extends car{
//Additional Attributes.
//The attributes of Car class belong to this
//one too and are accessible as private.
protected $ladder;
protected $tubes;
public function __construct($wheels, $engine, $ladder, $tubes) {
//Call the parent constructor, to initialize parent attributes
parent::__construct($wheels, $engine);
$this->ladder = $ladder;
$this->tubes = $tubes;
}
function moveLadder($direction){
$this->ladder->move($direction);
}
//...
}
Of course, there are many additional concepts in inheritance and generally OOP such as method overloading/overriding, abstract classed etc., but I am not goind to explain about them here as the point will be missed.I suggest you search for Object Oriented Programming Principles though and learn about them well.

Is it okay to pass a class object to another class? PHP

I am coding my first object factory, and I am wondering if there any any drawbacks to passing one object into another when creating the second object, and then saving the first object within the second for use later?
Example:
class main
{
public $connection = array();
// various other useful functions that should be loaded on every page here
// these other functions would be convenient to have avail for
// new objects in different classes
function dbconnect($db) {
if(!isset($this->connection[$db])) {
switch($db) {
case "users":
$connection = #mysql_connect(info,info,info);
$db_select = #mysql_select_db(info,$connection);
$this->connection[$db] = $connection;
break;
case "ads":
$connection = mysql_connect(info,info,info);
$db_select = mysql_select_db(info,$connection);
$this->connection[$db] = $connection;
break;
default:
die($db . " is not a recognized database.");
break;
}
}
return $this->connection[$db];
}
// note how i pass $this into the new object in this function
function create($class,$params=null) {
if(!class_exists($class) && !$this->load($class)) {
die($class . " is not a recognized class.");
}else{
return new $class($this,$params);
}
}
function load($file) {
$file = $_SERVER['DOCUMENT_ROOT'] . "/classes/" . $file . ".class.php";
if(file_exists($file)) {
return require_once($file);
}else{
return false;
}
}
}
class secondary {
private $connection;
private $mainObj;
private $params;
function __construct($mainObj,$params) {
$this->mainObj = $mainObj;
$this->params = $params;
$this->connection = $mainObj->dbconnect('users');
}
}
As you see here, any class created by the factory conveniently has the ability to connect to the MySQL db if the class requires it (and other common/useful functions) ... without having to use globals, or pass many things in.
Is this a stable way? I am new, and could use some good theory/schooling on why this is wrong - if it is.
Yes, it is a pretty stable way. But I would like to see type hinting in the methods taking outer instances as parameters, which would make your classes typed stronger.
Example;
class Alob {
public function aMethod(**Blob** $outerObject) {
...
}
}
class Blob {
...
}
This will throw a fatal error if Alob::aMethod() is called with another type than Blob.
I would also like to see more accessor keywords for defining visibility, hide your class privates with 'private' and so on.
Definitely nothing wrong with object passing. If you have a ClassB object that needs an instantiated object of ClassA in order to function, then your only options are to create that ClassA object inside ClassB, or to pass ClassA in.
If the ClassA object is likely to be used by multiple ClassB objects, like in your example, then passing the ClassA (ie. Database connection object) around is actually more efficient than the alternative, which would involve a lot of duplicate objects being created inside each class.
Since PHP5 automatically passes objects by reference, setting up a reference inside your secondary class to $mainObj is actually very efficient.
One this you'll have to be careful with, with that solution of keeping an object accessing the DB (which is not bad ; you should read about the "Dependancy injection" pattern, btw), is to not disconnect from the DB as long as you still need to be able to access it
(Yeah, seems pretty logical ^^ )
What I mean is it might become easy to forget that some object somewhere needs the DB connection not to be closed.
Easy way would be to never disconnect -- PHP will automatically close the connection to the DB server at the end of the script, anyway.
Not only is this ok, but it's actually one of the cornerstones of OOP, and it's called aggregation

Problems with parent / inheritance in PHP

EDIT: I got this working now. I have updated the code:
I've looked at a few examples in here, and they all look logical. But I can't get it to work. I have a class that extends my Data Access Layer (DAL). I would like to call parent class to retrieve DB results. What am I doig wrong?
DAL class
class DAL {
protected $username; // the username for db connect
protected $pwd; // the pwd to use when connecting
protected $host; // the host to which one connects
protected $dbname; // the db to select
public $conn; // reference to the db link resource
public $db; // result of db_select
public $query_result; // the stored result of the last query you ran
public function __construct()
{
$this->username = "";
$this->pwd = "";
$this->host = "";
$this->dbname = "";
}
public function connect()
{
/* connects to DB here */
}
private function query($sql)
{
/* Executes the query here and stores the result in $this->query_result */
}
public function getAllCountries()
{
$sql ="
SELECT id, name
FROM country";
//Process query
$this->query($sql);
if($this->query_result)
return $this->query_result;
}
}
And this is my other class
class myOtherClass extends DAL{
public function __construct() {
parent::__construct();
parent::connect();
}
public function getCountryListBox()
{
$result = parent::getAllCountries();
if($result)
{
$selectbox = "<select id='countryListBox' name='countryListBox'>";
while ($row = mysql_fetch_array($result))
{
$selectbox .= "<option value='".($row['id'])."'>".($row['name'])."</option>";
}
$selectbox .= "</select>";
}
else
$selectbox = "Countries could not be retrievd from database.";
return $selectbox;
}
}
This is the code in my template:
$sl = new myOtherClass();
echo '<form id="label_data_form">';
$sl->getCountryListBox();
echo '</form>';
The difference between these:
// $result = parent::getAllCountries(); // Like this
$result = this->getAllCountries(); // Or like this?
.. is probably best explained here:
class SuperFoo {
function fubar () {
echo "superfoo!";
}
function fuz () {
echo "superfuz!";
}
}
class SubBar extends SuperFoo {
function fubar() {
echo "subbar!";
}
function demonstrate() {
$this->fubar(); // "subbar!"
parent::fubar(); // "superfoo!"
$this->fuz(); // "superfuz!"
parent::fuz(); // "superfuz!"
}
}
$s = new SubBar();
$s->demonstrate();
(okay, maybe not best explained..)
Unless you particularly want the behaviour defined in the parent class, I'd always use $this->... since then you have the option of altering the behaviour if needed.
The MySQL error seems to be caused by a problem with your SQL - the class inheritance looks to be working fine.
if your class 'myOtherClass' does not implement the 'getAllCountries()' method, the following should work:
$result = $this->getAllCountries();
do not forget the $-sign before 'this'!
for the part you want to fetch list of all countries:
// $result = parent::getAllCountries(); // Like this
$result = $this->getAllCountries(); // Or like this?
the second line is correct. getAllCountries() is a method of your object, because it is inherited from your parent class. so you do not need to call the parent method. one place that you would want to call class parent's methods are in methods where you are overwriting the method.
anyways I suggest you define your properties in your DAL class as 'protected' instead of 'private'. because when you define them 'private', they can not be inherited.
so in your DAL class:
protected $username; // the username for db connect
protected $pwd; // the pwd to use when connecting
protected $host; // the host to which one connects
protected $dbname; // the db to select
you should define those properties as private, only if you do not want them to be inherited. I think your new object needs these info to connect to database.
Steven, let me draw your attention to other things, that are incorrect in your sample despite being syntactically correct. The major issue here is responsibility separation: Data Access Layer should only act as a general purpose data retrieving/storing utility class. Any additional logic should be moved outside this class.
Database connection handling should not be part of DAL. Ideal solution is to pass the db object in constructor, so the DAL operates on the connection configured somewhere else. This is called Dependency Injection and is generally regarded a good thing.
Method getAllCountries is way too specific for general purpose library. Should be replaced with getAll returning all records from current table. Table name should be passed in constructor or defined in subclass, so that every table has its corresponding DAL object.
*Method getCountryListBox generates some HTML output, which is not part of responsibility of DAL library. DAL should only return raw data.
It is worth keeping things separated, so you can reuse them in the future. Adding too many problem specific extension blurs the responsibility of a class. Main objectives of a class should be very narrow-minded, so classes can specialise in doing different things. Cooperation between several highly specialised classes should be the way of delivering complex functionality.
Generally speaking, you would use
$result = $this->getAllCountries();
(Note the **$**this rather than this!)
When calling getAllCountries from anywhere other than the getAllCountries method itself. This will ensure that if you were to override it, the overriden method would be called.
Inside the method, if you wanted to call the base class version, you would need to disambiguate the call with parent::
parent::getAllCountries();
Note you can use this form of method call within any method, but I would argue that it would be bad practice to do this by default, since it denies you the opportunity to override that method later on.
Answer to you edit?
Another typo:
but I guess you have this correct (-> in stead of -) in your code.
Are you sure the 'myOtherClass' is the 'storelocator' class?
Are you sure that storelocator is an instance of MyOtherClass? Because the method you are calling, getCountryListBox is defined in MyOtherClass, and the error complains about an undefined methods getCountryListBox...
<?php $sl = new storelocator(); ?>
<form id="label_data_form">
<?php $sl->getCountryListBox(); ?>
Update
You should add error handling logic inside query() and getAllCountries().
this->getAllCountries(); should be fine, provided that it was a type and you actually meant $this, ie with a dollar.
I'd also like to point out missing logic in getAllCountries() for cases when the query() method is returning nothing and thus $this->query_result holds nothing. getAllCountries() should return something like an empty array, because there may be cases when there's not country in the DB. You want to be able to handle that.

Categories