Utility

目次

公開期間の集中管理

コンテンツの公開期間を管理する例です。

解凍すると作成される status.php をサービスとして配置します。(libs/services/status.php など。)

app/controllers/before.php に、一例ですが以下の内容を記述します。

// 公開期間を設定
$allowed = array(
    '203.0.113.1',
);
service_status_set('test1', null, '2017-03-31 23:59:59', $allowed);
service_status_set('test2', '2017-04-01 00:00:00', null, $allowed);
service_status_set('test3', '2017-04-20 00:00:00', '2017-04-30 00:00:00', $allowed);

これで

  • test12017-03-31 23:59:59 まで公開される
  • test22017-04-01 00:00:00 から公開される
  • test32017-04-20 00:00:00 から 2017-04-30 00:00:00 まで公開される
  • IPアドレス 203.0.113.1 でアクセスするとすべて公開される

となります。test1 が公開中か否かは service_status_get('test1') で判断できます。(真なら公開、偽なら非公開。)よって例えば

<?php if (service_status_get('test1')) : ?>
    <p>test1</p>
<?php endif ?>
<?php if (service_status_get('test2')) : ?>
    <p>test2</p>
<?php endif ?>
<?php if (service_status_get('test3')) : ?>
    <p>test3</p>
<?php endif ?>

このように記述すると、公開期間中のコンテンツのみ表示することができます。

テストのために、強制的に特定の日時とみなさせることができます。例えば

index.php/?__status=201702011000

このようにアクセスすると、公開期間の判定に使用される日時が2017年2月1日10時0分となります。また

index.php/?__status=

このようにアクセスすると、公開期間の判定に使用される日時がリセットされます。

Cronの集中管理

Cronの実行タイミングをプログラムで管理する例です。

解凍すると作成される cron.php をプラグインとして配置します。(libs/plugins/cron.php など。)

通常の手順で、cronで実行するためのプログラムを作成します。(task/check_update.php など。)

一例ですが task/main.php を作成し、以下の内容を記述します。

<?php

if (!defined('MAIN_PATH')) {
    define('MAIN_PATH', '/var/www/html/test/levis/');
}
require_once MAIN_PATH . 'libs/cores/loader.php';

import('libs/plugins/cron.php');

cron_exec('* * * * *', 'task/check_update.php');
cron_exec('*/5 * * * *', 'task/test1.php');
cron_exec('*/10 * * * *', 'task/test2.php');

この task/main.php のみを、毎分実行されるようにcronに登録します。

* * * * * apache /usr/bin/php /var/www/levis/task/main.php >> /dev/null 2>&1

これで task/main.php 内の以下の部分で、プログラムの実行タイミングを制御できます。

cron_exec('実行タイミング', '実行対象');

これにより、cronの設定は最初に一度だけで、以降はすべてプログラム内で実行タイミングも管理できるようになります。実行タイミングをgitの管理対象にすることも容易です。

今回の場合 task/check_update.php は毎分、task/test1.php は5分ごと、task/test2.php は10分ごとに実行されます。

※1プロセスの負荷が大きくなるので、あまり重い処理の管理には向きません。また処理が止まってしまった場合、以降の処理もすべて実行されないので注意が必要です。

メールの大量送信

メールの一斉大量送信に耐えるために、キューから少しずつ送信する例です。

あらかじめ以下のテーブルを作成しておきます。ここに格納されたデータは、送信対象のメールとみなされます。

