Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calculate product variants based on option groups and options

I am writing an ecommerce site, and need a good way to calculate product variations. The Site has products, products can have many option groups, option groups can have many options.

So a Tshirt Product has 3 option groups and options:

Size: Small, Medium, Large,

Color: Red, Blue, Yellow, Black,

Material: Cotton, Nylon,

which creates: small red cotton, small red nylon, small blue cotton, small blue nylon, ... so on and so forth

I know that the script below works, but also that it can be optimized. Can anyone furnish a better working example of this? It should be possible using recursion as well... but I'm hitting a mental block.

    if(count($option_groups) > 1)
    {
        // start the variants up
        foreach($option_groups[0]->get_options() as $option)
        {
            $variants[] = array($option);
        }

        // go through every other option group to make combos
        for($x = 1; $x < count($option_groups); $x++)
        {
            $combos = array();

            foreach($variants as $variant)
            {
                $new = array();
                foreach($option_groups[$x]->get_options() as $option)
                {
                    $tmp        = $variant;
                    $tmp[]  = $option;
                    $new[]  = $tmp;
                }
                $combos[] = $new;
            }
            $variants = array();
            foreach($combos as $combo)
            {
                foreach($combo as $tmp)
                {
                    $variants[] = $tmp;
                }
            }
        }
    }

This isn't super time sensitive, but I'd like to have a more maintainable chunk of code, this is pretty gross.

Also does this problem (I feel like it isn't an original problem, many carts do this) have a name? I wasn't pulling anything up on google for this problem.

EDIT This is what I ended up with, its based off of profitphp's solution, but maintains my objects instead of giving me the options per variant concatenated as a string. All thanks to Profitphp!

private function _possible_combos($groups, $prefix = array())
{
    $result = array();
    $group  = array_shift($groups);
    foreach($group->get_options() as $selected)
    {
        if($groups)
        {
            $tmp            = $prefix;
            $tmp[]      = $selected;
          $result = array_merge($result, $this->_possible_combos($groups, $tmp));
        }
        else
        {
            $tmp            = $prefix;
            $tmp[]      = $selected;
          $result[] = $tmp; 
        }
    }

    return $result;
}
like image 711
Francis Yaconiello Avatar asked Sep 06 '11 17:09

Francis Yaconiello


1 Answers

This should do the trick:

<?

$data[]=array('shirt');
$data[]=array('red','yellow','black');
$data[]=array('small','medium','large');

$combos=possible_combos($data);

//calculate all the possible comobos creatable from a given choices array
function possible_combos($groups, $prefix='') {
    $result = array();
    $group = array_shift($groups);
    foreach($group as $selected) {
        if($groups) {
            $result = array_merge($result, possible_combos($groups, $prefix . $selected. ' '));
        } else {
            $result[] = $prefix . $selected;
        }
    }
    return $result;
}

echo count($combos) . "\n";
print_r($combos);

Tested: http://www.ideone.com/NZE5S

like image 119
profitphp Avatar answered Oct 10 '22 09:10

profitphp