src/ORM/DataObjectSchema.php
public function getRemoteJoinField($class, $component, $type = 'has_many', &$polymorphic = false)
    {
        // Extract relation from current object
        if ($type === 'has_many') {
            $remoteClass = $this->hasManyComponent($class, $component, false);
        } else {
            $remoteClass = $this->belongsToComponent($class, $component, false);
        }

        if (empty($remoteClass)) {
            throw new Exception("Unknown $type component '$component' on class '$class'");
        }
        if (!ClassInfo::exists(strtok($remoteClass, '.'))) {
            throw new Exception(
                "Class '$remoteClass' not found, but used in $type component '$component' on class '$class'"
            );
        }

        // If presented with an explicit field name (using dot notation) then extract field name
        $remoteField = null;
        if (strpos($remoteClass, '.') !== false) {
            list($remoteClass, $remoteField) = explode('.', $remoteClass);
        }

        // Reference remote has_one to check against
        $remoteRelations = Config::inst()->get($remoteClass, 'has_one');

        // Without an explicit field name, attempt to match the first remote field
        // with the same type as the current class
        if (empty($remoteField)) {
            // look for remote has_one joins on this class or any parent classes
            $remoteRelationsMap = array_flip($remoteRelations);
            foreach (array_reverse(ClassInfo::ancestry($class)) as $ancestryClass) {
                if (array_key_exists($ancestryClass, $remoteRelationsMap)) {
                    $remoteField = $remoteRelationsMap[$ancestryClass];
                    break;
                }
            }
        }

        // In case of an indeterminate remote field show an error
        if (empty($remoteField)) {
            $polymorphic = false;
            $message = "No has_one found on class '$remoteClass'";
            if ($type == 'has_many') {
                // include a hint for has_many that is missing a has_one
                $message .= ", the has_many relation from '$class' to '$remoteClass'";
                $message .= " requires a has_one on '$remoteClass'";
            }
            throw new Exception($message);
        }

        // If given an explicit field name ensure the related class specifies this
        if (empty($remoteRelations[$remoteField])) {
            throw new Exception("Missing expected has_one named '$remoteField'
				on class '$remoteClass' referenced by $type named '$component'
				on class {$class}");
        }

        // Inspect resulting found relation
        if ($remoteRelations[$remoteField] === DataObject::class) {
            $polymorphic = true;
            return $remoteField; // Composite polymorphic field does not include 'ID' suffix
        } else {
            $polymorphic = false;
            return $remoteField . 'ID';
        }
    }
public function getRemoteJoinField($class, $component, $type = 'has_many', &$polymorphic = false)
    {
        // Extract relation from current object
        if ($type === 'has_many') {
            $remoteClass = $this->hasManyComponent($class, $component, false);
        } else {
            $remoteClass = $this->belongsToComponent($class, $component, false);
        }

        if (empty($remoteClass)) {
            throw new Exception("Unknown $type component '$component' on class '$class'");
        }
        if (!ClassInfo::exists(strtok($remoteClass, '.'))) {
            throw new Exception(
                "Class '$remoteClass' not found, but used in $type component '$component' on class '$class'"
            );
        }

        // If presented with an explicit field name (using dot notation) then extract field name
        $remoteField = null;
        if (strpos($remoteClass, '.') !== false) {
            list($remoteClass, $remoteField) = explode('.', $remoteClass);
        }

        // Reference remote has_one to check against
        $remoteRelations = Config::inst()->get($remoteClass, 'has_one');

        // Without an explicit field name, attempt to match the first remote field
        // with the same type as the current class
        if (empty($remoteField)) {
            // look for remote has_one joins on this class or any parent classes
            $remoteRelationsMap = array_flip($remoteRelations);
            foreach (array_reverse(ClassInfo::ancestry($class)) as $ancestryClass) {
                if (array_key_exists($ancestryClass, $remoteRelationsMap)) {
                    $remoteField = $remoteRelationsMap[$ancestryClass];
                    break;
                }
            }
        }

        // In case of an indeterminate remote field show an error
        if (empty($remoteField)) {
            $polymorphic = false;
            $message = "No has_one found on class '$remoteClass'";
            if ($type == 'has_many') {
                // include a hint for has_many that is missing a has_one
                $message .= ", the has_many relation from '$class' to '$remoteClass'";
                $message .= " requires a has_one on '$remoteClass'";
            }
            throw new Exception($message);
        }

        // If given an explicit field name ensure the related class specifies this
        if (empty($remoteRelations[$remoteField])) {
            throw new Exception("Missing expected has_one named '$remoteField'
				on class '$remoteClass' referenced by $type named '$component'
				on class {$class}");
        }

        // Inspect resulting found relation
        if ($remoteRelations[$remoteField] === DataObject::class) {
            $polymorphic = true;
            return $remoteField; // Composite polymorphic field does not include 'ID' suffix
        } else {
            $polymorphic = false;
            return $remoteField . 'ID';
        }
    }
public function getRemoteJoinField ( $ class , $ component , $ type = 'has_many' , & $ polymorphic = false ) { // Extract relation from current object if ( $ type === 'has_many' ) { $ remoteClass = $ this -> hasManyComponent ( $ class , $ component , false ) ; } else { $ remoteClass = $ this -> belongsToComponent ( $ class , $ component , false ) ; } if ( empty ( $ remoteClass ) ) { throw new Exception ( "Unknown $type component '$component' on class '$class'" ) ; } if ( ! ClassInfo :: exists ( strtok ( $ remoteClass , '.' ) ) ) { throw new Exception ( "Class '$remoteClass' not found, but used in $type component '$component' on class '$class'" ) ; } // If presented with an explicit field name (using dot notation) then extract field name $ remoteField = null ; if ( strpos ( $ remoteClass , '.' ) !== false ) { list ( $ remoteClass , $ remoteField ) = explode ( '.' , $ remoteClass ) ; } // Reference remote has_one to check against $ remoteRelations = Config :: inst ( ) -> get ( $ remoteClass , 'has_one' ) ; // Without an explicit field name, attempt to match the first remote field // with the same type as the current class if ( empty ( $ remoteField ) ) { // look for remote has_one joins on this class or any parent classes $ remoteRelationsMap = array_flip ( $ remoteRelations ) ; foreach ( array_reverse ( ClassInfo :: ancestry ( $ class ) ) as $ ancestryClass ) { if ( array_key_exists ( $ ancestryClass , $ remoteRelationsMap ) ) { $ remoteField = $ remoteRelationsMap [ $ ancestryClass ] ; break ; } } } // In case of an indeterminate remote field show an error if ( empty ( $ remoteField ) ) { $ polymorphic = false ; $ message = "No has_one found on class '$remoteClass'" ; if ( $ type == 'has_many' ) { // include a hint for has_many that is missing a has_one $ message .= ", the has_many relation from '$class' to '$remoteClass'" ; $ message .= " requires a has_one on '$remoteClass'" ; } throw new Exception ( $ message ) ; } // If given an explicit field name ensure the related class specifies this if ( empty ( $ remoteRelations [ $ remoteField ] ) ) { throw new Exception ( "Missing expected has_one named '$remoteField'
				on class '$remoteClass' referenced by $type named '$component'
				on class {$class}" ) ; } // Inspect resulting found relation if ( $ remoteRelations [ $ remoteField ] === DataObject :: class ) { $ polymorphic = true ; return $ remoteField ; // Composite polymorphic field does not include 'ID' suffix } else { $ polymorphic = false ; return $ remoteField . 'ID' ; } }
Tries to find the database key on another object that is used to store a
relationship to this class. If no join field can be found it defaults to 'ParentID'.

If the remote field is polymorphic then $polymorphic is set to true, and the return value
is in the form 'Relation' instead of 'RelationID', referencing the composite DBField.

@param string $class
@param string $component Name of the relation on the current object pointing to the
remote object.
@param string $type the join type - either 'has_many' or 'belongs_to'
@param boolean $polymorphic Flag set to true if the remote join field is polymorphic.

@return string
@throws Exception
Tries to find the database key on another object that is used to store a relationship to this class . If no join field can be found it defaults to ParentID .