開発

目次

a-blog cmsのモジュール

a-blog cmsのモジュール

a-blog cmsはGETモジュールとPOSTモジュールという独自単位のPHPプログラムによって動作します。

GETモジュール

テンプレートを通して情報を表示するためのプログラムです。テンプレート内で表示制御のテンプレートタグとして動作します。

  • データベースの情報を表示する
  • XML生成用に加工して表示する
  • 外部データを取得して表示する
<html>
<body>
<!-- BEGIN_MODULE Hoge -->
(プログラムの出力結果)
<!-- END_MODULE Hoge -->
</body>
</html>

POSTモジュール

入力・操作に対してアクションを起こすためのプログラムです。フォーム要素内のsubmitまたはimageボタンとして動作します。

  • フォームの情報をデータベースに記録する
  • ボタンを押した後に指定したページに遷移する
  • ファイルをアップロードする
<form action="" method="post">
<input type="submit" name="ACMS_POST_Fuga" value="Fugaモジュールを実行" />
</form>

ディレクトリ構造

/php/
phpファイルの格納ディレクトリ
/php/ACMS/
a-blog cms動作ファイルの格納ディレクトリ
/php/ACMS/GET/
GETモジュールの格納ディレクトリ
/php/ACMS/POST/
POSTモジュールの格納ディレクトリ
/extension/acms/
独自に開発したモジュールの格納ディレクトリ

a-blog cmsのシステム上、GETモジュールはGETディレクトリ内に配置し、同様にPOSTモジュールはPOSTディレクトリ内に配置します。

GETモジュールの基本と雛形

GETモジュールの雛形

<?php

namespace Acms\Custom\GET;

use ACMS_GET;
use Template;

/**
 * extension/acms/GET/Sample.php
 *
 * テンプレート上では、標準のGETモジュールと同様に、
 * '<!-- BEGIN_MODULE Sample --><!--END_MODULE Sample -->' で呼び出されます。
 */
class Sample extends ACMS_GET
{
    function get()
    {
        return 'sample sample';
    }
}

GETモジュールの規約

クラス

GETモジュールとして動作させるために、ACMS_GETを継承してください。
ファイルのパスと命名規則はPSR4に従います。(ただし下位互換性を保つため一部したがっていない場合があります)

**extension/acms の名前空間は Acms\Custom になります。**

この命名規則によりクラスがオートロード(autoload)されますので、requireなどは必要ありません。

extension/acms/GET/Sample.php の場合

namespace Acms\Custom\GET;
use ACMS_GET;

class Sample extends ACMS_GET {
}

extension/acms/GET/Own/Sample.php の場合

namespace Acms\Custom\GET\Own;
use ACMS_GET;

class Sample extends ACMS_GET {
}

出力

GETモジュールは呼び出されるとgetメソッドを実行します。最終的にgetメソッド内で、returnした文字列がモジュール内で出力されます。Smartyなど他のテンプレートエンジンと組み合わせたり、外部から情報を取得したりして情報を出力できます。

returnする文字列にはHTMLタグなどが含まれていても構いません。テンプレートとプログラムを分離させる必要が無い場合は、直接HTMLコンテンツを出力することもできます。

実行例

冒頭の雛形を実行する際のテンプレートと、その実行結果を例示します。GETモジュールは、BEGIN_MODULEから始まり、ENDMODULEで終わる、一連のテンプレートタグによって呼び出されます。テンプレート上のモジュール名は Acms\Custom 以降のクラス名を **(アンダーバー)** 繋ぎにしたものになります。

例: Acms\Custom\GET\Own\Sample -> Own_Sample

テンプレート

<html>
<body>
    <p><!-- BEGIN_MODULE Own_Sample --><!-- END_MODULE Oen_Sample --></p>
</body>
</html>

実行結果

<html>
<body>
    <p>sample sample</p>
</body>
</html>

POSTモジュールの基本と雛形

POSTモジュールの雛形

<?php

namespace Acms\Custom\POST;

use ACMS_POST;

/**
 * extension/acms/POST/Sample.php
 *
 * テンプレート上では、標準のPOSTモジュールと同様に、
 * '<input type="submit" name="ACMS_POST_Sample" value="送信" />' で呼び出されます。
 */
