I'm just getting started with dependency injection and I have immediately hit a problem: I have two classes that depend on each other.
The classes are Basket and Shipping. In my Basket class I have the following relevant methods:
public function totalShipping()
{
return $this->_shipping->rate();
}
public function grandTotal()
{
return $this->totalProductsPrice() + $this->totalShipping();
}
public function totalWeight()
{
$weight = 0;
$products = $this->listProducts();
foreach ($products as $product) {
$weight += $product['product_weight'];
}
return ($weight == '') ? 0 : $weight;
}
$this->_shipping
is an instance of the Shipping class
In my Shipping class I have the following relevant methods:
public function rate()
{
if (isset($_SESSION['shipping']['method_id'])) {
$methodId = $_SESSION['shipping']['method_id'];
return $this->_rates[$methodId]['Shipping Price'];
}
// Method not set
return NULL;
}
// Available Methods depend on country and the total weight of products added to the customer's basket. E.g. USA and over 10kg
public function listAvailableMethods()
{
$rates = array();
if (isset($_SESSION['customer']['shipping_address']['country_code'])) {
foreach ($this->_rates as $method_id => $rate) {
if (($_SESSION['customer']['shipping_address']['country_code'] == $rate['Country']) && ($this->_basket->totalWeight() > $rate['Weight From']) && ($this->_basket->totalWeight() < $rate['Weight To'])) {
$rates[$method_id] = $rate;
}
}
}
return $rates;
}
$this->_basket
is an instance of the Basket class.
I am totally clueless as to how to resolve this circular dependency. Thank you for your help in advance.
In my Shipping Class I also have this method:
public function setMethod($method_id)
{
// A check to make sure that the method_id is one of the provided methods
if ( !array_key_exists($method_id, $this->listAvailableMethods()) ) return false;
$_SESSION['shipping'] = array(
'method_id' => $method_id
);
}
I have ended up renaming Shipping
to Shipping_Methods
and I have created a new class called Customer_Shipping_Methods
. Essentially Customer_Shipping_Methods
could be part of the Basket
class but I'd rather keep it separate.
@RyanLaBarre was totally right. I was essentially mixing methods that should have been in the Basket
Class with methods in my Shipping_Methods
class. Shipping_Methods
should have only contained general shipping data methods which were not specific to the current session.
I think what threw me, was that Shipping_Methods
sources its data from a csv file rather than a database table. Once I started seeing Shipping_Methods
as just another table, it all clicked in my mind.
@rdlowrey that is very good advice. I will be putting my session globals into my controllers immediately!