/    Sign up×
Community /Pin to ProfileBookmark

help with OOP please!!

I’m new to OOP and am trying to write my first app ?

I’ve created a class which uses the PDO to establish a connection to MySQL which itself works fine:

[CODE]
class DB {
const DBHOST = ‘localhost’;
const DBNAME = ‘xxxx’;
const DBUSER = ‘root’;
const DBPASS = ‘xxxx’;

function __construct(){
try {
$pdo = new PDO(“mysql:host=”.DB::DBHOST.”;dbname=”.DB::DBNAME, DB::DBUSER, DB::DBPASS);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
return $pdo;
}
}
[/CODE]

but i now want to create another class (Property) which handles queries on the database such as INSERT, UPDATE, SELECT also using the PDO built in methods. I’m trying to make the Property class extend(?) the DB class so that only the Property class needs to be called in the client code. However, i’m having difficulty passing the PDO created in the DB class to it.

All i get is: [B]Fatal error: Call to undefined method DB:: prepare() in /home/…/class_lib.php on line 54[/B]

prepare() is method of the PDO object and it works fine if i instantiate another PDO object in my Property class, but that defeats the object of aiming towards reusable code does it not?!

This is the class where the error originates…

[CODE]
class Property{
private $dbh;
function __construct(){
$dbh = new DB();
$this->dbh = $dbh;
}

public function insertRow ($table,$field,$value){

$query = “INSERT INTO $table ($field) VALUES (?)”;
try {
$stmt = $this->dbh->prepare($query);
}
catch(PDOException $e) //IMPORTANT catch exception
{
echo $e->getMessage();
}
}
}
[/CODE]

and the client code…

[CODE]
$dbh= new Property();
$dbh->insertRow(‘property_details’,’pty_desc’,’whatever’);
[/CODE]

I’ve cut a bit of code out for sake of clarity but it irrelevant to the error.

Am i going about this in entirely the wrong fashion?!

to post a comment
PHP

7 Comments(s)

Copy linkTweet thisAlerts:
@NogDogSep 27.2009 — It looks like the immediate problem is that when you instantiate PDO, it is local to the constructor of your DB class. You could assign it to a class variable of DB, but perhaps a simpler solution would be for your DB class to [i]extend[/i] the PDO class.
[code=php]
<?php
class DB extends PDO
{
const DBHOST = 'localhost';
const DBNAME = 'test';
const DBUSER = 'root';
const DBPASS = 'xxxx';

function __construct()
{
try
{
parent::__construct(
"mysql:host=" . self::DBHOST . ";dbname=" .self::DBNAME,
self::DBUSER,
self::DBPASS
);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
}
[/code]
Copy linkTweet thisAlerts:
@pavsidauthorSep 28.2009 — Thanks NogDog, that's done it. What's the better method in terms of performance? Doing as you did above or assigning the object to a class variable?
Copy linkTweet thisAlerts:
@NogDogSep 28.2009 — I don't know what (if any) difference there would be in performance, and frankly I don't really care. I [i]suspect[/i] that the time to connect to the database is much more significant than which way you do it (though even that is likely a small fraction of a second), so the more important consideration is to make sure that you do not code your application such that you repeatedly connect/disconnect within a single script. With that in mind, I would suggest instantiating your DB object only once per script, and then passing it to those objects that need it.
[code=php]
class DB extends PDO
{
// blah blah blah
}

class Property
{
private $db;

public function __construct(DB $db)
{
$this->db = $db;
}

public function foo()
{
return $this->db->query("SELECT * FROM table");
}
}
[/code]

Sample usage:
[code=php]
$db = new DB();
$prop = new Property($db);
$result = $prop->foo();
$prop2 = new Property($db); // uses same connection
$result2 = $prop2->foo();
[/code]
Copy linkTweet thisAlerts:
@MindzaiSep 28.2009 — I also tend to use a registry object like the following to get the database object. It decouples the code a bit more than passing around database objects, which may or may not be worth the effort depending on your project:

[code=php]
class Registry {

private static $_instance;
private $_data = array();

// prevent direct creation of objects
private function __construct(){}
private function __clone(){}

public static function getInstance() {
if (empty(self::$_instance)) {
self::$_instance = new Registry;
}
return self::$_instance;
}

public function __isset($name) {
return array_key_exists($name, $this->_data);
}

public function __get($name) {
return $this->get($name);
}

public function __set($name, $value) {
return $this->_set($name, $value);
}

public function get($name) {
if (array_key_exists($name, $this->_data)) {
return $this->_data[$name];
}
return false;
}

public function set($name, $value) {
if (array_key_exists($name, $this->_data)) {
return false;
}
$this->_data[$name] = $value;
return true;
}

}
[/code]


To add something:

[code=php]Registry::getInstance()->database = new DatabaseClass;[/code]

To retrieve something:

[code=php]class Foo {
public function __construct() {
// either use and dispose....
Registry::getInstance()->database->query("SELECT foo FROM bar");
// or store for later
$this->db = Registry::getInstance()->database;
}
}[/code]
Copy linkTweet thisAlerts:
@pavsidauthorSep 28.2009 — Hi, thanks for your replies, i was only asking about the performance issues because i'm still learning about the best, and more efficient, ways to do OOP.

Mindzai, is your example also called a singleton pattern? I was going to try and implement one into my DB class as i've read they are a good way to prevent an object being created more than once.

I take it that i should persevere with this?

Thanks again both for your help
Copy linkTweet thisAlerts:
@MindzaiSep 28.2009 — Often you might find that OOP techniques are not necessarily the most efficient in terms of processor time, but generally you are only dealing with differences of fractions of a second. This is far outweighed by the organization and sanity you will often gain from an OOP approach. Generally it is best to have slightly less efficient, but much more maintainable code.

The registry class does use the singleton pattern yes. I also tend to make database classes singletons too, but in the example code I posted the registry itself actually enforces that any objects are kind-of singletons (kind-of because it doesn't stop you creating new objects, but it does stop you adding them to the registry under the same key). Obviously you don't always want that, but I find that the sort of objects I store in a registry tend to be application-wide objects such as database, registry, cache etc, and I usually don't want more than one instance of this sort of object knocking about.
Copy linkTweet thisAlerts:
@NogDogSep 28.2009 — Yes, the registry example uses the Singleton pattern. It is useful in preventing multiple instances of a class, if that is desired/required. However, before becoming too enamored of it, be sure to do a search on "[url=http://www.google.com/search?q=why+singletons+are+evil]Why singletons are evil[/url]." While they can be useful, they can also be limiting and can make both testing and code re-use problematic, plus as typically used they tend to hide code dependencies within the guts of the classes that use them instead of being obvious in their interfaces. (Imagine, for instance, that you decided to apply the singleton pattern to your DB class, and then at some point found you had a need to establish a second connection to a database, perhaps with a different database user or to a different database server.) I'm not saying to never use singletons, just to be sure you understand all the ramifications of doing so before you do.
×

Success!

Help @pavsid spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.18,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...