Converting an object to another class of same inheritance

I think I’ve painted myself into a corner with my application design.

Say I have an Order class, and an Ordered_product class. These include logic for reading/writing to database tables.

I also have other subclasses for example Pending_order and Pending_ordered_product, which inherit from Order and ordered_product respectively, but have slightly different read/write queries…

What I want to do is convert an object of type pending_order to order, and use the database functions of order to write to the database eg


$pending_order = new Pending_order($pendingOrderID);//initializes using info from database

$new_order = $pending_order->convertToOrder();//returns object of type Order

$new_order->writeToDB();

But I can’t think of a way to do this without the convertToOrder() function explicitly populating every single variable. Given that extra variables are likely to be added, and there are going to be a few subclasses of Order, this seems like a maintenance nightmare.

Given that Pending_order is a subclass of Order, is there a more efficient way of making this conversion? Or a more efficient way of designing the application?

I’m not even sure if this makes sense. :confused:

Thanks for that. Encapsulating any shared details into an OrderDetails object does solve a lot of the problems. Would that be called a decorator model?

Reflection is a dark forest which I’ve not had the courage to explore. Can you explain how you’d use reflection in this instance?

Reflection is not only a dark forest, it’s one without a map. The online documentation is awful. Because of that I’ll give you an example using standard (non-reflection) easy to use functions.

Before I do, can you give me the code of your two classes?

Perhaps if both of them compose a mutual object, it might be easier:

abstract class aOrder{
	protected $Details;
	function __construct(OrderDetails $Details){
		$this->setDetails($Details);
	}
	function getDetails(){
		return $this->Details;
	}
	function setDetails(OrderDetails $Details){
		$this->Details = $Details;
	}
	function getDetail($Name){
		return $this->Details->get($Name);
	}
	function setDetail($Name, $Value){
		$this->Details->set($Name, $Value);
	}
	abstract function writeToDB();
}
class OrderFactory{
	protected $Database;
	public function __construct(Database $Database){
		$this->Database = $Database;
	}
	public function getOrder($ID){
		$Data = $this->Database->getSingle('Orders', array('ID' => (int)$ID));
		if(false === $Data){
			return false;
		}
		$Details = new OrderDetails;
		$Details->setAll($Data);
		$Order = new Order($Details);
		return $Order;
	}
	public function getPendingOrder($ID){
		$Data = $this->Database->getSingle('Orders', array('ID' => (int)$ID, 'pending' => true));
		//$Data = $this->Database->getSingle('PendingOrders', array('ID' => (int)$ID)); - depends on db
		if(false === $Data){
			return false;
		}
		$Details = new OrderDetails;
		$Details->setAll($Data);
		return new PendingOrder($Details);
	}
	public function toOrder(aOrder $Order){
		$Details = $Order->getDetails();
		return new Order($Details); 
	}
	public function toPendingOrder(aOrder $Order){
		$Details = $Order->getDetails();
		return new PendingOrder($Details);
	}
        public function writeToDB(aOrder $Order){}
}
class Order extends aOrder{
}
class PendingOrder extends aOrder{
}

You would be able to use the toOrder on PendingOrder and get an identical order, etc.

Knowing how pending orders and orders are distinguished in the database would perhaps allow a better method, but the above is an example. On reflection (pun intended), I’d rather just use reflection.