Edited at

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

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つのサービスオブジェクトを使ってアプリケーションを実行するところに続きます。