ブランチルーティング¶
概要¶
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: レスポンス返却