BEAR.Sunday

アプリケーションはオブジェクトグラフ

More than 3 years have passed since last update.

HelloWorld

第1日目で試したMyvVendor\HelloWorldアプリは最小構成のアプリケーションです。

bearsunday_2014_adv_2.png

実行可能なBEAR.Sundayアプリケーションの最小構成です。PHPファイルが4つあります。

  • Index.php ページリソース
  • AppModule アプリケーションモジュール

  • www/index.php アプリケーションスクリプト

  • App.php アプリケーションクラス

リソースはMVCフレームワークでいうとモデルに近いものですが、ページリソースはwebのページに対応します。アプリケーションモジュールがDIとAOPの設定を持ちオブジェクトの構成を決定します。

アプリケーションの実行に必要なサービスオブジェクトはアプリケーションオブジェクトが保持しているのでスクリプトはそのサービスを使いアプリケーションを実行します。

アプリケーションスクリプト

アプリケーションの実行手順が記述してあります。

<?php

use BEAR\Resource\Request;
use BEAR\Sunday\Extension\Application\AbstractApp;
use BEAR\Sunday\Extension\Application\AppInterface;
use MyVendor\HelloWorld\AppModule;
use Ray\Di\Injector;

require dirname(__DIR__) . '/vendor/autoload.php';

$app = (new Injector(new AppModule))->getInstance(AppInterface::class);
/** @var $app AbstractApp */

$request = $app->router->match($GLOBALS);
try {
    // resource request
    $page = $app->resource
        ->{$request->method}
        ->uri($request->path)
        ->withQuery($request->query)
        ->request();
    /** @var $page Request */

    // representation transfer
    $page()->transfer($app->responder);

} catch (\Exception $e) {
    $code = $e->getCode() ?: 500;
    http_response_code($code);
    echo $code;
    error_log($e);
}

順に見ていきましょう。5つのステップがあります。

1.オートローダーの登録

require dirname(__DIR__) . '/vendor/autoload.php';

composerのオートロードを利用します。

2.アプリケーションインスタンスの生成

$app = (new Injector(new AppModule))->getInstance(AppInterface::class);

アプリケーションは1つの変数に格納されています。BEAR.Sundayアプリケーションは全体を通してDIが利用されるので、実クラス名がほとんど登場しません。全ての依存の束縛を知るのがAppModuleです。インジェクターはそれを利用しアプリケーションクラスからアプリケーションのインスタンスを生成します。

アプリケーションクラス名ですらもここに登場しないのに注目してください。AppInterfaceに束縛されたアプリケーションクラスが使用されます。

基本的なアプリケーションクラスはこのようなものです。

<?php
namespace BEAR\Sunday\Extension\Application;

use BEAR\Resource\ResourceInterface;
use BEAR\Sunday\Extension\Router\RouterInterface;
use BEAR\Sunday\Extension\Transfer\TransferInterface;

class AbstractApp implements AppInterface
{
    /**
     * @var RouterInterface
     */
    public $router;

    /**
     * @var TransferInterface
     */
    public $responder;

    /**
     * @var ResourceInterface
     */
    public $resource;

    /**
     * @param RouterInterface   $router
     * @param TransferInterface $responder
     * @param ResourceInterface $resource
     */
    public function __construct(
        RouterInterface $router,
        TransferInterface $responder,
        ResourceInterface $resource
    ) {
        $this->router = $router;
        $this->responder = $responder;
        $this->resource = $resource;
    }
}

アプリケーションの振舞いはスクリプトで記述するので、このクラスでは記述されてなく単にスクリプトで使用するサービスオブジェクトを3つ保持しているだけです。

クラスは単純ですが、実際に生成されるインスタンスは複雑です。

http://bearsunday.github.io/readme/print_o/app.html
http://bearsunday.github.io/readme/print_o/app_array.html (詳細)

BEAR.Sundayは適切なDIを使ったオブジェクト指向のアプリケーションでもあります。

オブジェクト指向のアプリケーションは相互に関係のある複雑なオブジェクト網を含んでいます。オブジェクトはあるオブジェクトから所有されているか、他のオブジェクト(またはそのリファレンス)を含んでいるか、そのどちらかでお互いに接続されています。このオブジェクト網をオブジェクトグラフと呼びます。

上記のリンクのオブジェクトグラフの中から検索してMyVendor\HelloWorld\Appを探してみてください。3つのオブジェクトに依存しているルートオブジェクトが見つかるでしょう。それがAppInterfaceに束縛されていたアプリケーションクラスのインスタンスです。

明日はその3つのサービスオブジェクトを使ってアプリケーションを実行するところに続きます。