Working with several classes - Extend or reference?

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Working with several classes - Extend or reference?

Post by StumpDK »

I think I need an advice... :)

I have a project (PHP 4) in which I have 3 different classes: Database, Validator and Authorize.

Every class have its own responsibilities, but some times, I'll need the classes to work together.

An example:

I'll check if a user have logged in. Therefore I'll use the Authorize-class. But I'll have to connect to the database to check if the user exists. And I'll have to use the Validator-class to check if the user-submitted information is correct.
So I can't create the Authorize-class by extending it from the Database-class because I'd still need the Validator to control the data handled by Validator-class.

How do I do it?
Ree
Forum Regular
Posts: 592
Joined: Fri Jun 10, 2005 1:43 am
Location: LT

Post by Ree »

My suggestion is leave them separate as they are now. In Authorize class you can create an instance of the Database class (probably in constructor) and then use it to your needs to check whatever data in the db you need. Validation object you will of course use before Authorization, and there's really no need to combine them in a single class.
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

Definitely no inheritance. The objects have different roles: use inheritance sparingly, and only when a derived class is is the same "thing" as the superclass, with a couple of extra bells and whistles.

Encapsulation does create the problem of how to get all these separate objects talking to each other. Read up as much as you can about design patterns for some ideas.
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Post by StumpDK »

So the right way to do it is this:

Code: Select all

include('database_class.php');

class Authorize{

function checkUserLogin(){

$db = new Database;

$db->dbConnect();

//Do the login check

}

}
But is this 'correct' OOP?
zwxetlp
Forum Newbie
Posts: 3
Joined: Fri Apr 15, 2005 12:44 pm

Post by zwxetlp »

The general rule I use for inheritance vs inclusion is the 'is a/has a' rule.
Use inheritance when the new class 'is a' more specific or otherwise special object of the type of the superclass, and use inclusion when the new class contains ('has a') instance of the other class.
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

StumpDK wrote:So the right way to do it is...
Yes. You might find that several objects need to use the $db object, in which case you would pass it in, probably as a constructor parameter.
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Post by StumpDK »

As a constructor parameter?
User avatar
Nathaniel
Forum Contributor
Posts: 396
Joined: Wed Aug 31, 2005 5:58 pm
Location: Arkansas, USA

Post by Nathaniel »

StumpDK wrote:As a constructor parameter?

Code: Select all

<?PHP
class Authorize
{
	var $db;

	//Class Constructor
	// Automatically called on $auth = new Authorize($db);
	function Authorize(&$db)
	{
		$this->db =& $db;
	}
}
?>
Make sense?

- Nathaniel
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Post by StumpDK »

So you create the Database-object first, and then call the constructor of the Authorize-class with a reference to the Database-object?
By doing that I only have to create one Database-object for every page, since I can use the same database-class in all other classes that needs it...
Am I right?
User avatar
sweatje
Forum Contributor
Posts: 277
Joined: Wed Jun 29, 2005 10:04 pm
Location: Iowa, USA

Post by sweatje »

StumpDK wrote:So you create the Database-object first, and then call the constructor of the Authorize-class with a reference to the Database-object?
By doing that I only have to create one Database-object for every page, since I can use the same database-class in all other classes that needs it...
Am I right?
Yep.

Since your Authorize class needs the Database Connection, it is "dependant" on the DbConn. You could just create it where needed, but this is limiting. What you have done in that case is hard code in the only possible value for the dependancy. If you want to be able to vary the dependancy, then you have three options.

a) constructor injection (you have seen an example of this already)
b) method injection- which looks like this insize the Authorize class:

Code: Select all

function setConn(&$conn) {
    $this->db =& $conn;
  }
or c) attribute injection - with public attributes:

Code: Select all

$auth =& new Authorize;
$auth->db =& $conn;
Even though the language allows it, I like to pretend my attributes are all private, therefore that leaves a or b as options, of which I tend to lean towards a.

HTH
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

I've run up against this problem recently - I find a few classes needing to be used within others on a very regular basis - typically Database, Configuration, Template.

Needing to pass these as parameters becomes difficult when every script requiring them is and of itself an object (Command pattern). Now given the number of this parameters can vary as the project progresses, and not all Commands need the same number of objects in order to operate. What are everyone's view on utilising the Singleton to access objects within other objects? I think this works fine for many single instance objects, but are there major downsides to using a similar tactic for say DB?

To explain to StumpDK...

A Singleton allows an object to be called from any other object using a static getInstance() method. For example:

Code: Select all

<?php

class FrequentlyUsed {
	
	function FrequentlyUsed() {
		
	}

	function &getInstance() {
		static $thisInstance;
		if($thisInstance == null) 
		{
			$thisInstance = new FrequentlyUsed();
		}
		return $thisInstance;
	}
}

class NeedsFrequentlyUsed {

	var $frequentlyUsed;
	
	function NeedsFrequentlyUsed() {
		$this->frequentlyUsed =& FrequentlyUsed::getInstance();
	}

	function execute() {
		$this->frequentlyUsed->method();
	}
}

?>
A singleton method re-uses the same instance of a class, i.e. it returns a reference to the whatever class it is included with - no copies.
User avatar
sweatje
Forum Contributor
Posts: 277
Joined: Wed Jun 29, 2005 10:04 pm
Location: Iowa, USA

Post by sweatje »

The Singleton pattern still exhibits on of the main problems the dependancy injection get around: you have hard coded the dependancy into the class and therefore shot yourself in the foot by not allowing polymorphism. Singletons are good for ensuring access to a common single instance without using a global variable, but they still pose subtler dangers. Use with caution.
Post Reply