コンテンツにスキップ

customer_addresses テーブル定義

テーブル概要

会員が事前に登録した配送先住所を管理するテーブルです。ECCUBEのdtb_customer_addressテーブル構造を参考にしています。

テーブル名: customer_addresses 説明: 会員配送先住所 用途: 会員が事前に登録した配送先リストを管理。注文時に選択してaddressesテーブルにコピーされる。

カラム定義

カラム名 NULL デフォルト キー 説明
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PK 主キー
user_id BIGINT UNSIGNED NOT NULL - FK, INDEX 会員ID(users.id)
address_name VARCHAR(255) NOT NULL - INDEX 住所名("自宅", "実家", "会社"等)
last_name VARCHAR(255) NOT NULL - -
first_name VARCHAR(255) NOT NULL - -
last_name_kana VARCHAR(255) NULL NULL - 姓カナ
first_name_kana VARCHAR(255) NULL NULL - 名カナ
company_name VARCHAR(255) NULL NULL - 会社名
phone_number VARCHAR(14) NOT NULL - INDEX 電話番号
country_id BIGINT UNSIGNED NOT NULL - FK 国ID(countries.id)
postal_code VARCHAR(8) NOT NULL - INDEX 郵便番号/ZIP
state_province VARCHAR(255) NOT NULL - INDEX 州/省/都道府県
address_line1 VARCHAR(255) NOT NULL - - 住所1(市区町村・番地)
address_line2 VARCHAR(255) NULL NULL - 住所2(建物名等)
address_line3 VARCHAR(255) NULL NULL - 住所3(追加情報)
is_default BOOLEAN NOT NULL FALSE INDEX デフォルト配送先フラグ
created_at TIMESTAMP NULL NULL - 作成日時
updated_at TIMESTAMP NULL NULL - 更新日時

インデックス

種別 名称 対象カラム 説明
PRIMARY KEY pk_customer_addresses id 主キー
INDEX idx_customer_addresses_user user_id 会員別検索
INDEX idx_customer_addresses_name address_name 住所名検索
INDEX idx_customer_addresses_phone phone_number 電話番号検索
INDEX idx_customer_addresses_postal postal_code 郵便番号検索
INDEX idx_customer_addresses_state state_province 都道府県/州検索
INDEX idx_customer_addresses_default is_default デフォルト配送先検索

外部キー制約

名称 対象カラム 参照先 ON DELETE ON UPDATE 説明
fk_customer_addresses_user user_id users(id) CASCADE RESTRICT 会員削除時に配送先も削除
fk_customer_addresses_country country_id countries(id) RESTRICT RESTRICT 国削除時はエラー

リレーション

関連先テーブル 関連タイプ 外部キー 参照先 ON DELETE ON UPDATE 説明
users N:1 user_id id CASCADE RESTRICT 配送先は1つの会員に属する
countries N:1 country_id id RESTRICT RESTRICT 配送先は1つの国に属する

データ例

id user_id address_name last_name first_name phone_number postal_code state_province address_line1 is_default
1 1 自宅 山田 太郎 090-1234-5678 554-0001 大阪府 大阪市此花区高見1-2-3 TRUE
2 1 会社 山田 太郎 06-1234-5678 530-0001 大阪府 大阪市北区梅田1-1-1 FALSE
3 2 実家 佐藤 花子 080-9876-5432 100-0001 東京都 千代田区千代田1-1 TRUE

備考・注意事項

住所設計

世界共通フォーマット

  • 5つのフィールド(country_id, postal_code, state_province, address_line1-3)で全世界対応
  • JSON不要でシンプル
  • 検索・ソートが高速

日本の例

  • country_id: 日本
  • postal_code: 554-0001
  • state_province: 大阪府
  • address_line1: 大阪市此花区高見1-2-3
  • address_line2: ○○マンション101号

アメリカの例

  • country_id: USA
  • postal_code: 10001
  • state_province: NY
  • address_line1: 123 Main Street
  • address_line2: Apt 4B
  • address_line3: New York

デフォルト配送先管理

is_defaultフラグ

  • 1つの会員につき、1つのデフォルト配送先のみ設定可能
  • 新しい配送先をデフォルトに設定する際は、既存のデフォルトを解除する必要がある
  • アプリケーション層で制御(データベース制約は設定しない)

推奨実装

// デフォルト配送先を設定
public function setDefaultAddress(CustomerAddress $address): void
{
    // 既存のデフォルトを解除
    $this->customerAddresses()
        ->where('is_default', true)
        ->update(['is_default' => false]);

    // 新しいデフォルトを設定
    $address->update(['is_default' => true]);
}

addressesテーブルとの関係

役割の違い

  • customer_addresses: 会員の登録配送先リスト(事前登録)
  • addresses: 注文時のスナップショット住所(注文時点での情報を記録)

データフロー

  1. 会員がcustomer_addressesに配送先を事前登録
  2. 注文時にcustomer_addressesから選択
  3. 選択した配送先情報をaddressesテーブルにコピー
  4. 会員が後からcustomer_addressesを変更しても、addressesの情報は変わらない

Eloquentモデル例

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class CustomerAddress extends Model
{
    protected $fillable = [
        'user_id',
        'address_name',
        'last_name',
        'first_name',
        'last_name_kana',
        'first_name_kana',
        'company_name',
        'phone_number',
        'country_id',
        'postal_code',
        'state_province',
        'address_line1',
        'address_line2',
        'address_line3',
        'is_default',
    ];

    protected function casts(): array
    {
        return [
            'is_default' => 'boolean',
        ];
    }

    // リレーション
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function country(): BelongsTo
    {
        return $this->belongsTo(Country::class);
    }

    // アクセサ
    public function getFullNameAttribute(): string
    {
        return trim($this->last_name . ' ' . $this->first_name);
    }

    public function getFullNameKanaAttribute(): string
    {
        return trim(($this->last_name_kana ?? '') . ' ' . ($this->first_name_kana ?? ''));
    }

    // スコープ
    public function scopeDefault($query)
    {
        return $query->where('is_default', true);
    }

    // デフォルト配送先を設定
    public function setAsDefault(): void
    {
        // 既存のデフォルトを解除
        $this->user->customerAddresses()
            ->where('is_default', true)
            ->where('id', '!=', $this->id)
            ->update(['is_default' => false]);

        // この配送先をデフォルトに設定
        $this->update(['is_default' => true]);
    }
}