LoginSignup
31

More than 5 years have passed since last update.

CodeIgniterでのマルチサイト

Posted at

※ 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行目を編集。

index.php
- $application_folder = 'application';
+ $application_folder = 'application/www';
admin.php
- $application_folder = 'application';
+ $application_folder = 'application/admin';

そのうえでサイトごとにURLリライト設定。

Apacheの場合
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]
Nginxの場合
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 は通常の記述で。

Apacheの場合
RewriteEngine On

# 全サイト共用
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
Nginxの場合
server {
    #...

    # 全サイト共用
    location / {
        try_files $uri $uri/ /index.php;
    }

    #...
}

index.php の116行目のあとに、マルチサイト用の記述を追加。

index.php
    // これはもともとある記述(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 の記述は以下のようになります。

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」を付けなければならないのが。
なので、以下のように加工したりしてます。

application/admin/config/routes.php
<?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 をサブドメイン用に変更するだけです。

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日のあいだに投函すれば元旦に届くそうです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31