Laravel3、コードをドキュメントルートから外す

タグ: Laravel3  

Laravelをお手軽にインストールするには、ファイル構造を保ったままアップしましょう。簡単ですし、大抵ローカルに同じ構造がありますから、メンテナンスも楽です。

ただ、この方法は複数サイトを構築する場合、コアのアップデートなどが面倒なため、コアは共通で使用したいものです。さらに、ドキュメントルート上にコードが置かれてしまうため、セキュリティー的には弱くなります。

そこで、構造を以下のように再構成する、シェルプログラムを紹介します。SSHなどでコマンド実行できることが前提です。できない場合は次の記事を参照してください。

参照:FTP使用バージョン

例えば元の構造が以下であるとします。

/home
  /yourhome
    /public_html <= ドキュメントルート
       /site_a <= 仮想ホストA、以下はLaravelの構造
         /application
         /bundle
         /laravel
         /public
            /bundle
            /css
            /img
            /js
            index.php
         /storage
         artisan
         paths.php
       /site_b <= 仮想ホストB、以下はLaravelの構造
         /application
         /bundle
         /laravel
         /public
            /bundle
            /css
            /img
            /js
            index.php
         /storage
         artisan
         paths.php

これを次のように移動します。

/home
  /yourhome
    /laravel_dir
        /laravel <= Laravelのコア、全サイト共通で使用
        /sites
          /site_a <=仮想ホストAのコード部分とstorage
            /application
            /bundle
            /storage
            artisan
            paths.php
          /site_b <=仮想ホストBのコード部分とstorage
            /application
            /bundle
            /storage
            artisan
            paths.php
    /public_html
      /site_a <= publicの内容
        /bundle
        /css
        /img
        /js
        index.php
      /site_b <= publicの内容
        /bundle
        /css
        /img
        /js
        index.php

これによりindex.php以外の実行コードはドキュメントルート上から外せます。Laravelのコアは全サイト共通で使用しますので、アップデートは楽になります。また、内容にパスを設定する必要のあるindex.phpとpaths.phpは構造に合わせ書き換えます。(絶対パスで指定するように書き換えますが、使用に差支えありません。)

bundleフォルダーを全サイト共通にしなかったのは、バンドルにより設定方法が異なり、共通にするとバッティングする可能性があるためです。

storageはファイルの保存場所という性格上、共有は難しいですから、分けました。同じ内容を書き込まれるとコンフリクトを起こします。

このスクリプトはLinux(openSUSE)上で作成しました。openCludeというOSの共有サーバー上で実行し、動作確認しています。MacやWindows上では一工夫しないと動作しないでしょう。MacはLinuxではなく、Unixですからね。(どなたか動かせたら、教えてください。)

動作要件

以下です。緩いです。大抵の共有サーバーやVSPであれば楽勝でしょう。

  • Linux(もしくは以下のシェルとコマンドを準備できる環境)
  • bash(Linuxで一番一般的なシェル)
  • sed(-iで上書きできるもの)
  • cpで-aが仕様できること(無ければ-Rなどで代用可能)
  • 共有サーバーであればシェルアクセス(SSH)ができること
使用方法

ホームのbinディレクトリーなど、実行パスの通っているディレクトリにーに設置してください。その他の場所に設置する場合は、コマンドにパスを指定するのをお忘れなく。

laravel3-code-unite 作業対象ディレクトリー名

前記の例ですと、2つのサイトに対し、以下のようにします。

laravel3-code-unite site_a
laravel3-code-unite site_b

コマンドを最初に実行する前にエディターで開き、対象ディレクトリーを設定する必要があります。詳細は以下をご覧ください。

インストール

以下のコードをlaravel3-code-uniteで作成してください。前述の通り、実行パスの通っているホームのbinディレクトリーに作成することをおすすめします。

# !/usr/bin/sh

set -e

# Please set your html document root
publichtml=/home/Your-Home-Directory/public_html

# Please set your directory to collect core/core files/directories
codedir=/home/Your-Home-Directory/laravel-dirs

laravelcore="${codedir}/laravel"
sitesdir="${codedir}/sites"
distdir="${sitesdir}/$1"