class Sample extends ACMS_POST
{
    function post()
    {
        return $this->Post;
    }
}

POSTモジュールの規約

クラス

POSTモジュールとして動作させるために、ACMS_POSTを継承してください。ファイルのパスと命名規則はPSR4に従います。(ただし下位互換性を保つため一部したがっていない場合があります)

またこの命名規則によりクラスがオートロード(autoload)されますので、requireなどは必要ありません。

extension/acms/POST/Sample.php の場合

<?php

namespace Acms\Custom\POST;

use ACMS_POST; 

class Sample extends ACMS_POST
{
}

extension/acms/POST/Own/Sample.php の場合

<?php

namespace Acms\Custom\POST\Own;

use ACMS_POST; 

class Sample extends ACMS_POST
{
}

実行

POSTモジュールは呼び出されるとpostメソッドを実行します。postメソッド内で処理を実行した後には、最後に$this->Postをreturnします。これは規約上のスペルです。次に起動するGETモジュールとの情報の受け渡しに利用されますが、ここでは言及しません。

制約

POSTモジュール内では、echoやprintなど文字列を直接出力することはしません。表示(View)に関わる部分はGETモジュールで行います。

GETモジュールから表示ページがもつIDを参照する

ページ情報を取得する

URLコンテキスト(参照)で表されるページ情報のうち各種IDをGETモジュール内で取得する方法を説明します。

GETモジュール内でページ情報のうち、例えばエントリーID(以下EID)を取得することができれば、そのモジュールがどのエントリーから呼び出されたかによって参照する情報を変えることができます。基本的には、Entry_BodyやEntry_Headlineなどのモジュールもそのようにページ情報を取得することで、表示すべき情報を決定しデータベースを参照しています。

スコープの設定

下記のようにプロパティを設定することで、$this->bid, $this->cid, $this->eidとして、表示中のページが持つID情報を取得できます。

public $_scope = array(
    'bid' => 'global',
    'cid' => 'global',
    'eid' => 'global',
);

表示中ページの各種IDを参照するサンプル

<?php

namespace Acms\Custom\GET;

use ACMS_GET;

class Hoge extends ACMS_GET
{
    public $_scope = array(
        'bid' => 'global',
        'cid' => 'global',
        'eid' => 'global',
    );

    function get()
    {
        $string[] = 'Global Vars';
        $string[] .= "BID = $this->bid";
        $string[] .= "CID = $this->cid";
        $string[] .= "EID = $this->eid";

        return nl2br(implode("\r\n", $string));
    }
}

出力結果

<!-- bid = 1, cid = 2, eid = 5 の場合 -->
Global Vars<br />
BID = 1<br />
CID = 2<br />
EID = 5

取得できる情報

GETモジュールで現在表示中のページより取得できる情報には以下のものがあります。

プロパティ説明
bidブログIDhttp://sample.com/blog/
uidユーザーIDhttp://sample.com/uid/1/profile.html
cidカテゴリーIDhttp://sample.com/news/
eidエントリーIDhttp://sample.com/news/123.html
keywordキーワードhttp://sample.com/keyword/検索文字/
http://sample.com/?keyword=検索文字
tagタグhttp://sample.com/tags/aaa/
fieldフィールドhttp://sample.com/field/station/あの駅/
start検索の始まり日時http://sample.com/2017-01-01/-/2017-03-03/
end検索の終わり日時http://sample.com/2017-01-01/-/2017-03-03/
pageページ番号http://sample.com/page/2/
order並び順http://sample.com/order/datetime-desc/

GETモジュールのID化

独自に開発したGETモジュールも、標準のビルドインモジュールと同様にモジュールID化する事ができます。ここでは、モジュールID化の仕方と、モジュールID化によってどのような動作になるかみていきます。

モジュールID化できるようにする

まずモジュールID化に対応するため、モジュールID作成時に独自モジュールを選択できるようにします。

ご利用のテーマに以下のファイルを作成し、セレクト要素を記述します。

  • /themes/ご利用テーマ/admin/module/select.user.html
