コンテンツにスキップ

ブランチルーティング

概要

DDDSシステムは、サブドメインに基づいてブランチ(branch)を自動判定し、適切なコントローラとビューを表示します。

ブランチ定数

application/config/constants.php:

// ブランチ定数
define('APP_HEAD', 'headquarter');         // 本部
define('APP_CORDINATOR', 'cordinator');    // コーディネータ
define('APP_TRANSPLANT', 'transplant');    // 移植施設
define('APP_TRANSLIVE', 'translive');      // 生体移植施設(TRACER)

// 2FAドメイン
define('TR_2FA_DOMAIN', 'tracer');

ブランチ判定フロー

graph TD
    START[HTTPリクエスト] --> CHECK_DOMAIN{SERVER_NAMEチェック}

    CHECK_DOMAIN -->|hdqrs| SET_HEAD[branch = APP_HEAD]
    CHECK_DOMAIN -->|brnch| SET_CORD[branch = APP_CORDINATOR]
    CHECK_DOMAIN -->|ddds| SET_TRANS[branch = APP_TRANSPLANT]
    CHECK_DOMAIN -->|tracer| SET_LIVE[branch = APP_TRANSLIVE]
    CHECK_DOMAIN -->|その他| SET_DEFAULT[branch = APP_TRANSPLANT<br/>デフォルト]

    SET_HEAD --> ROUTE[ルーティング処理]
    SET_CORD --> ROUTE
    SET_TRANS --> ROUTE
    SET_LIVE --> ROUTE
    SET_DEFAULT --> ROUTE

    ROUTE --> HOOK[フック処理]
    HOOK --> CONTROLLER[コントローラ実行]

ルーティング設定

デフォルトコントローラ

application/config/routes.php:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

// ブランチ取得
$branch = config_item('branch');

// ブランチ別デフォルトコントローラ
switch ($branch) {
    case APP_HEAD:
        // 本部: メニュー画面
        $route['default_controller'] = 'headquarter/menu';
        break;

    case APP_CORDINATOR:
        // コーディネータ: ドナー一覧
        $route['default_controller'] = 'cordinator/donorList';
        break;

    case APP_TRANSPLANT:
    case APP_TRANSLIVE:
        // 移植施設: メニュー画面
        $route['default_controller'] = 'transplant/menu';
        break;

    default:
        $route['default_controller'] = 'transplant/menu';
        break;
}

$route['404_override'] = 'errors/index/404';
$route['translate_uri_dashes'] = FALSE;

// 共通ルート
$route['login'] = 'common/auth/index';
$route['auth/login'] = 'common/auth/login';
$route['auth/logout'] = 'common/auth/logout';

ルーティング例

URL ブランチ コントローラ メソッド
hdqrs.example.com/ APP_HEAD headquarter/Menu index()
brnch.example.com/ APP_CORDINATOR cordinator/DonorList index()
ddds.example.com/ APP_TRANSPLANT transplant/Menu index()
tracer.example.com/ APP_TRANSLIVE transplant/Menu index()
ddds.example.com/livingDonorTransplant/search APP_TRANSPLANT common/LivingDonorTransplant search()

フック処理

ブランチ別フック設定

application/config/hooks.php:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

$branch = config_item('branch');

// ブランチ別ログイン認証フック
switch ($branch) {
    case APP_HEAD:
        $hook['post_controller_constructor'][] = array(
            'class' => 'Headquarter_MyClasses',
            'function' => 'loginCheck',
            'filename' => 'Headquarter_MyClasses.php',
            'filepath' => 'hooks'
        );
        break;

    case APP_CORDINATOR:
        $hook['post_controller_constructor'][] = array(
            'class' => 'Cordinator_MyClasses',
            'function' => 'loginCheck',
            'filename' => 'Cordinator_MyClasses.php',
            'filepath' => 'hooks'
        );
        break;

    case APP_TRANSPLANT:
    case APP_TRANSLIVE:
        $hook['post_controller_constructor'][] = array(
            'class' => 'Transplant_MyClasses',
            'function' => 'loginCheck',
            'filename' => 'Transplant_MyClasses.php',
            'filepath' => 'hooks'
        );
        break;
}

// 共通: アクセスログ記録
$hook['post_controller'][] = array(
    'class' => 'MyClasses',
    'function' => 'writeAccessLog',
    'filename' => 'MyClasses.php',
    'filepath' => 'hooks'
);

// 共通: SQLクエリログ
$hook['pre_system'][] = array(
    'class' => 'QueryLogger',
    'function' => 'logQuery',
    'filename' => 'QueryLogger.php',
    'filepath' => 'hooks'
);

フッククラス

application/hooks/Transplant_MyClasses.php:

<?php
class Transplant_MyClasses
{
    public function loginCheck()
    {
        $CI =& get_instance();

        // 除外URL(ログイン不要)
        $excludeUrls = [
            'common/auth',
            'common/auth/login',
            'common/auth/logout',
            'errors',
        ];

        $uri = uri_string();

        // 除外URLチェック
        foreach ($excludeUrls as $excludeUrl) {
            if (strpos($uri, $excludeUrl) === 0) {
                return; // ログインチェックをスキップ
            }
        }

        // セッションチェック
        if (!$CI->session->userdata('is_login')) {
            redirect('/');
            exit;
        }

        // ブランチチェック
        $loginBranch = $CI->session->userdata('login_branch');
        $currentBranch = config_item('branch');

        if ($loginBranch !== $currentBranch) {
            $CI->session->sess_destroy();
            redirect('/');
            exit;
        }
    }
}

