ZF-2577: _dependentTables and _referenceMap should have class parameter


I tried to follow Coding Standard and Naming Conventions with my database models. But it all breaks when I try $paper->findPaperWriter() or $paperWriter->findParentPaper().

CREATE TABLE paper ... CREATE TABLE paper_writer ( paper_id... );

So I'd like to have

Database/Paper.php Database/Paper/Writer.php

class Database_Paper class Database_Paper_Writer

All of this would work, if I would call $paper->findDatabasePaperWriter() or $paperWriter->findParentDatabasePaperWriter(), but as you can see this is not a very good solution. I found two solutions.

  1. "class" parameter in _dependentTables and _referenceMap, that would tell ZF to look for certain class instead of trying magically resolve it. Zend/Db/Table/Row/Abstarct.php findDependentRowset() and findParentRow() should check for if there parameter has been set and use that instead of the one received as $dependentTable or $parentTable parameter.

  2. have addHelperPath() similar to Zend_View View Helper


Quick test with Zend/Db/Table/Row/Abstract.php findDependentRowset() seems to work just fine!

        $dependapleTables = $this->_getTable()->getDependentTables();
        if (is_array($dependapleTables[$dependentTable])) {

            $dependentTable = new $dependapleTables[$dependentTable]['class'](array('db' => $db));
        } elseif (is_string($dependentTable)) {

Apparently I don't know how to use comment markup on here, sorry about that.

After using my fix for a while I noticed some problems with Parent magic methods. I noticed, that there's a lot of code that would require if clauses. So instead of option 1. I presented earlier I'm now leaning towards option 2. of using addDatabasePath(). Option 2 would also be backwards compatible and would ease working.

After some copy paste from Zend_View I have a working Zend_Db_Table_Abstract and Zend_Db_Table_Row_Abstract, that utilizes addDatabasePath() concept and this time it even seems to work without a problem.

I'll generate a patch of it tomorrow after cleanup.

This patch modifies Db/Table/Abstract.php and Db/Table/Row/Abstract.php adding the possibility to have prefixes for database files. I have database tables on each file so hierarchially so, that it's 1:1 to the datbase.

Example of Customer table: In bootstrap Zend_Db_Table_Abstract::addRelationshipPath('../library/Site/Db/Table', 'Site_Db_Table');

../library/Site/Db/Table/Customer.php class Site_Db_Table_Customer{}

This is a proper patch. The previous contained hardcoding from my codebase.

Perhaps the first str_replace('' could be replaced with some ZF core function?

The _addPath had a minor defunc, when it didn't check if the path already exists.

Fixed function

    private function _addPath($path, $prefix = null)
        foreach ((array) $path as $dir) {
            // attempt to strip any possible separator and
            // append the system directory separator
            $dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $dir);
            $dir = rtrim($dir, DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR)
                 . DIRECTORY_SEPARATOR;
            $params = array('prefix' => $prefix, 'dir' => $dir);

            if (!in_array($params, self::$_path)){
                // add as array with prefix and dir keys
                array_unshift(self::$_path, $params);

I think this is change is required to maintain compability with those who wont be using RelationshipPath. The main point is the code inside else.

    protected function _prepareReference(Zend_Db_Table_Abstract $dependentTable, Zend_Db_Table_Abstract $parentTable, $ruleKey)
        if (count($parentTable->getRelationshipPath() > 0) {
            foreach ($parentTable->getRelationshipPath() as $relationshipPath) {
                $parentTable = str_replace('_', '', str_replace($relationshipPath, '', get_class($parentTable)));
        } else {
            $parentTable = get_class($parentTable);

Please categorize/fix as needed.

This latest patch contains all the fixes applied against trunk.

And of course I managed to screw newest patch up a bit. Table/Row/Abstract.php line 776 is missing closing )

Otherwise it's good to go

My patches remove @ in front of Zend_Loader and thus, should to some extent solve the issue.

Reassigning to Ralph since he's the new maintainer of Zend_Db

Will evaluate within 2 weeks

Marking this as 'wont fix'. There are a couple of new components in place that would better facilitate what you are asking for. First is the module autoloader in Zend_Application. You can read about the Zend_Application_Module_Autoloader here… and here

As for the magic finder __call() method, I would tend to stay away from it: findParentClassNameByRule() in favor of the actual calls themselves: findParentRow($class ...) and findDependentRowset($class, ...)

Have a look at the new Zend_Application functionailty, i think it solves what you are looking for.