#キュー
CREATE TABLE IF NOT EXISTS queues(
    id        BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    created   DATETIME        NOT NULL                COMMENT '作成日時',
    modified  DATETIME        NOT NULL                COMMENT '更新日時',
    deleted   DATETIME                                COMMENT '削除日時',
    started   DATETIME                                COMMENT '送信開始日時',
    completed DATETIME                                COMMENT '送信完了日時',
    failed    INT UNSIGNED    NOT NULL                COMMENT '送信失敗回数',
    mailto    TEXT            NOT NULL                COMMENT '送信先',
    subject   VARCHAR(255)    NOT NULL                COMMENT '件名',
    message   TEXT            NOT NULL                COMMENT '本文',
    header    TEXT                                    COMMENT 'ヘッダ',
    parameter VARCHAR(255)                            COMMENT 'パラメータ',
    PRIMARY KEY(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'キュー';

以下のプログラムで、メールがキューに格納されます。

service_queue_push('送信先アドレス', '件名', '本文');

以下のプログラムで、キュー内のメールが送信されます。

service_queue_send(送信する件数);

つまり、メールを送信したいタイミングで service_queue_push() を実行します。service_queue_send() はCronで定期的に実行し、例えば「1分間に10通ずつ」のように送信するようにします。

※プログラム上問題はなくても、サーバの規約などで1時間に送信できるメールの件数などが制限されていることがあるので、注意が必要です。

プログラムとテストの自動作成

フレームワーク標準実装のものよりも、高機能なScaffoldです。

解凍すると作成される scaffold.php をコントローラとして配置します。(app/controllers/tool/scaffold.php など。)

index.php/tool/scaffold のようにアクセスすると、自動作成のための画面が表示されます。

コードカバレッジの表示

Xdebugを使えば、単体テストの際にコードカバレッジ(テストの網羅率)を取得できます。

WindowsのXAMPPでXdebugを使う場合、一例ですが C:\xampp\php\php.ini の最後に以下を追加します。

[XDebug]
zend_extension = "C:\xampp\php\ext\php_xdebug.dll"

Apacheを再起動し、phpinfo() でxdebugが有効になっていることを確認します。(「xdebug」で検索して項目が表示されていることを確認します。)

この時点でErrorやNoticeなどの結果が見やすいものに変わり、var_dump() の結果も見やすいものに変わります。これでPHP側の準備は完了です。

解凍すると作成される app/services/coverage.php をサービスとして配置します。

単体テストを作成する際に

service('coverage.php');

として coverage.php を読み込み、

service_coverage_start();

でコードカバレッジの記録を開始します。

$coverages = service_coverage_end();

でコードカバレッジの記録を終了します。その後、例えば

service_coverage_output($coverages, array(
  'app/models/members.php',
  'libs/plugins/validator.php',
));

のようにすると、app/models/members.phplibs/plugins/validator.php のコードカバレッジが表示されます。

付属している test/model_members.php がコードカバレッジを表示するモデルの単体テストサンプルです。通常の手順で単体テストを個別に実行すると、コードカバレッジが表示されます。(単体テストを一括で実行した場合は表示されません。)

自動テスト

Selenium風の自動テストを行います。テストシナリオはJavaScriptで作成します。

あらかじめ、app/config.php にある以下の部分を正しく設定しておきます。

/* 公開URL */
$GLOBALS['config']['http_url']  = 'http://localhost';

テストにメール送信が含まれる場合、以下を true に設定して mail/ 内にメールが蓄積されるようにします。

/* メールの記録 */
$GLOBALS['config']['mail_log'] = true;

解凍すると作成されるファイルを上書きで配置します。次に app/views/footer.phpapp/views/admin/footer.php の最後に以下のコードを追加します。

<?php import('app/views/test.php') ?>

つまり、テストしたいすべてのページで、最後に app/views/test.php が読み込まれるようにします。あとは index.php/tool/test にアクセスするとテスト一覧が表示され、クリックすると実行できます。

以下はテストを作成する際の簡単なメモです。

  • テストシナリオは scenario/ に格納されており、JavaScriptで書くことができます。
  • test.scenario に対して関数を配列で格納すると、1ページにつき1関数が実行されます。基本的にはJavaScriptの文法そのままです。
  • scenario/category_create_01.js にあるように、test.loadScenario() を使うとシナリオを使いまわすことができます。
  • scenario/member_create.js にあるように、test.saveScreenshot() を使うとスクリーンショットを撮影できます。スクリーンショットは files/test/ 内に保存されます。(html2canvas.jsを使用。)
  • scenario/member_create.js にあるように、index.php/personal/ を呼び出すとダミーの個人情報をランダムに呼び出せます。
  • scenario/password.js にあるように、index.php/tool/test/mail を呼び出すと蓄積されたメールにアクセスできます。
  • window.alert() などのダイアログで表示されるボタンをクリックすることはできません。(JavaScriptの機能による制限)ダイアログは回避する必要があります。
  • 外部のサイトを操作することはできません。どうしても操作する必要があれば、外部サイトにアクセスするPHPを作成して呼び出すなどする必要があります。