---
title: "Configuring Relations"
manual: "TypoGraph"
permalink: "https://docs.typo3.org/permalink/digicademy/typograph:relations"
source: "configuration/relations/index.rst"
rendered: "2026-09-18T09:10:56+00:00"
---

# Configuring Relations {#configuring-relations}

-   [Why Relations Need Configuration](https://docs.typo3.org/permalink/digicademy/typograph:why-relations-need-configuration)
-   [Relation Configuration Structure](https://docs.typo3.org/permalink/digicademy/typograph:relation-configuration-structure)
-   [Configuration Fields](https://docs.typo3.org/permalink/digicademy/typograph:configuration-fields)
-   [Storage Types](https://docs.typo3.org/permalink/digicademy/typograph:storage-types)
-   [Complete Configuration Example](https://docs.typo3.org/permalink/digicademy/typograph:complete-configuration-example)
-   [GraphQL Query Example](https://docs.typo3.org/permalink/digicademy/typograph:graphql-query-example)

When your GraphQL types reference other types (e.g., a `Taxonomy` has multiple
`Discipline` objects), you need to configure how TypoGraph should resolve these
relations from your database.

## Why Relations Need Configuration {#why-relations-need-configuration}

Unlike scalar fields (strings, integers), object-type fields require the
TypoGraph extension to:

1.  Identify which database column stores the relation reference
1.  Know which table to query for the related records
1.  Understand the storage format (single UID, comma-separated UIDs, or MM table)

Without explicit configuration, TypoGraph will log a warning and return `null`
for unconfigured relations.

## Relation Configuration Structure {#relation-configuration-structure}

Relations are configured under the `typograph.relations` key in the site
configuration, nested as `<TypeName>: <fieldName>: <config>`:

**config/sites/\<site-identifier>/config.yaml**

```yaml
typograph:
  relations:
    TypeName:
      fieldName:
        sourceField: database_column_name
        targetType: RelatedTypeName
        storageType: uid  # uid | commaSeparated | mmTable | foreignKey

        # Additional fields for mmTable storage type:
        mmTable: tx_some_mm_table
        mmSourceField: uid_local
        mmTargetField: uid_foreign
        mmSortingField: sorting

        # Additional fields for foreignKey storage type:
        foreignKeyField: column_in_target_table
```

## Configuration Fields {#configuration-fields}

| Field | Required | Default | Description |
| --- | --- | --- | --- |
| `sourceField` | No | Field name in snake_case | Database column in the source table containing the relation reference (not used for `foreignKey` type) |
| `targetType` | Yes | \<none> | GraphQL type name of the related entity (must exist in `tableMapping`) |
| `storageType` | No | `uid` | How the relation is stored: `uid`, `commaSeparated`, `mmTable`, or `foreignKey` |
| `mmTable` | For `mmTable` only | \<none> | Name of the MM (many-to-many) intermediary table |
| `mmSourceField` | For `mmTable` only | `uid_local` | Column in MM table referencing source record |
| `mmTargetField` | For `mmTable` only | `uid_foreign` | Column in MM table referencing target record |
| `mmSortingField` | For `mmTable` only | `sorting` | Column in MM table for sorting order |
| `foreignKeyField` | For `foreignKey` only | \<none> | Column in target table that references the source record UID |

## Storage Types {#storage-types}

The following variants are available for the `storageType` field.

### 1\. Single UID (`uid`) {#1-single-uid-uid}

Use when a database column contains a single UID reference.

**Database structure**

```text
tx_taxonomy table:
  uid: 1
  name: "Computer Science"
  main_discipline: 42  ← Single UID
```

**GraphQL schema**

```text
type Taxonomy {
  name: String
  mainDiscipline: Discipline
}
```

**config/sites/\<site-identifier>/config.yaml**

```yaml
typograph:
  relations:
    Taxonomy:
      mainDiscipline:
        sourceField: main_discipline
        targetType: Discipline
        storageType: uid
```

### 2\. Comma-Separated UIDs (`commaSeparated`) {#2-comma-separated-uids-commaseparated}

Use when a database column contains multiple UIDs as a comma-separated string.

**Database structure**

```text
tx_taxonomy table:
  uid: 1
  name: "Computer Science"
  disciplines: "12,45,78"  ← Comma-separated UIDs
```

**GraphQL schema**

```text
type Taxonomy {
  name: String
  disciplines: [Discipline]
}
```

**config/sites/\<site-identifier>/config.yaml**

```yaml
typograph:
  relations:
    Taxonomy:
      disciplines:
        sourceField: disciplines
        targetType: Discipline
        storageType: commaSeparated
```

### 3\. MM Table (`mmTable`) {#3-mm-table-mmtable}

Use for many-to-many relations stored via an intermediary MM table.

**Database structure**

```text
tx_expert table:
  uid: 5
  name: "Dr. Smith"

tx_expert_discipline_mm table:
  uid_local: 5      ← References expert
  uid_foreign: 12   ← References discipline
  sorting: 1

tx_discipline table:
  uid: 12
  name: "Physics"
```

**GraphQL schema**

```text
type Expert {
  name: String
  disciplines: [Discipline]
}
```

**config/sites/\<site-identifier>/config.yaml**

```yaml
typograph:
  relations:
    Expert:
      disciplines:
        targetType: Discipline
        storageType: mmTable
        mmTable: tx_expert_discipline_mm
        mmSourceField: uid_local
        mmTargetField: uid_foreign
        mmSortingField: sorting
```

### 4\. Foreign Key / Inverse Relation (`foreignKey`) {#4-foreign-key-inverse-relation-foreignkey}

Use when the target table has a foreign key column pointing back to the source
record. This handles 'sloppy MM' scenarios where multiple target records can
reference the same source record, potentially with duplicate data. While this
ideally should not happen, sometimes you may have to work with legacy databases
containing denormalized data, inverse relations where child records point to
the parent, or just with cases where somebody couldn't be bothered to set up
proper MM tables (every software project has at least one former team member
like this).

**Database structure**

```text
tx_taxonomy table:
  uid: 5
  name: "Applied Sciences"

tx_discipline table:
  uid: 1
  name: "Physics"
  discipline_taxonomy: 5  ← Foreign key pointing to taxonomy

tx_discipline table:
  uid: 2
  name: "Physics"          ← Same name, different record
  discipline_taxonomy: 5  ← Same taxonomy reference

tx_discipline table:
  uid: 3
  name: "Chemistry"
  discipline_taxonomy: 5  ← Another discipline for same taxonomy
```

**GraphQL schema**

```text
type Taxonomy {
  name: String
  disciplines: [Discipline]
}

type Discipline {
  name: String
}
```

**config/sites/\<site-identifier>/config.yaml**

```yaml
typograph:
  relations:
    Taxonomy:
      disciplines:
        targetType: Discipline
        storageType: foreignKey
        foreignKeyField: discipline_taxonomy
```

**How it works:** In this case, TypoGraph queries the target table (`tx_discipline`) with a `WHERE discipline_taxonomy = <source-uid>` query and returns all matching records (including duplicates).

## Complete Configuration Example {#complete-configuration-example}

This is a complete example with multiple relation types:

**config/sites/\<site-identifier>/config.yaml**

```yaml
typograph:

  # Schema files
  schemaFiles:
    - 'EXT:pkf_website/Resources/Private/Schemas/Query.graphql'
    - 'EXT:pkf_website/Resources/Private/Schemas/Taxonomy.graphql'
    - 'EXT:pkf_website/Resources/Private/Schemas/Discipline.graphql'
    - 'EXT:pkf_website/Resources/Private/Schemas/Expert.graphql'

  # Root elements to tables mapping
  tableMapping:
    disciplines: tx_dmdb_domain_model_discipline
    experts: tx_academy_domain_model_persons
    taxonomies: tx_dmdb_domain_model_discipline_taxonomy

  # Relation configuration
  relations:

    Taxonomy:
      # Single UID relation
      mainDiscipline:
        sourceField: main_discipline
        targetType: Discipline
        storageType: uid

      # Comma-separated UIDs relation
      disciplines:
        sourceField: disciplines
        targetType: Discipline
        storageType: commaSeparated

      # Foreign key relation (inverse/legacy MM)
      relatedDisciplines:
        targetType: Discipline
        storageType: foreignKey
        foreignKeyField: discipline_taxonomy

    Expert:
      # MM table relation
      disciplines:
        targetType: Discipline
        storageType: mmTable
        mmTable: tx_academy_persons_discipline_mm
        mmSourceField: uid_local
        mmTargetField: uid_foreign
        mmSortingField: sorting
```

## GraphQL Query Example {#graphql-query-example}

With the configuration above, you can now query nested relations:

**GraphQL query**

```text
{
  experts {
    familyName
    givenName
    disciplines {
      name
    }
  }
}
```
