---
url: /laravel-api-generator/guide/relationships.md
---
# Relationships

Relations can be declared in [schema files](/guide/schema-files), [Mermaid diagrams](/guide/mermaid), `class_data.json`, the interactive wizard, or detected automatically [from your database](/guide/from-database).

## Declare one side, get both

In schema files, Mermaid diagrams and `class_data.json`, declaring one side of a `belongsTo` / `hasOne` / `hasMany` / `belongsToMany` is enough: the inverse relation **and its FK migration column** are synthesized automatically, exactly like `--from-database` does:

```yaml
entities:
  Category:
    fields:
      name: string unique
    relations:
      posts: hasMany Post
  Post:
    fields:
      title: string
```

Here, `Post` gets the `belongsTo Category` and the `category_id` column without one more line. If both sides are declared, they are de-duplicated.

## Eloquent vocabulary

Schema files use the Eloquent method names directly:

| Declaration | Eloquent method | Foreign key |
|-------------|----------------|-------------|
| `author: belongsTo User` | `belongsTo()` | On current table |
| `posts: hasMany Post` | `hasMany()` | On related table |
| `profile: hasOne Profile` | `hasOne()` | On related table |
| `tags: belongsToMany Tag` | `belongsToMany()` | Pivot table, created automatically |

Entities are generated **parents-first** so migrations run in foreign-key-safe order, and pivot migrations are created automatically for every `belongsToMany`.

## Polymorphic relations

Schema files support `morphTo`, `morphOne` and `morphMany`:

```yaml
entities:
  Post:
    fields:
      title: string
    relations:
      comments: morphMany Comment
  Comment:
    fields:
      body: text
    relations:
      commentable: morphTo
```

`morphTo` emits `$table->nullableMorphs('commentable')` in the migration and `morphTo()` on the model; `morphOne` / `morphMany` point back with the right morph name. Database introspection detects `*_type` / `*_id` column pairs as `morphTo` automatically.

## Custom primary keys propagate

When a related entity uses a [custom primary key](/guide/field-types#custom-primary-keys), every incoming relation follows: FK name (`country_code`), column type, `->references('code')` and the `exists:countries,code` validation rule.

## JSON mode (`class_data.json`)

Bulk generation from JSON uses explicit relationship arrays:

| JSON key | Eloquent method |
|----------|----------------|
| `oneToOneRelationships` | `hasOne()` |
| `oneToManyRelationships` | `hasMany()` |
| `manyToOneRelationships` | `belongsTo()` |
| `manyToManyRelationships` | `belongsToMany()` |

```json
[
  {
    "name": "User",
    "attributes": [{ "name": "name", "_type": "string" }],
    "oneToManyRelationships": [{ "role": "posts", "comodel": "Post" }]
  },
  {
    "name": "Post",
    "attributes": [{ "name": "title", "_type": "string" }],
    "manyToOneRelationships": [{ "role": "user", "comodel": "User" }]
  }
]
```

Model inheritance is also supported via the `"parent"` key.

## Relations in the PHPDoc

Every relation lands in the model's docblock, so your IDE autocompletes `$post->comments` immediately:

```php
/**
 * @property-read Category $category
 * @property-read \Illuminate\Database\Eloquent\Collection<int, Comment> $comments
 */
```
