Web Hosting Talk







View Full Version : PHP CLass inheritance problem: Same functions, Diff column name


grabmail
03-01-2006, 03:17 PM
Class Apple {

function delete() {
delete from table where appleid = $appleid;
}

}

Class Orange {

function delete() {
delete from table where orangeid = $orangeid;
}

}


As you can see, the only diff is the column name (appleid vs orangeid) and the $appleid vs $orangeid.

I wish to create a parent class which orange and apple can extend such as:


Class Parent {

function delete() {
delete from table where ? = $?;
}

}


Problem is: what do i enter in the ?

I cannot put appleid or orangeid as the column name.

Right now, i'm doing a very crude way.


Class Orange extends {

public __construct() {
$this->columnName = 'orangeid';
}

public function setOrangeid($orangeid) { $this->setColumnid($orangeid); }

}

Class Parent {

protected $columnName, $columnid;

public function setColumnid($columnid) { $this->columnid = $columnid; }

function delete() {
delete from table where $this->columnName = $this->columnid;
}

}


As you can see, it's damn ugly and hard to maintain in the future.

"delete from table where $this->columnName = $this->columnid;"

Who would understand that?

Is there a better way?

Dan L
03-01-2006, 04:47 PM
I'd just do:

<?php
class fruit {
var $dbHandler;
function fruit($dbHandler) {
$this->dbHandler = $dbHandler;
}
function delete($columnName,$columnId) {
$this->dbHandler->doQuery("DELETE FROM `table`
WHERE `$columnName` = $columnId");
if(!$this->dbHandler->error()) {
echo 'The deletion was successful!';
}
}
}
?>

I'm not sure if `$columnName` works, though. At worst, you could just do

if($columnName == 'orange') {
// query for orange
} elseif...

grabmail
03-01-2006, 07:10 PM
i can't do that cos

apple has some functions that orange doesn't have.

Apple and orange may share some similarities but they are not exact.

So i chose inheritance instead.

Dan L
03-01-2006, 07:14 PM
Then pass the Fruit class to them.

class Apple {
var $fruit;
function Apple($fruit) {
$this->fruit = $fruit;
}
function eatApple() {
$this->fruit->delete('apple',55);
}
}

Burhan
03-02-2006, 01:57 AM
Aye, use composition instead of inheritence (which is what DanX is doing).

grabmail
03-02-2006, 07:53 AM
But Apple is a fruit. Apple is not MADE UP of fruit.

So shouldn't apple extends fruit?

Compositions is like:

class car {
wheel = new wheel();
door = new door();
}

Isn't it?

grabmail
03-02-2006, 08:44 AM
Ok. how would you code this?

You have a Pie class.
Now, you have an Apple Pie class and Orange Pie class.

Both classes have a bake method.

Apple Pie bake method's sql is "insert into applepies values('flour', 'black', 'lite')"

Orange Pie bake method's sql is "insert into orangepies values('sweet', 'large')"

applepie table is
----------------------------------
ingredient | color | variety

orangepie table is
----------------------------------
taste | size

As you can see, both table schemas are different. These schema may not make sense but the point i'm trying to make is that both pies IS A pie but they have different table schemas, different column names, different column count.

In this case, is it wise to inherit pie?

hiryuu
03-02-2006, 09:13 AM
When you inherit from a superclass, you're not obligated to use it's version of all of the methods. Depending on what bake does, it may be faster, cleaner, and clearer to write a separate method for it in each subclass. With different schema for them, I would probably use separate methods.

Another approach is to wrap an internal function:
protected function _delete ($table, $colName, $rowid) {
...
}

public function delete () {
$this->_delete('oTable', 'orange', $id);
}

That will also let you do other custom actions, while sharing the meat of the code.

grabmail
03-02-2006, 10:34 AM
You're right. It's probably best to use separate bake functions.

deuce868
03-02-2006, 03:32 PM
I split it up more. I have a base dataObj class that is loaded into my base DAO classes that have the delete function.

// so here I define what db table I am using for this Schedule object
class Schedule extends DataObject {
public $db_table = 'rsch_schedule'; // database we're pulling fields from
public $pk = 'ScheduleID'; // the primary key for this object

}

// then I have a ScheduleDAO that actually has an instance of the Schedule so I know the db table
require_once('dataDAO.php');
require_once('schedule.php');

class ScheduleDAO extends DataDAO {

}

// the Schedule DAO inherits the __construct and delete from the dataDAO class
// notice that this actually creates an instance of the Research object as $this->obj
// so for the rest of the class I can get the table name with:
// $this->obj->db_table
class DataDAO {

protected $debug = false;
protected $obj; // the root data object for this DAO

protected $dbConn;

public function __construct() {

// first get your dataobject
// get your class name to load
$data_obj_name = substr(get_class($this), 0, -3); // drop the DAO off the class name
$this->obj = new $data_obj_name();

$this->dbConn = dataSourceInstance::getConnection();
if ($this->debug) {
$this->dbConn->debug = true;
}
}

// so here is the actual delete function that is generic and works with any extending class
public function delete($args) {
// pass in this pk field and the value to this DAGO function
// to remove we need to get the pk out
if (isset($args[$this->obj->pk])) {
$pk_value = $args[$this->obj->pk];
} else {
die('You need to include the primary key to delete from the DAO.');
}

$sql = "DELETE FROM " . $this->obj->db_table . " WHERE " . $this->obj->pk . " = ? LIMIT 1";


$result = $this->dbConn->Execute($sql, array($pk_value));

if( $this->dbConn->Affected_Rows() != 1 ) {
// then the deletion failed
return false;
} else {
return true; // ok the delete succeeded
}
}


Notes:
The $args is actually just the $_POST array from the form I have the delete button on. There is a hidden field named with the same name as the object's $pk so in this way I don't have to first clean the $_POST before I pass it into the delete function.

The DataDAO is meant to be reused in all classes like a UserDAO class would extend DataDAO and the database would be something like 'users' and the primary key might be set to 'username'. That would be all you would have to set in the User class that extends the DataObj class. Then when you create a new instance of the UserDAO you automatically have a working Delete() function.

You can use this by doing something like:

$researchDAO = new ResearchAbstractDAO();
if($researchDAO->delete($_POST)) {
// it worked
} else {
// it didn't
}