0

I'm using the Dependency Class from this question PHP dependency class i'm using in particular the version from Paul Norman, it works almost perfectly, but i found out that the order doesn't always come out correclty

You can check the code here http://codepad.org/EBtWWn1b

The result is wrong, it should be

Loaded: Array
(
    [0] => menus
    [1] => settings
    [2] => countries
    [3] => dashboard
    [4] => languages
    [5] => modules
    [6] => users
)
Failed: Array
(
)

Do you know any way to fix it ?

Thanks !

2
  • Have you made any own research? Commented Sep 10, 2012 at 3:56
  • i have tried sorting them, but they don't come the way they need to be. i tried sorting the array $_dependencies but no luck aswell, i tried aswell searching for PHP Topological Sort function/class, the first result it find is very confuse to use imo.. Commented Sep 10, 2012 at 4:01

1 Answer 1

2

I don't know what to tell you about Paul Norman's solution, but there seems to be a bug... I tried my hand at a solution, it seems to satisfy the depencies in your example (although doesn't list them in exactly the order you wanted...)

class Dependencies
{
    private $items;
    private $depends;
    private $hasDependency;

    public function __construct()
    {
        $this->items = array();
        $this->depends = array();
        $this->hasDependency = array();
    }

    public function add($item, $dependsOn = array())
    {
        $this->items[] = $item;
        foreach ($dependsOn as $dependsOnItem)
        {
            $this->items[] = $dependsOnItem;
            $this->depends[$dependsOnItem][] = $item;
        }

        $this->items = array_unique($this->items);
        $this->hasDependency[$item] = $dependsOn;
    }

    public function getLoadOrder()
    {
        $order = array();

        $hasChanged = true;
        while (count($order) < count($this->items) && $hasChanged === true)
        {
            $hasChanged = false;
            foreach ($this->hasDependency as $item => $dependencies)
            {
                if ($this->satisfied($item, $order))
                {
                    $order[] = $item;
                    unset($this->hasDependency[$item]);
                    $hasChanged = true;
                }
            }
        }

        if (count($order) < count($this->items) && $hasChanged === false)
        {
            echo 'Impossible set of dependencies';
            return false;
        }

        return $order;
    }

    private function satisfied($item, $addedSoFar)
    {
        $dependencies = $this->hasDependency[$item];

        foreach ($dependencies as $dependency)
        {
            if (!in_array($dependency, $addedSoFar))
            {
                return false;
            }
        }

        return true;
    }
}

$deps = new Dependencies();

$deps->add('countries', array('menus', 'settings'));
$deps->add('dashboard', array('menus'));
$deps->add('languages', array('menus', 'settings'));
$deps->add('menus');
$deps->add('modules'  , array('menus'));
$deps->add('settings' , array('menus'));
$deps->add('users'    , array('menus'));

print_r($deps->getLoadOrder());
Sign up to request clarification or add additional context in comments.

4 Comments

thanks it works but i have a little issue, i removed my other two comments, just to not confuse anyone.. I changed the way the add function works, and i tried to retrieve the items that fail to sort, because of missing dependencies but it does not work properly well codepad.org/cxKifX6U the passed items are ok but the way. The crm item is never added to the failed array =\
I am sorry for the lag, but I am not clear what you mean by the "items that fail to sort". My understanding is that you just want to make sure you get to all the dependent items before the ones that depend on them. None of them should fail if there are no cycles in your dependencies.
No problem =), i managed to get what i needed working, not using this class thought, but i will use this class when installing my application. The thing is, that i have a modular system, and each module can have dependencies and dependents.. so when the system is installed i can manage the modules, like installing, uninstalling, enabling and disabled modules... the needed thing was that i needed to check if i could install a module that has dependencies, i implemented some functions in my modules class to do the needed checks and it came out preety nice =) but thanks for your class =D
Glad it helped! Nice work. Sounds like a pretty intricate system.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.