投稿日 2008年5月19日 月曜日 カテゴリ CMS, MODx 投稿者 sugimotoコメント(0) » 

MODxのsnippetを使うと、コンテンツを管理、表示するための便利な機能を作ることができます。

snippetはMODx本体と同じように、PHPで書きます。zeera document searchのページで使う、「次のページへ」のリンクを作るsnippetを作りました。

modx オブジェクトの関数

modx オブジェクトはMODxがページを表示するときに必ず作成されるオブジェクトです。 DocumentParserクラスから作られます。DocumentParserクラスはドキュメントを表示する機能を提供するクラスですが、それ以外にも

  • データベースから任意のドキュメントを取ってくる
  • ドキュメントのパラメータの取得
  • プレースホルダーの作成

などのAPIを提供しています。たとえば、次のようなAPIがあります。

  • getParentIds($id, $height, $parent) : 親ドキュメントのIDをrecursiveに取得
  • getChildIds($id, $height, $children) : 子ドキュメントのIDをrecursiveに取得
  • getDocument($id, $fields, $published, $deleted) : ドキュメントを取得してarrayで返します。
  • getDocuments($id, $fields, $published, $deleted) : $id に一括取得するドキュメントのIDをarrayで指定します。
  • getActiveChildren($id, $sort, $dir, $fields) : 子ドキュメントを一括取得します。
  • makeURL($id, $alias, $args, $scheme) : フレンドリーURLを返します。
  • getPlaceholder($name) : プレースホルダーに設定された値を取得。
  • setPlaceholder($name, $value) : プレースホルダーを作ります。

snippetの作成

管理画面で、[リソース]->[リソース管理]->[スニペット]->[新規作成]で、snippetを作成します。

今回は[次へ]リンクを作成するためのDocumentPager snippetを作りました。

親IDが同じドキュメントのうち、指定したソート順で次(前)のドキュメントをプレースホルダーにします。

[[DocumentPager? &sortBy='id' &sortDir='ASC' &returnId='xx']]
[+dpPrev+] [+dpNext+]

パラメータ

  • sortBy: 次、前のドキュメントを探す順番
  • sortDir: 次、前のドキュメントを探す順番
  • returnId: 最初と最後のドキュメントで[戻る]リンクの先ドキュメントID

作られるPlaceholder

  • [+dpPrevId+]: 前のドキュメントのID
  • [+dpPrevPagetitle+]: 前のドキュメントのページタイトル
  • [+dpPrevAlias+]: 前のドキュメントのAlias
  • [+dpPrevLink+]: 前のドキュメントへのリンク
  • [+dpNextId+]: 次のドキュメントのID
  • [+dpNextPagetitle+]: 次のドキュメントのページタイトル
  • [+dpNextAlias+]: 次のドキュメントのAlias
  • [+dpNextLink+]: 次のドキュメントのリンク

snippet

< ?php
class DocumentPager {
    var $id, $sort, $dir, $return;
    function DocumentPager($sort = "id", $dir = "ASC", $returnId = null) {
        global $modx;
        $this->id = $modx->documentIdentifier;
        $this->sort = "id";
        $this->dir = "ASC";
        $this->returnId = $return;
        $this->getDocuments();
        $this->return = $modx->getDocument($returnId);
        $this->setPlaceholders();
    }
    function getDocuments() {
        global $modx;
        $parent = $modx->getParent();
        $docs = $modx->getActiveChildren($parent['id'], $this->sort, $this->dir);
        $found = false;
        for ($i = 0; $i < count($docs); $i++) {
            if ($this->id == $docs[$i]['id']) {
                $this->next = $docs[$i + 1];
                break;
            }
            $this->prev = $docs[$i];
        }
    }
    function setPlaceholders() {
        global $modx;
        if ($this->prev != null) {
            $modx->setPlaceholder('dpPrevId', $this->prev['id']);
            $modx->setPlaceholder('dpPrevPagetitle', $this->prev['pagetitle']);
            $modx->setPlaceholder('dpPrevAlias', $this->prev['alias']);
            $prevLink = "<a href='". $modx->makeUrl($this->prev['id']) ."'>« ". $this->prev['pagetitle'] ."</a>";
            $modx->setPlaceholder('dpPrev', $prevLink);
        } elseif ($this->return) {
            $prevLink = "<a href='". $modx->makeUrl($this->return['id']) ."'>« ". $this->return['pagetitle'] ."に戻る</a>";
            $modx->setPlaceholder('dpPrev', $prevLink);
        }
        if ($this->next != null) {
            $modx->setPlaceholder('dpNextId', $this->next['id']);
            $modx->setPlaceholder('dpNextPagetitle', $this->next['pagetitle']);
            $modx->setPlaceholder('dpNextAlias', $this->next['alias']);
            $nextLink = "<a href='". $modx->makeUrl($this->next['id']) ."'>". $this->next['pagetitle'] ." »</a>";
            $modx->setPlaceholder('dpNext', $nextLink);
        } elseif ($this->return) {
            $nextLink = "<a href='". $modx->makeUrl($this->return['id']) ."'>". $this->return['pagetitle'] ."に戻る »</a>";
            $modx->setPlaceholder('dpNext', $nextLink);
        }
    }
}
new DocumentPager($sortBy, $sortDir, $returnId);
?>