targetdir="${publichtml}/$1"

if [ $publichtml = '/home/Your-Home-Directory/public_html' ]
then
    echo Error! Please open this script with a editor, and set your document root to 'publichtml'.
    exit 10
fi

if [ $codedir = '/home/Your-Home-Directory/laravel-dirs' ]
then
    echo Error! Please open this script with a editor, and set you directory that collect your codes to 'codedir'.
fi

if [ $# != 1 ]
then
    echo
    echo Unite Laravel file structure into out of web document root.
    echo
    echo Usage: $0 Target-directory-name
    echo
    echo Note: Before first run this command, please set your directories to fit your host envrionments.
    echo
    exit 1
fi

if [ ! -d $targetdir ]
then
    echo Error! Target directory is not found. \($targetdir\)
    exit 2
fi

if [ ! -f "${targetdir}/paths.php" ]
then
    echo Error! Maybe already united. No paths.php in $targetdir
    exit 3
fi

if [ ! -d $codedir ]
then
    mkdir $codedir
fi

if [ ! -d $sitesdir ]
then
    mkdir $sitesdir
fi

# move laravel root folder to united directory
mv $targetdir $sitesdir

# move back public folder to document root.
mv "${distdir}/public" $targetdir

# copy core folder if not exist in united directory.
if [ ! -d $laravelcore ]
then
    cp -fa "${distdir}/laravel/" $laravelcore
    echo Notice : Copied Laravel core direcotry to $laravelcore.
fi

# remove core folder
rm -R "${distdir}/laravel"

# replace paths.php path in index.php

sed -i -e "
    s+../paths.php+${distdir}/paths.php+
" "${targetdir}/index.php"

# replace public/sys path in paths.php
sed -i -e "
    s+paths[ \n\r\f\t]*[[ \n\r\f\t]*'sys'[ \n\r\f\t]*][ \n\r\f\t]*=[ \n\r\f\t]*'laravel'+paths['sys'] = '${laravelcore}'+
    s+paths[ \n\r\f\t]*[[ \n\r\f\t]*'public'[ \n\r\f\t]*][ \n\r\f\t]*=[ \n\r\f\t]*'public'+paths['public'] = '${targetdir}'+
"  "${distdir}/paths.php"

echo "Successfully complited."
exit 0

その時にpublichtmlとcodedirを自分の環境に合わせ設定してください。スクリプトの最初の方にあります。

publichtmlはあなたのドキュメントルートを絶対パスで指定します。上記の例ですと/home/yourhome/public_htmlになります。

codedirはコードをまとめるディレクトリーを絶対パスで指定します。上記の例ですと/home/yourhome/laravel-dirになります。

上記2つを設定しないと、コマンドは動作しません。

保存したら、実行権限を付けてください。

chmod u+x laravel3-code-unite
注意

初めて使用するときは、いきなり動作中のサイトに対して行うのではなく、新たにインストールしたLaravelのサイトなどで、テストし動作結果を確認してください。

実働サイトのフォルダーに対して行う前には、必ずバックアップを取ってください。

コマンドを実行すると、ドメインに対する仮想ホストのドキュメントルートフォルダーを変更する必要があるでしょう。例えば、上記の例でしたらサイトAに対するドキュメントルートは/home/yourhome/public_html/site_a/publicであるものを/home/yourhome/public_html/site_aへと変更する必要があります。お忘れなく。

Macではコマンドの一部がLinuxとは異なっているようなので、動作するかどうかは分かりません。(もちろん、私がMac使いでしたら確かめますが、持っていません。)多分、sedの入力ファイルを置き換える-iオプションや、cpコマンドの-aオプションあたりが問題なく動作するようでしたら、そのままいけるでしょう。あまり特別な処理は行なっていませんので、動作させるのもそれほど面倒でないと思います。

追記:自分の共有ホスティングでも試しましたが、簡単すぎて実感が湧きませんでした。 :D 引っかかったのは古いバージョン(3.1)で動いていたアプリを、最新バージョン(3.2)で動かした時だけです。