<optgroup label="独自モジュール">
	<option value="Sample"{name:selected#Sample}>独自モジュール(Sample)</option>
</optgroup>

以下の仕様でセレクト要素を記述してください。

  • 値: GETモジュールの呼び出しと同じ値
  • 変数: {name:selected#セレクトの値}

この実装を行う事でモジュールIDの作成ができるようになります。

モジュールIDの作成

モジュールIDの作成ができるようになったので、モジュールIDを作成してみます。以下画像のように作成できると思います。


独自モジュールのID作成画面

独自モジュールのID作成画面


モジュールID化でのコンテキスト情報の取得

モジュールID化した時のコンテキスト情報の取得について解説します。モジュールID化する前は、以下のコードを書く事により、そのページの情報を取得できていました。

var $_scope = array(
  'bid' => 'global',
  'cid' => 'global',
  'eid' => 'global',
);

function get()
{
  $string[] = 'Global Vars';
  $string[] .= "BID = $this->bid";
  $string[] .= "CID = $this->cid";
  $string[] .= "EID = $this->eid";

  return nl2br(implode("\r\n", $string));
}

しかし、モジュールID化したモジュールを利用すると $this->cid や $this->eid で、そのページのコンテキスト情報を取得できなくなります。(bidだけはモジュールID化しても取得できます。)

モジュールID化したモジュールを利用すると、そのままではコンテキスト情報は取得できない。

<!-- BEGIN_MODULE Sample id="sample" --><!--END_MODULE Sample -->

ではどのようにURLコンテキスト情報を取得するかというとモジュールID管理画面で取得したい情報の引数項目にチェックをつけます。これによりURLコンテキストの情報を取得できるようになります。


引数の設定画面

引数の設定画面


これでプログラム側で、以下のようにURLコンテキスト情報を取得できるようになりました。

$string[] = 'Global Vars';
$string[] .= "BID = $this->bid";
$string[] .= "CID = $this->cid";
$string[] .= "EID = $this->eid";

return nl2br(implode("\r\n", $string));

ここまで、$this->cid や $this->eid はURLコンテキスト情報(つまりURLの情報)を取得すると説明してきましたが、モジュールID化する事により、そうでなくなる場合があります。以下の設定画面をみてください。


引数の設定画面2

引数の設定画面2


この場合、表示しているURLが別のカテゴリーや、トップページなどカテゴリー情報がない場合でも、常に $this->cid はお知らせのカテゴリーIDを返すようになります。このようにモジュールID化するとモジュールIDの設定により取得してくる情報は変わるようになります。

モジュールID化時のコンテキスト情報の取得まとめ

引数チェック固定値$this->cid などのプロパティ
ありなしURLの情報を取得
なしありモジュールIDで設定した固定値を取得
ありありURLに該当の情報があればURLの情報を取得。ない場合は固定値を取得

モジュールIDの設定と関係なく表示ページのURLコンテキストが取得したい場合は、定数を利用します。

項目定数
ブログIDBID
ユーザーIDUID
カテゴリーIDCID
エントリーIDEID
キーワードKEYWORD
タグTAG
フィールドFIELD
日時検索のスタートSTART
日付検索のエンドEND
ページ番号PAGE
並び順ORDER

テンプレートエンジン - 1(基礎)

a-blog cmsのテンプレートエンジン

a-blog cmsは独自のテンプレートエンジンを備え、標準のGETモジュールはすべてこのテンプレートエンジンを通して実装されています。ここではそのTemplateクラスの使用方法を説明します。

Templateクラス

Templateクラスはテンプレートをもとに、与えられたデータに応じて情報を加工して出力します。

$Tpl = new Template($this->tpl);

$this->tpl

$this->tpl には、テンプレート上における、BEGIN_MODULE〜END_MODULEまでの間の文字列が自動で格納されています。

<html>
<body>
    <!-- BEGIN_MODULE Sample_UseTpl -->
    <!-- ここから -->
    <p>{hoge} and {fuga}</p>
    <!-- BEGIN foo --><p>{bar}</p><!-- END foo -->
    <!-- ここまでが$this->tplには入ってくる -->
    <!-- END_MODULE Sample_UseTpl -->
</body>
</html>

addメソッド

addメソッドは、ブロックや変数をテンプレートに加えるメソッドです。

  • ブロック: ある範囲を表示するためや、繰り返し(ループ)をする テンプレート要素
  • 変数: 動的に表示を変わってくるテンプレート要素

サンプル

// get module
$Tpl = new Template($this->tpl);

// ブロックの追加
$Tpl->add('notFound');

// 変数の追加
$Tpl->add(null [
  'hoge' => 'hello world.'
]);

// html
<h1>{hoge}</h1>

<!-- ブロックの追加がされていないと以下の表示はされない -->
<!-- BEGIN notFound -->404 Not Found<!-- END notFound -->

getメソッド

getメソッドは、加えられた情報をもとにテンプレート処理を解決し、その結果の文字列を取得するメソッドです。通常はreturnするときにそのまま呼び出します。

サンプル

function get()
{
  $Tpl = new Template($this->tpl);

  $Tpl->add('notFound');
  $Tpl->add(null, [
    'hoge' => 'hello world.'
  ]);

  return $Tpl->get();
}

ACMS_Correctorクラス (校正オプションの利用)

モジュールのテンプレート内で校正オプションを利用する場合は、ACMS_Correctorクラスのインスタンスを同時に渡します。 これにより以下のように変数に対して校正オプションを利用できるようになります。

サンプル

$Tpl = new Template($this->tpl, new ACMS_Corrector());

$Tpl->add(null, [
  'hoge' => date('Y-m-d H:i:s'),
]);

// html
<p>{hoge}[datetime('Y年m月d日 H時i分)]</p>

// 表示
<p>2017年01月01日 12時59分</p>

全体のサンプル(まとめ)

テンプレート(HTML形式)

<html>
<body>
    <!-- BEGIN_MODULE Sample_UseTpl -->
    <p>{hoge} and {fuga}</p>
    <!-- BEGIN foo --><p>{bar}</p><!-- END foo -->
    <!-- END_MODULE Sample_UseTpl -->
</body>
</html>

Sample_UseTplモジュール

<?php

namespace Acms\Custom\GET\Sample;

use ACMS_GET;
use Template;
use ACMS_Corrector;

/*
 * path: extension/acms/GET/Sample/UseTpl.php
 */
class UseTpl extends ACMS_GET
{
  function get()
  {
    // Templateクラス
    $Tpl  = new Template($this->tpl, new ACMS_Corrector());

    // <!-- BEGIN foo --> ~ <!-- END foo --> の中の {bar} にテキストを代入
    $Tpl->add('foo', array('bar' => 'fooブロックの中のbar変数'));

    // ブロックを介さない、モジュール直下の変数 {hoge} と {fuga} にテキストを代入
    $Tpl->add(null, [
      'hoge' => 'ほげ', 'fuga' => 'ふが'
    ]);

    // テンプレートを処理済みの文字列としてreturn
    return $Tpl->get();
  }
}

実行結果

<html>
<body>
    <p>ほげ and ふが</p>
    <p>fooブロックの中のbar変数</p>
</body>
</html>

テンプレートエンジン - 2(ループブロック、入れ子のブロック)

ブロック制御

前回はTemplateクラスのブロックと変数の制御について説明しました。今回はのようなループするブロックと、入れ子構造になっているブロックの出力について説明します。

ループの追加を行う

Templateクラスのaddメソッドは次のような引数を持ちます。

$Tpl->add( ブロック名(文字列), ブロック内変数( 連想配列 ) );

以下のようにaddメソッドで同じ名前のブロックを繰り返し追加することでループ構造を作ります。

テンプレート (HTML形式)

<html>
<body>
    <!-- BEGIN_MODULE Sample_Loop -->
    <ul>
        <!-- BEGIN data:loop -->
        <li>id : {id} {name} ( {kana} ) </li>
        <!-- END data:loop -->
    </ul>
    <!-- END_MODULE Sample_Loop -->
</body>
</html>

Sample_Loopモジュール

<?php

namespace Acms\Custom\GET\Sample;

use ACMS_GET;
use Template;
use ACMS_Corrector;

class Loop extends ACMS_GET
{
    function get()
    {
        $Tpl = new Template($this->tpl, new ACMS_Corrector());

        $loopData = array();
        $loopData[] = array(
            'id'       => '1',
            'name'     => '山田太郎',
            'kana'     => 'やまだたろう',
        );

        $loopData[] = array(
            'id'       => '2',
            'name'     => '鈴木次郎',
            'kana'     => 'すずきじろう',
        );

        $loopData[] = array(
            'id'       => '3',
            'name'     => '佐藤三郎',
            'kana'     => 'さとうさぶろう',
        );

        foreach ( $loopData as $loop ) {
            $Tpl->add('data:loop', $loop);
        }

        return $Tpl->get();
    }
}

実行結果

<html>
<body>
    <ul>
        <li>id : 1 山田太郎 ( やまだたろう )</li>
        <li>id : 2 鈴木次郎 ( すずきじろう )</li>
        <li>id : 3 佐藤三郎 ( さとうさぶろう )</li>
    </ul>
</body>
</html>

入れ子の順番

ブロックの追加は、入れ子の中の深い位置のブロック(子にあたるブロック)から順に追加します。ブロックを配列で表現して追加するときは、配列の先頭が追加する目標のブロック名であり、以降は親のブロック名をあらわすことに注意してください。

入れ子のテンプレート

<html>
<body>
<!-- BEGIN_MODULE Sample_Nest -->
    <!-- BEGIN year -->
        <!-- BEGIN month -->
            <!-- BEGIN day -->
            <!-- END day -->
        <!-- END month -->
    <!-- END year -->
<!-- END_MODULE Sample_Nest -->
</body>
</html>

Sample_Nestモジュール

<?php

namespace Acms\Custom\GET\Sample;

use ACMS_GET;
use Template;
use ACMS_Corrector;

class Nest extends ACMS_GET
{
    function get()
    {
        $Tpl     = new Template($this->tpl, new ACMS_Corrector());

        $Tpl->add( array('day', 'month', 'year') );

        $Tpl->add( array('month', 'year') );

        $Tpl->add( 'year' );

        return $Tpl->get();
    }
}

入れ子構造のループを追加する

ひとつのループの中で更に別のループがあるような入れ子型のループを作成します。以下のように、ブロック名の引数を配列にすることでループの中に別のループを追加できます。この入れ子型のブロックの追加はループに限らず共通です。

以下はカテゴリーのループ構造の中に、エントリーのループが加わる処理の例です。

    foreach ( $categories as $category ) {
        foreach ( $entries as $entry ) {
            // entry:loopを追加
            $Tpl->add(array('entry:loop', 'category:loop'), $entry);
        }
        // category:loopを追加
        $Tpl->add('category:loop', $category);
    }

テンプレートエンジン - 3(render method)

ここまで、ブロックの制御の仕方や変数の追加の仕方などを説明してきましたが、Ver. 2.6.1で追加された render メソッドを利用するともっと簡単にテンプレートエンジンを扱うことができます。

まずは、今まで説明してきたやり方とrenderメソッドを使ったサンプルで同じものを出力してみて、どう違うか比較してみましょう。

出力するテンプレート(HTML)

<!-- BEGIN_MODULE Sample -->
<!-- BEGIN message -->
ブロックの表示
<!-- END message -->

<!-- BEGIN message2 -->
<p>{msg}</p>
<!-- END message2 -->  

<p>件数: {count}件</p>

<ul>
  <!-- BEGIN data:loop -->
  <li>{id}: {name}</li>
  <!-- END data:loop -->
</ul>
<!-- END_MODULE Sample -->

今までの方法

function get()
{
  $Tpl = new Template($this->tpl, new ACMS_Corrector());

  $data = [
    [
      'id' => 'aaa',
      'name' => '山田太郎',
    ],
    [
      'id' => 'bbb',
      'name' => '鈴木次郎',
    ],
    [
      'id' => 'ccc',
      'name' => '佐藤三郎',
    ],
  ];

  foreach ( $data as $i => $line ) {
    $line['data.i'] = ++$i;
    $Tpl->add('data:loop', $line);
  }

  $Tpl->add('message');
  $Tpl->add('message2', [
    'msg' => 'ブロック内の変数',
  ]);

  $Tpl->add(null, [
    'count' => count($data),
  ]);

  return $Tpl->get();
}

renderメソッドを使った方法

function get()
{
  $Tpl = new Template($this->tpl, new ACMS_Corrector());

  $data = [
    [
      'id' => 'aaa',
      'name' => '山田太郎',
    ],
    [
      'id' => 'bbb',
      'name' => '鈴木次郎',
    ],
    [
      'id' => 'ccc',
      'name' => '佐藤三郎',
    ],
  ];

  $obj = [
    'data' => $data,
    'count' => count($data),
    'message' => (object)[],
    'message2' => [
      'msg' => 'ブロック内の変数',
    ]
  ];

  return $Tpl->render($obj);
}

どうでしょうか? 今までのやり方は、その都度テンプレートを組み立てていくイメージですが、renderメソッドはデータの組み立てに集中し最後にrenderメソッドに渡すイメージです。

これにより、a-blog cms独特なテンプレートエンジンのルールを覚えなくても、データを連想配列または、オブジェクトで用意するだけで簡単に実装ができるようになります。

render 仕様

それでは render メソッドの詳しい仕様を見ていきましょう。

引数

まず、renderメソッドに渡す引数は、連想配列 もしくは オブジェクト に対応しています。

連想配列形式

$data = [
  'hoge1' => 'value1',
  'hoge2' => 'value2',
];

return $Tpl->render($data);

オブジェクト形式

$data = new stdClass();

$data->hoge1 = 'value1';
$data->hoge2 = 'value2';

return $Tpl->render($data);

変数

変数になるデータは連想配列の値、もしくはオブジェクトのプロパティの値が、配列、オブジェクトでないスカラー型の場合に変数になります。 注意点として、論理値(boolean)は 1 or 0 に変換されて表示されますのでお気をつけください。

変数になるデータ形式表示
論理値 (boolean)1 or 0
整数 (integer)そのまま
浮動小数点数 (float, double も同じ)そのまま
文字列 (string)そのまま

ブロック

ブロックは、連想配列の値、もしくはオブジェクトのプロパティの値が、連想配列またはオブジェクトの場合にブロックになります。

その値が空のオブジェクトや連想配列の場合は、ブロックのみの出力になり、データ(連想配列やプロパティ)がある場合は、そのブロック内で変数が利用できます。

<!-- 例1 変数をもったブロックの出力(連想配列の場合) -->
<!-- BEGIN hoge -->{val}<!-- END hoge -->
$data = [
  'hoge' => [
    'val' => 'value',
  ]
];

<!-- 例2 空のブロック出力(オブジェクトの場合)-->
<!-- BEGIN hoge -->hoge<!-- END hoge -->
$data = new stdClass();
$data->hoge = new stdClass();

ループブロック

ループブロックは、連想配列の値もしくはオブジェクトのプロパティの値が、配列の場合にループブロックになります。連想配列でない ところに注意してください。

また、ループブロック名は、 連想配列のkey名:loop になります。

$data = [
  [
    'id' => 'aaa',
    'name' => '山田太郎',
  ],
  [
    'id' => 'bbb',
    'name' => '鈴木次郎',
  ],
  [
    'id' => 'ccc',
    'name' => '佐藤三郎',
  ],
];

return $Tpl->render(['data' => $data]);

// html
<!-- BEGIN data:loop -->
<li>{id}: {name}</li>
<!-- END data:loop -->

上の例では配列の中身が連想配列だったので、そのまま連想配列が変数として利用できました。では、配列の中身がスカラー型だった場合はどうでしょうか。

$data = ['山田太郎', '鈴木次郎',  '佐藤三郎'];

return $Tpl->render(['data' => $data]);

// html
<!-- BEGIN data:loop -->
<li>{data}</li>
<!-- END data:loop -->

この場合は、上記のコードのように連想配列のkey名がそのままループ内の変数として利用できます。

特殊なブロック、変数

さらにループブロック内では、自動的に生成される特殊なブロックと変数を利用できます。

添字変数

ループ内で {連想配列のkey名.i} という変数が使えるようになります。これは、ループ回数を出力するものになります。

$data = ['山田太郎', '鈴木次郎',  '佐藤三郎'];

return $Tpl->render(['data' => $data]);

// html
<!-- BEGIN data:loop -->
<li>{data.i}:{data}</li>
<!-- END data:loop -->

// 結果
<li>1:山田太郎</li>
<li>2:鈴木次郎</li>
<li>3:佐藤三郎</li>
glueブロック

ループ回数 - 1回出力される glueブロックも出力されるようになります。ブロック名は 連想配列のkey名:glue です。使いどころとしては配列をカンマでつなげたい場合などに利用できます。

$data = ['山田太郎', '鈴木次郎',  '佐藤三郎'];

return $Tpl->render(['data' => $data]);

// html
<!-- BEGIN data:loop -->
  <!-- BEGIN data:glue -->, <!-- END data:glue -->{data}
<!-- END data:loop -->

// 結果
山田太郎, 鈴木次郎,  佐藤三郎

Ver. 2.6.1以上をご利用の場合は、renderメソッドで独自モジュールを作っていくほうが、簡潔に記述できますのでrederメソッドをお勧めします。

データベース関係クラスの使用(1) DB編

DBクラス

DBクラスは、a-blog cmsで使用しているデータベースへの接続を支援するクラスです。

インスタンスの作成

// DBクラス
DB = DB::singleton(dsn());

dsn関数は、a-blog cmsの組み込み関数で、config.server.phpに保存されているデータベース情報を、連想配列で返します。以降のサンプルで紹介されている箇所以外で、使用することはほとんどありません。

クエリーの発行

基本的なクエリーの発行と、結果を全件取得するサンプルを下記に示します。

$DB = DB::singleton(dsn());
$q = '`SELECT * FROM `acms_entry` LIMIT 0, 10';

/**
 * query
 * @param string $query
 * @param string $mode
 * @return mixed $response
 */

// クエリーの結果を全件取得する
$all = $DB->query($q, 'all');

クエリー発行の各モードの挙動

queryメソッドは、複数のモードを持ちます。それぞれのモードで、返り値が異なります。

all - 結果から全行を取得

結果を多次元配列として、全行取得します。

$q = '`SELECT * FROM `acms_entry` LIMIT 0, 10';
$all = $DB->query($q, 'all');

var_dump($all);
/*
dumpの結果

array(10)(
    [0] => array(21)(
        'entry_id' => 1,
        'entry_title' => 'サンプルレコード',
        'entry_code' => 'entry-1.html',
        ...
    ),
    [1] => array(21)(
        'entry_id' => 2,
        'entry_title' => 'サンプルレコード2',
        'entry_code' => 'entry-2.html',
        ...
    ),
    [2] => array(21)(
        'entry_id' => 3,
        'entry_title' => 'サンプルレコード3',
        'entry_code' => 'entry-3.html',
        ...
    ),
    ...
);
*/

row - 結果から1行を取得

結果から1行のみ取得します。結果が複数行だった場合は、先頭の1行を連想配列で返します。

$q = '`SELECT * FROM `acms_entry` WHERE `entry_id` = 1';
$row = $DB->query($q, 'row');

var_dump($row);
/*
dumpの結果

array(21)(
    'entry_id' => 1,
    'entry_title' => 'サンプルレコード',
    'entry_code' => 'entry-1.html',
    ...
)
*/

one - 結果から1つの値を取得

結果から1つの値を取得します。結果が複数列をもつ場合は、先頭列の値を取得します。また、結果が複数行であった場合は、先頭の1行が対象行となります。

$q = '`SELECT `entry_title` FROM `acms_entry` WHERE `entry_id` = 1';
$one = $DB->query($q, 'one');

var_dump($row);
/*
dumpの結果 

string "サンプルレコード"
*/

fetch - 結果を1行ずつ取得

結果を1行ずつ取得できるように、クエリーの結果をDBインスタンス内で保持します。保持された結果は、fetchメソッドで1行ずつ取得します。

fetchメソッドの返り値はrowモードと同じ挙動を示しますが、取得すべき結果が無くなった場合は、falseを返します。

$q = '`SELECT * FROM `acms_entry` LIMIT 0, 10';
$DB->query($q, 'fetch');

/**
 * fetch
 * @param string $query
 * @return array $row
 */
while ( $row = $DB->fetch($q) ) {
   echo $row['entry_title']."\r\n";
}

/*
echo の結果

サンプルレコード
サンプルレコード2
サンプルレコード3
...
..
.

*/

exec - クエリーの成否をbooleanで取得

クエリーの成否のみをbooleanで返します。INSERT、UPDATE、DELETEなどの発行時に使用します。

$q = 'INSERT INTO acms_entry (col1, col2, col3....) VALUES(val1, val2, val3...);'
$res = $DB->query($q, 'exec');

if ( $res == true ) {
   // success
} else {
   // fail
}

データベース関係クラスの使用(2) SQL Select編

SQLクラス

SQLクラスは、a-blog cmsで使用しているSQL文の作成を支援するクラスです。DBクラスとあわせて使用します。今回はSelect文を発行するケースで順にサンプルを紹介します。

基本のSELECTからテンプレートへの追加まで

// Templateクラス
$Tpl = new Template($this->tpl, new ACMS_Corrector());

// DBクラス @dsn()はconfig.server.php で定義されたデータベース情報を返します
$DB = DB::singleton(dsn());

// SQLクラス
$SQL = SQL::newSelect('entry');

// 対象の列を設定
$SQL->addSelect('entry_title');
$SQL->addSelect('entry_datetime');

// SQLを組み立てる
$q = $SQL->get(dsn());

// クエリーを実行して結果を取得
$all = $DB->query($q, 'all');

// 取得したデータをentry:loopとしてテンプレートに追加
foreach ( $all as $row ) {
    $Tpl->add('entry:loop', $row);
}

return $Tpl->get();

日付が新しい順に並び替えて10件取得する

$SQL =  SQL::newSelect('entry');

$SQL->addSelect('entry_title');
$SQL->addSelect('entry_datetime');

// エントリーの日付で降順に並び替える
$SQL->setOrder('entry_datetime', 'DESC');

// 取得数を10までに制限する
$SQL->setLimit(10);

$q = $SQL->get(dsn());
$all = $DB->query($q, 'all');

?>

カテゴリーごとにエントリーの数をカウントする

$SQL = SQL::newSelect('entry');

// 合計をカウントする ( MAX・MINなど集計関数 )
$SQL->addSelect('*', 'amount', null, 'COUNT');

// カテゴリーIDでグループする
$SQL->setGroup('entry_category_id');

$q = $SQL->get(dsn());
$all = $DB->query($q, 'all');

WHEREの処理

entry_blog_idが1のエントリー

$SQL = SQL::newSelect('entry');
$SQL->setSelect('*');


// 第三引数以降は省略できます
$SQL->addWhereOpr('entry_blog_id', 1, '=', 'AND');

$q = $SQL->get(dsn());
$all = $DB->query($q, 'all');

entry_category_idが1 または entry_user_idが1のエントリー

$SQL = SQL::newSelect('entry');
$SQL->setSelect('*');

// entory_category_idが1
$SQL->addWhereOpr('entry_category_id', 1);

// または entry_user_idが1
$SQL->addWhereOpr('entry_user_id', 1, '=', 'OR');

$q = $SQL->get(dsn());
$all = $DB->query($q, 'all');

entry_statusがdraft(下書き) か close(非公開)であるエントリー

$SQL = SQL::newSelect('entry');
$SQL->setSelect('*');

// draft か close である ( IN )
$SQL->addWhereIn('entry_status_id', array('draft', 'close'));

$q = $SQL->get(dsn());
$all = $DB->query($q, 'all');

title, body, nameのいずれかに指定した文字列を含むコメント

$keyword   = 'hogehoge';

$SQL = SQL::newSelect('comment');
$SQL->addSelect('*');

$SQL->addWhereOpr('CONCAT(comment_title, comment_body, comment_name)', "%$keyword%", 'LIKE');

$q = $SQL->get(dsn());
$all = $DB->query($q, 'all');

バージョンアップ時に上書きされないユーザー定義php (config.user.php)について

サーバーのドメインやデータベースの情報などはconfig.server.phpで設定します。ただし、このファイルは自動アップデートを利用すると上書き保存されてしまうため、最初から記述されている設定以外を定義しておくことができません。

そこで、Ver.2.10より config.user.php を用意しました。このファイルに記述されている内容は config.server.phpがロードされるタイミングと同じタイミングでロードされ、CMSのアップデートによって上書きされません。 CMS起動時に処理したい内容はここに記述しておきましょう。