# Schéma de base de données

## Tables

### users
```sql
id              bigint PK
name            varchar(255)
email           varchar(255) UNIQUE
password        varchar(255)
role            enum('admin','editor') DEFAULT 'editor'
remember_token  varchar(100) NULL
created_at      timestamp
updated_at      timestamp
```

### templates
```sql
id          bigint PK
name        varchar(255)          -- "Page complète"
slug        varchar(255) UNIQUE   -- "full-width"
zones       json                  -- ["content"] ou ["content","sidebar"]
thumbnail   varchar(255) NULL     -- chemin image aperçu
created_at  timestamp
updated_at  timestamp
```

### pages
```sql
id               bigint PK
title            varchar(255)
slug             varchar(255) UNIQUE
status           enum('draft','published','archived') DEFAULT 'draft'
template_id      bigint FK → templates.id
meta_title       varchar(255) NULL
meta_description text NULL
meta_image       varchar(255) NULL     -- chemin media
created_at       timestamp
updated_at       timestamp
published_at     timestamp NULL
```

### blocks
```sql
id       bigint PK
page_id  bigint FK → pages.id (CASCADE DELETE)
zone     varchar(100)    -- "content", "sidebar", "hero"...
type     varchar(100)    -- "hero", "text", "property-list"...
order    int DEFAULT 0
props    json            -- contenu du bloc selon son schéma
created_at timestamp
updated_at timestamp

INDEX (page_id, zone)
INDEX (page_id, order)
```

### menu_locations
```sql
id     bigint PK
slug   varchar(100) UNIQUE   -- "header", "footer-col-1"
label  varchar(255)          -- "Menu principal"
```

### menus
```sql
id         bigint PK
name       varchar(255)
created_at timestamp
updated_at timestamp
```

### menu_location (table pivot)
```sql
menu_id          bigint FK → menus.id
menu_location_id bigint FK → menu_locations.id
PRIMARY KEY (menu_id, menu_location_id)
```

### menu_items
```sql
id        bigint PK
menu_id   bigint FK → menus.id (CASCADE DELETE)
parent_id bigint FK → menu_items.id NULL (CASCADE DELETE)
label     varchar(255)
type      enum('page','url','custom')
page_id   bigint FK → pages.id NULL (SET NULL)
url       varchar(500) NULL
target    enum('_self','_blank') DEFAULT '_self'
order     int DEFAULT 0
created_at timestamp
updated_at timestamp

INDEX (menu_id, parent_id)
INDEX (menu_id, order)
```

### media
```sql
id          bigint PK
filename    varchar(255)       -- nom original
path        varchar(500)       -- chemin stockage (relatif au disk)
disk        varchar(50) DEFAULT 'public'
mime_type   varchar(100)
size        int                -- octets
width       int NULL           -- px (images uniquement)
height      int NULL           -- px (images uniquement)
alt         varchar(255) NULL
created_at  timestamp
updated_at  timestamp
```

### settings
```sql
id         bigint PK
key        varchar(255) UNIQUE   -- "site.name", "site.logo"
value      json                  -- valeur sérialisée
autoload   boolean DEFAULT true  -- chargé au démarrage
created_at timestamp
updated_at timestamp
```

---

## Relations Eloquent importantes

```php
// Page.php
public function template(): BelongsTo   { return $this->belongsTo(Template::class); }
public function blocks(): HasMany       { return $this->hasMany(Block::class)->orderBy('order'); }

// Block.php
public function page(): BelongsTo      { return $this->belongsTo(Page::class); }

// Menu.php
public function items(): HasMany       { return $this->hasMany(MenuItem::class)->whereNull('parent_id')->orderBy('order')->with('children'); }
public function locations(): BelongsToMany { return $this->belongsToMany(MenuLocation::class, 'menu_location'); }

// MenuItem.php
public function children(): HasMany    { return $this->hasMany(MenuItem::class, 'parent_id')->orderBy('order')->with('children'); }
public function page(): BelongsTo      { return $this->belongsTo(Page::class); }

// Accesseur URL résolue
public function getResolvedUrlAttribute(): string
{
    return match($this->type) {
        'page'   => $this->page ? '/' . $this->page->slug : '#',
        default  => $this->url ?? '#',
    };
}
```

---

## Règles migrations

- Toujours définir les index sur les colonnes FK et les colonnes de recherche fréquente
- Les FK avec CASCADE DELETE : blocks → pages, menu_items → menus, menu_items → parent
- Les FK avec SET NULL : menu_items.page_id → pages (si page supprimée, item garde le label)
- Ne jamais modifier une migration existante — créer une nouvelle migration corrective
- Nommage : `create_{table}_table`, `add_{col}_to_{table}_table`, `modify_{col}_in_{table}_table`
