• 0

[PHP] Classes and inheritance, quick questions


Question

I have a class called database, and I have several child classes, with one class for each table in my database.

My problem is, I have to pass a database link to my other classes (non-database related), and I want my other classes to be able to be able to use every single "child" database class without having to create instances of each and every table every time I want to use a class.

Any ideas?

Link to comment
Share on other sites

10 answers to this question

Recommended Posts

  • 0

Sorry, I'm a little lost, can you provide some code? :)

Something similar to...

<?php
class Database
{
	protected $rConn = null;

	public function __construct()
	{
		$this->rConn = mysql_connect(/* details */);
	}
}

class Users extends Database
{
	public function find($id)
	{
		return mysql_query($sql, $this->rConn);
	}
}
?>

?

Link to comment
Share on other sites

  • 0

Sure, although please don't laugh if it seems completely illogical :p

I have a class called database, which goes basically like this:

class database

{

private $db_user;

private $db_pass;

private $db_link

function __construct($db_user,$db_pass,$db_link)

{

$this->db_user=$db_user;

$this->db_pass=$db_user;

}

function connect()

{

.......

}

}

I have classes for each and every table in my database that look like this (html_templates is one of many, I have others such as members, member_profiles etc):

class html_templates extends database

{

private $id;

private $title;

private $html;

function load()

{

$query=mysql_query("SELECT * WHERE id = '$this->id'");

return mysql_fetch_row($query);

}

}

Obviously I have more methods and so on but just for example :)

I have many classes for content based functions, for example, class_content, which requires access to about 3 database tables. I would like to give my other classes (such as ones that fetch a selection of templates from html_templates table) access to all of my table classes, but ideally through only one class.

For example, take my class_content.php file. I would like to be able to do this:

$content = new content(new $db)

rather than

$content = new content(new $html_templates, new $site_settings, new $members)

just ask if you need any more detail :)

Link to comment
Share on other sites

  • 0

Yes :) By doing that, it means that my other classes that perform only content based operations will never have to deal with a line of SQL, as all of that is in my table classes. So, in future, if I decide to port this over to MS Access or any other database, then I can simply change my table classes without having to change my other classes and all their dependencies.

In theory, I figured that that's the best way about making a big project, but whether it is or not I don't know :p

Link to comment
Share on other sites

  • 0

Very nice thinking, and it proves you're on the right path. The best way to do this would be to create a common interface for all your potential Database.

Although very basic, it would go along the lines of...

Interface

interface IDatabase
{
	public function execute($sSQL);
}

MySQL

class MySQL implements IDatabase
{
	protected $rConn;

	public function __construct()
	{
		#connect
	}

	public function execute($sSQL)
	{
		$rResult = mysql_query($sSQL, $this->rConn);
		if(is_resource($rResult))
		{
			$aRecords = array();
			while($aRecord = mysql_fetch_assoc($rResult))
			{
				array_push($aRecords, $aRecord);
			}
			return $aRecords;
		}
	}
}

SQLite

class SQLite implements IDatabase
{
	protected $rConn;

	public function __construct()
	{
		#connect
	}

	public function execute($sSQL)
	{
		$rResult = sqlite_query($sSQL, $this->rConn);
		if(is_resource($rResult))
		{
			return sqlite_fetch_array($rResult, SQLITE_ASSOC);
		}
	}
}

User Do Hickey

class Users
{
	protected $oDatabase = null;

	public function __construct(IDatabase $oDatabase)
	{
		$this->oDatabase = $oDatabase;
	}

	public function findByID($iId)
	{
		return $this->oDatabase->query(
			sprintf(
				'SELECT id, name, email FROM users WHERE id = %d',
				$iId
			)
		);
	}
}

Usage

$oObj = new Users(new SQLite());
$oObj->findByID(5);

$oObj = new Users(new MySQL());
$oObj->findByID(5);

By using the interface, we create a contract that any object which implements it must abide by, even yourself. The Users object accepts any objects which implements the IDatabase interface, it doesn't care what any of the other methods do, or what they are called, it only wants an IDatabase compliant object.

Now, currently, every object which implements IDatabase only has to have a public method called execute that accepts a parameter called $sSQL. As this is all we know, this is all we, as the programmer can rely upon - Of course this can be changed via the interface.

So when ever we get a IDatabase object, we know we can safely call the execute method on it. Our query method returns an array of results, our Users object doesn't care how we created them, or what tables we used, it got an array of results.

Following?

Link to comment
Share on other sites

  • 0

Wow, I've never used interfaces before (knew what they were, just not a good example of a time to use one) so this is great for me :)

I've never looked at designing it from that perspective before, however I still have half of a problem:

I have a class called Content, which has many methods which take data from sometimes multiple tables. Obviously, these methods will require a reference to one of my table objects, such as html_templates and members. While I could provide these references through the constructor, things get a bit annoying when I have many tables which a class requires access too, and I end up with things like:

$obj = new Content(&$html_templates,&$members,&$member_profiles,&$more_tables....) etc, especially when I have to do the same for each and every class I use.

I was wondering if there was any way I could create one object or reference which would provide access to every single table object?

If not, no worries, that code above will still be beneficial, but it would be great if I could do this too.

Thanks! :)

Sazz

Link to comment
Share on other sites

  • 0

I know it's probably not what you want to hear, but I think you're going to have to lose all those individual table objects. As you have seen, it becomes very messy, very quickly.

As for the one object with access to all your tables, surely that is the Database object, no? ;)

If you insist on using the multiple objects->tables solution, you could use a Registry.

<?php
class Registry
{
	protected $oObjectStore;

	public function has($sImplementation)
	{
		return isset($this->oObjectStore[$sImplementation]);
	}

	public function set($sImplmentation, $oConcrete)
	{
		$this->oObjectStore[$sImplmentation] = $oConcrete;
	}

	public function get($sImplementation)
	{
		return $this->oObjectStore[$sImplementation];
	}
}

class Page
{
	protected $oRegistry;

	public function __construct(Registry $oRegistry)
	{
		$this->oRegistry = $oRegistry;
	}

	public function render()
	{
		$oTemplate = $this->oRegistry->get('ITemplate');
		/* assign data */
		return $oTemplate->render();
	}
}

$oRegistry = new Registry();
$oRegistry->set('ITemplate', new Template());
$oPage = new Page($oRegistry);
$oPage->render();
?>

You can now pre-register all your objects in the registry at run time, then pass this into an objects constructor to find the pre-assigned objects.

Link to comment
Share on other sites

  • 0

Errm, wouldn't it be a bit simpler to just declare a Database object outside the classes and use global to access the variable inside of the functions you need it in? Perhaps thats not correct object oriented programming though. :\

Link to comment
Share on other sites

  • 0
Errm, wouldn't it be a bit simpler to just declare a Database object outside the classes and use global to access the variable inside of the functions you need it in? Perhaps thats not correct object oriented programming though. :\

Spot on, whilst possible, you shouldn't do it this way.

It would hide the dependency from the API.

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.