src/ORM/DataQuery.php
protected function joinManyManyRelationship(
        $relationClass,
        $parentClass,
        $componentClass,
        $parentField,
        $componentField,
        $relationClassOrTable,
        $parentPrefix = null,
        $componentPrefix = null
    ) {
        $schema = DataObject::getSchema();

        if (class_exists($relationClassOrTable)) {
            $relationClassOrTable = $schema->tableName($relationClassOrTable);
        }

        // Check if already joined to component alias (skip join table for the check)
        $componentBaseClass = $schema->baseDataClass($componentClass);
        $componentBaseTable = $schema->tableName($componentBaseClass);
        $componentAliasedTable = $componentPrefix . $componentBaseTable;
        if ($this->query->isJoinedTo($componentAliasedTable)) {
            return;
        }

        // Join parent class to join table
        $relationAliasedTable = $componentPrefix . $relationClassOrTable;
        $parentIDColumn = $schema->sqlColumnForField($parentClass, 'ID', $parentPrefix);
        $this->query->addLeftJoin(
            $relationClassOrTable,
            "\"{$relationAliasedTable}\".\"{$parentField}\" = {$parentIDColumn}",
            $relationAliasedTable
        );

        // Join on base table of component class
        $componentIDColumn = $schema->sqlColumnForField($componentBaseClass, 'ID', $componentPrefix);
            $this->query->addLeftJoin(
                $componentBaseTable,
                "\"{$relationAliasedTable}\".\"{$componentField}\" = {$componentIDColumn}",
                $componentAliasedTable
            );

        // Add join clause to the component's ancestry classes so that the search filter could search on
        // its ancestor fields.
        $ancestry = ClassInfo::ancestry($componentClass, true);
        $ancestry = array_reverse($ancestry);
        foreach ($ancestry as $ancestor) {
            $ancestorTable = $schema->tableName($ancestor);
            if ($ancestorTable !== $componentBaseTable) {
                $ancestorTableAliased = $componentPrefix . $ancestorTable;
                $this->query->addLeftJoin(
                    $ancestorTable,
                    "{$componentIDColumn} = \"{$ancestorTableAliased}\".\"ID\"",
                    $ancestorTableAliased
                );
            }
        }
    }
protected function joinManyManyRelationship(
        $relationClass,
        $parentClass,
        $componentClass,
        $parentField,
        $componentField,
        $relationClassOrTable,
        $parentPrefix = null,
        $componentPrefix = null
    ) {
        $schema = DataObject::getSchema();

        if (class_exists($relationClassOrTable)) {
            $relationClassOrTable = $schema->tableName($relationClassOrTable);
        }

        // Check if already joined to component alias (skip join table for the check)
        $componentBaseClass = $schema->baseDataClass($componentClass);
        $componentBaseTable = $schema->tableName($componentBaseClass);
        $componentAliasedTable = $componentPrefix . $componentBaseTable;
        if ($this->query->isJoinedTo($componentAliasedTable)) {
            return;
        }

        // Join parent class to join table
        $relationAliasedTable = $componentPrefix . $relationClassOrTable;
        $parentIDColumn = $schema->sqlColumnForField($parentClass, 'ID', $parentPrefix);
        $this->query->addLeftJoin(
            $relationClassOrTable,
            "\"{$relationAliasedTable}\".\"{$parentField}\" = {$parentIDColumn}",
            $relationAliasedTable
        );

        // Join on base table of component class
        $componentIDColumn = $schema->sqlColumnForField($componentBaseClass, 'ID', $componentPrefix);
            $this->query->addLeftJoin(
                $componentBaseTable,
                "\"{$relationAliasedTable}\".\"{$componentField}\" = {$componentIDColumn}",
                $componentAliasedTable
            );

        // Add join clause to the component's ancestry classes so that the search filter could search on
        // its ancestor fields.
        $ancestry = ClassInfo::ancestry($componentClass, true);
        $ancestry = array_reverse($ancestry);
        foreach ($ancestry as $ancestor) {
            $ancestorTable = $schema->tableName($ancestor);
            if ($ancestorTable !== $componentBaseTable) {
                $ancestorTableAliased = $componentPrefix . $ancestorTable;
                $this->query->addLeftJoin(
                    $ancestorTable,
                    "{$componentIDColumn} = \"{$ancestorTableAliased}\".\"ID\"",
                    $ancestorTableAliased
                );
            }
        }
    }
protected function joinManyManyRelationship ( $ relationClass , $ parentClass , $ componentClass , $ parentField , $ componentField , $ relationClassOrTable , $ parentPrefix = null , $ componentPrefix = null ) { $ schema = DataObject :: getSchema ( ) ; if ( class_exists ( $ relationClassOrTable ) ) { $ relationClassOrTable = $ schema -> tableName ( $ relationClassOrTable ) ; } // Check if already joined to component alias (skip join table for the check) $ componentBaseClass = $ schema -> baseDataClass ( $ componentClass ) ; $ componentBaseTable = $ schema -> tableName ( $ componentBaseClass ) ; $ componentAliasedTable = $ componentPrefix . $ componentBaseTable ; if ( $ this -> query -> isJoinedTo ( $ componentAliasedTable ) ) { return ; } // Join parent class to join table $ relationAliasedTable = $ componentPrefix . $ relationClassOrTable ; $ parentIDColumn = $ schema -> sqlColumnForField ( $ parentClass , 'ID' , $ parentPrefix ) ; $ this -> query -> addLeftJoin ( $ relationClassOrTable , "\"{$relationAliasedTable}\".\"{$parentField}\" = {$parentIDColumn}" , $ relationAliasedTable ) ; // Join on base table of component class $ componentIDColumn = $ schema -> sqlColumnForField ( $ componentBaseClass , 'ID' , $ componentPrefix ) ; $ this -> query -> addLeftJoin ( $ componentBaseTable , "\"{$relationAliasedTable}\".\"{$componentField}\" = {$componentIDColumn}" , $ componentAliasedTable ) ; // Add join clause to the component's ancestry classes so that the search filter could search on // its ancestor fields. $ ancestry = ClassInfo :: ancestry ( $ componentClass , true ) ; $ ancestry = array_reverse ( $ ancestry ) ; foreach ( $ ancestry as $ ancestor ) { $ ancestorTable = $ schema -> tableName ( $ ancestor ) ; if ( $ ancestorTable !== $ componentBaseTable ) { $ ancestorTableAliased = $ componentPrefix . $ ancestorTable ; $ this -> query -> addLeftJoin ( $ ancestorTable , "{$componentIDColumn} = \"{$ancestorTableAliased}\".\"ID\"" , $ ancestorTableAliased ) ; } } }
Join table via many_many relationship

@param string $relationClass
@param string $parentClass
@param string $componentClass
@param string $parentField
@param string $componentField
@param string $relationClassOrTable Name of relation table
@param string $parentPrefix Table prefix for parent class
@param string $componentPrefix Table prefix to use for both joined and mapping table
Join table via many_many relationship