参考

投稿日 2008年4月21日 月曜日 カテゴリ mysql, rsync, CMS, MODx 投稿者 sugimotoコメント(3) » 

OpenGrooveの検索アプライアンスサーバ「zeera document search」の製品サイトはMODx CMSを利用して構築しています。

サイトの更新は

  1. 別に用意したテスト環境で更新
  2. 更新に問題がないか社内でチェック
  3. 本番環境に更新分を反映

という手順でやっているのですが、#3の反映作業は手作業にすると、手間がかかり、反映漏れが出るもとになります。

そこで、ssh, rsync, mysqldumpを使って、#3の手順を自動化し、更新分を確実に反映することにしました。

1. 反映の方法

自動化の方法の概要を簡単に説明すると以下の通りです。

- rsyncでディレクトリの同期

MODx CMSは、

   top --- manager
        +- assets

というディレクトリ構造をしていて、assetsにテンプレート,CSS,imageなどが保存されています。 逆にmanagerにはMODxのコアスクリプトと設定ファイルがあります。 そのため、assetsをrsyncで同期することにします。

- データベースの更新

MODx CMSはMySQLでデータを保存しています。 環境依存なデータはsite_settingsテーブルに集約されているため、このテーブル以外をコピーします。

- サーバ間の接続はSSHを使用する

自動化するためにパスフレーズなしの鍵をつくり、自動接続して本番環境にデータを転送します。

2. サーバの設定

自動化のためにテストサーバから本番サーバにSSHで接続するための環境を作ります。

- 鍵の作成

テストサーバで鍵を作成します。

> ssh-keygen -t rsa

パスフレーズを聞かれますが、入力せずにリターンキーを押し、パスフレーズなしで作成します。 出来上がった公開鍵は本番サーバに転送し、/home/[user]/.ssh/authorized_keysに入れておきます。

3. データベースの更新の設定

mysqldumpでテスト環境のデータベースをdumpして、本番環境にdumpデータを反映します。

まず、テスト環境のデータをコピーし、本番環境に反映するためのSQL文のファイルを生成するシェルスクリプトを用意します。

[dump_modx_data.sh]

#!/bin/bash
work_dir=/home/user/xxxxx
filename=dumpfile.dump
file_path=$work_dir$filename

echo "" > $file_path

# データを削除するSQL文をファイルに書き込み
echo "TRUNCATE TABLE active_users;" >> $file_path
...site_settings 以外のテーブルについて同じ

# データを INSERT するSQL文をファイルに書き込み
mysqldump -u [user] -p[password] [database] --no-create-info \
        --tables [テーブルを列挙] >> $file_path

これで、データベース反映用のSQLスクリプトがダンプされます。

4. データベース反映用のSQLスクリプトを本番サーバで実行する

次に、先ほどのシェルスクリプトで作成したデータベース反映用のSQLスクリプトを本番サーバで実行します。

[insert_dumpfile.sh]

#!/bin/bash
work_dir=/home/user/workdirectory
filename=dumpfile.dump
file_path=$work_dir$filename
#本番サーバで実行するシェルスクリプト
command=remote_commands.sh

#SQLスクリプトを本番サーバにコピー
scp $file_path remoteuser@remoteserver:/temporary/dir/.
#sshでログインしてSQLスクリプトを実行
ssh -l remoteuser remoteserver < $work_dir$command
#作業後に削除
rm -f $file_path

[remote_commands.sh] < 本番サーバー上で実行されるシェルスクリプト

#!/bin/bash
filename=/temporary/dir/dumpfile.dump
mysql -u [user] -p[password] [database] < $filename
rm -f $filename

5. rsync でディレクトリをコピーする

スタイルシートや、画像ファイルはデータベースには保存されていないので、rsyncでディレクトリの同期をして本番サーバに反映します。assets ディレクトリ全体を同期の対象にします。

[rsync_assets.sh]

#!/bin/bash
#rsyncコマンドでassetsディレクトリの同期
#削除されたファイルも反映する
#remoteディレクトリは親ディレクトリを指定する
rsync -a --delete --exclude "cache/docid_*.pageCache.php" /path/to/local remoteserver:/parent/path/to/remote    

6. 反映の実行

これまでに作成したシェルスクリプトを

  1. dump_modx_data.sh
  2. insert_dumpfile.sh
  3. rsync_assets.sh

の順に実行すると自動的にテストサーバーのデータが本番サーバーに反映されます。

3つのファイルを一つにまとめて、cronに登録しておけば、毎晩、自動的にテストサーバーのデータが本番サーバーに反映されます。