Question

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.

Update

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
    );
}
Was it helpful?

Solution

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top