※ CodeIgniter v3 をもとにしています。
はじめまして。年賀状の進捗どうですか。
CodeIgniterでマルチサイトにしたいことがないですかね。
たとえば公開用と管理画面用とを分けるなど。
さらに、分けたサイトを別々のGitリポジトリで管理したりとかにも少し触れます。
ちなみに、海外では「Multi Site」よりも「Multi Application」という呼称の方がよく使われるようなので、ググる場合などご参考に。
以下のような構成にしたい場合を想定して話を進めます。
- 公開側用
- URL:/
- フォルダ名:www
- 管理画面用
- URL:/admin/
- フォルダ名:admin
公式な方法
まず、CodeIgniterのデフォルトのフォルダ構成は以下のようになっています。(最低限必要なもの)
application
├cache
│(略)
└views
system
index.php
このままでもルーティングや Controller をがんばればマルチサイトにできなくもないんですが、v2のユーザーガイド や v3のユーザーガイド にて、以下のように分割する方法が書かれています。
application
├www (公開用)
│├cache
││(略)
│└views
└admin (管理画面用)
├cache
│(略)
└views
system
index.php (公開用)
admin.php (管理画面用)
まず application の中にサイトごとのフォルダを用意し、もともと application にあったフォルダ群をコピー。
そして、直下の index.php を公開用に使い、それを admin.php としてコピーして管理画面用にします。
あとは、index.php と admin.php の116行目を編集。
- $application_folder = 'application';
+ $application_folder = 'application/www';
- $application_folder = 'application';
+ $application_folder = 'application/admin';
そのうえでサイトごとにURLリライト設定。
RewriteEngine On
# 管理画面用
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^admin(/(.*))?$ admin.php/$2 [L]
# 公開用
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
server {
#...
# 管理画面用
location /admin {
try_files $uri $uri/ /admin.php;
}
# 公開用
location / {
try_files $uri $uri/ /index.php;
}
#...
}
でもこれ・・・サイト増えたりとかするとわりとめんどくさいですよね?
あと、直下と application 内とでファイルが分かれてて Git の管理なんかもやりにくい・・・。
そこで。
ひと手間かける
各サイトのフォルダは application 内のものだけで完結させたい。(独立して Git 管理したい)
なので、全てのサイトで直下の index.php を使うことにする。
フォルダ構成はこのような感じ。
application
├www (公開用)
│├cache
││(略)
│└views
└admin (管理画面用)
├cache
│(略)
└views
system
index.php (全サイト共用)
Apache または Nginx は通常の記述で。
RewriteEngine On
# 全サイト共用
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
server {
#...
# 全サイト共用
location / {
try_files $uri $uri/ /index.php;
}
#...
}
index.php の116行目のあとに、マルチサイト用の記述を追加。
// これはもともとある記述(116行目)
// $application_folder = 'application';
// 公開用をデフォルトにする
$application_folder = 'application/www';
/*
* -------------------------------------------------------------------
* マルチサイト用(追加部分)
* -------------------------------------------------------------------
*
* Nginxを通してる場合は $_SERVER['REQUEST_URI'] ではなく
* $_SERVER['HTTP_X_ORIGINAL_REQUEST'] である場合があるため対応してます。
*/
$uri = NULL;
if (isset($_SERVER['REQUEST_URI'])) {
$uri = $_SERVER['REQUEST_URI'];
} elseif (isset($_SERVER['HTTP_X_ORIGINAL_REQUEST'])) {
$uri = $_SERVER['HTTP_X_ORIGINAL_REQUEST'];
}
// URLの第一階層と同じディレクトリが application 内にあれば $application_folder に追記
if ($uri && ($dir = strtok(trim($uri, '/'), '/')) && is_dir($application_folder.'/'.$dir)) {
$application_folder .= '/'.$dir;
}
これで自動的に $application_folder
が各フォルダに自動設定されるので、マルチサイト化完了。
また、application 内のフォルダをコピーすることでいくらでもサイトを増やせます。
Gitで管理する例
これは自分の例だけど、ルートフォルダと application フォルダ内とで submodule を使ってリポジトリを分けてます。
管理が分轄できていいかなと。
このような感じ。
.git
application
├www (submodule)
││(略)
│└.git
└admin (submodule)
│(略)
└.git
system
.gitmodules
index.php
ルーティング記述を少し楽にする
ここまでで問題はないんですが、サブサイトでのルーティングで少し面倒な点が。
例えばURLが /admin/login
とかの場合、application/admin/config/routes.php
の記述は以下のようになります。
<?php
$route['default_controller'] = 'welcome';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
// 管理画面トップページ用
$route['admin'] = 'welcome';
// 管理画面ログイン用
$route['admin/login'] = 'login';
面倒じゃないですかね。すべてのルーティングに「admin」を付けなければならないのが。
なので、以下のように加工したりしてます。
<?php
$route['default_controller'] = 'welcome';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
// -- ↓ すこし変更 --
// 管理画面トップページ用
$route['/'] = 'welcome';
// 管理画面ログイン用
$route['login'] = 'login';
// -- ↓ 以下追加部分 --
// 各キー名に「admin/」を追加
$route = array_combine(array_map(function($k) use($route) {
if('default_controller' == $k || '404_override' == $k || 'translate_uri_dashes' == $k) {
return $k;
}
return trim('admin/'.$k, '/');
}, array_keys($route)), $route);
このあたりは Hooksとかで対応できないかな~なんていろいろ試したんですが無理っぽかったです。
あと、コアの Routing.php
にそういうことできるっぽいやつがある!と思ったけどURLの書き換えとかではなさげでした。
なくても動くので少しでも高速化したい場合は不要ですかね。
サブドメインの場合
サブドメインの場合はすこし楽です。
ディレクトリ構成はここまでのものと同じで、index.php をサブドメイン用に変更するだけです。
// これはもともとある記述(116行目)
// $application_folder = 'application';
// 公開用をデフォルトにする
$application_folder = 'application/www';
/*
* -------------------------------------------------------------------
* マルチサイト用(追記部分)
* -------------------------------------------------------------------
*/
if (isset($_SERVER['HTTP_HOST'])) {
// サブドメイン名と同じディレクトリが application 内にあれば $application_folder に追記
if (($dir = current(explode('.', $_SERVER['HTTP_HOST']))) && is_dir($application_folder.'/'.$dir)) {
$application_folder .= '/'.$dir;
}
}
で、前述のルーティングを楽にする部分は必要なくなります。
以上です。
ちなみに年賀状は12月15日~25日のあいだに投函すれば元旦に届くそうです。