ブランチ別表示制御

ビュー分岐

application/views/transplant/menu.php:

<?php
$branch = config_item('branch');
$institutionKubun = $this->session->userdata('account')->institution_kubun;
?>

<h1>メニュー</h1>

<?php if ($branch === APP_TRANSPLANT): ?>
    <!-- ddds専用メニュー -->
    <?php if (in_array($institutionKubun, [INSTITUTION_KUBUN_TRANSPLANT, INSTITUTION_KUBUN_MANAGEMENT])): ?>
        <li><a href="/cadavericTransplant/search">死体移植管理</a></li>
    <?php endif; ?>

    <?php if (!file_exists(APPPATH . 'maintenance_tracer_living.flag')): ?>
        <li><a href="/livingDonorTransplant/search">生体移植管理</a></li>
    <?php else: ?>
        <li style="color:#999">生体移植管理(メンテナンス中)</li>
    <?php endif; ?>

<?php elseif ($branch === APP_TRANSLIVE): ?>
    <!-- tracer専用メニュー -->
    <?php if (!file_exists(APPPATH . 'maintenance_tracer_living.flag')): ?>
        <li><a href="/livingDonorTransplant/search">生体移植管理</a></li>
    <?php else: ?>
        <li style="color:#999">生体移植管理(メンテナンス中)</li>
    <?php endif; ?>
<?php endif; ?>

コントローラ分岐

application/controllers/common/Auth.php:

class Auth extends CI_Controller
{
    public function login()
    {
        // ... 認証処理 ...

        $branch = config_item('branch');
        $this->session->set_userdata('login_branch', $branch);

        // ブランチ別リダイレクト
        switch ($branch) {
            case APP_HEAD:
                redirect('/headquarter/menu');
                break;
            case APP_CORDINATOR:
                redirect('/cordinator/donorList');
                break;
            case APP_TRANSPLANT:
            case APP_TRANSLIVE:
                redirect('/transplant/menu');
                break;
        }
    }
}

ブランチ別アクセス制御

施設区分とブランチの関係

所属区分 定数 hdqrs brnch ddds tracer
移植施設(死体) INSTITUTION_KUBUN_TRANSPLANT (1)
生体移植専用 INSTITUTION_KUBUN_LIVING_DONOR (3)
学会 INSTITUTION_KUBUN_MANAGEMENT (4)

アクセス制御ロジック

application/controllers/common/Auth.php (line 136-139):

// 生体専用施設・学会のアクセス制御
if ($this->branch === APP_TRANSPLANT &&
    $this->domain !== 'ddds' &&
    in_array($account->institution_kubun, [
        INSTITUTION_KUBUN_LIVING_DONOR,
        INSTITUTION_KUBUN_MANAGEMENT
    ])) {
    // ddds以外からのアクセスをブロック
    $this->session->sess_destroy();
    show_error('アクセスが許可されていません', 403);
}

ドメイン判定

ドメイン取得

application/controllers/common/Auth.php:

class Auth extends CI_Controller
{
    private $domain;

    public function __construct()
    {
        parent::__construct();

        // ドメイン判定
        $serverName = $_SERVER['SERVER_NAME'] ?? '';

        if (strpos($serverName, 'hdqrs') === 0) {
            $this->domain = 'hdqrs';
        } elseif (strpos($serverName, 'brnch') === 0) {
            $this->domain = 'brnch';
        } elseif (strpos($serverName, 'ddds') === 0) {
            $this->domain = 'ddds';
        } elseif (strpos($serverName, 'tracer') === 0) {
            $this->domain = 'tracer';
        } else {
            $this->domain = 'unknown';
        }
    }
}

ブランチ判定の実行タイミング

sequenceDiagram
    participant Browser as ブラウザ
    participant Apache as Apache
    participant Index as web/index.php
    participant Config as MY_Config
    participant Routes as routes.php
    participant Hooks as hooks.php
    participant Controller as Controller

    Browser->>Apache: HTTPリクエスト
    Apache->>Index: index.php実行
    Index->>Config: MY_Config::__construct()
    Config->>Config: SERVER_NAMEからbranch判定
    Config-->>Index: branch設定完了

    Index->>Routes: routes.php読み込み
    Routes->>Routes: config_item('branch')取得
    Routes->>Routes: ブランチ別ルート設定
    Routes-->>Index: ルート設定完了

    Index->>Hooks: hooks.php読み込み
    Hooks->>Hooks: config_item('branch')取得
    Hooks->>Hooks: ブランチ別フック設定
    Hooks-->>Index: フック設定完了

    Index->>Controller: コントローラ実行
    Controller->>Hooks: post_controller_constructor
    Hooks->>Hooks: loginCheck()
    Hooks-->>Controller: 認証OK

    Controller->>Controller: ビジネスロジック実行
    Controller-->>Browser: レスポンス返却

関連ドキュメント