依存注入とルーティングを実現することにより,独自の近代的なPHPフレームワークを構築する


どのようにして自分でコードを書く能力を高めますか?まず、優れたオープンソースプロジェクトを読み、独自のWebフレームワークやクラスライブラリコンポーネントを書くことを考えます.Web開発者として、我々は通常オブジェクト向けOOPに基づいて開発しているので、オブジェクト向けの設計能力や設計モデルの運用能力が特に重要であり、もちろん開発言語自体の特性や基礎の柔軟な運用もある.
私たちはいくつかの優秀なオープンソースプロジェクトを読んで、中のコード設計を理解して、車輪を勉強して自分を高めることができます.
優れた成熟したweb frameworkでは,ルーティングとhttp処理はwebフレームワークに不可欠であり,フレームワーク全体のサービスオブジェクト依存解析も重要であり,依存注入容器があればクラスの良好なデカップリングを実現できる.
依存注入容器Dependency Injection Container
まず、依存注入とは、実行時またはコンパイル時に修正可能なソフトウェア設計モード(ウィキペディアWikipediaから)をハードコーディングの依存からデカップリングすることを可能にするものです.依存注入は、注入、関数呼び出し、または属性の設定を構築することによって、コンポーネントの依存関係を提供します.
次のコードにはデータベースと対話するアダプタが必要なDatabaseクラスがあります.構造関数にアダプタをインスタンス化し,結合を生成した.これにより、テストが困難になり、Databaseクラスとアダプタが緊密に結合されます.
adapter = new MySqlAdapter;
    }
}

class MysqlAdapter {}

このコードは依存注入で再構成でき,それによってデカップリングできる.
adapter = $adapter;
    }
}

class MysqlAdapter {}

今、私たちは外部を通じてDatabaseクラスに依存し、それ自身に依存するオブジェクトを生み出すのではなく、外部を通じてDatabaseクラスに依存しています.オブジェクトパラメータに依存するメンバー関数を受け入れて設定したり、$adapterプロパティ自体がpublicの場合、直接値を付与したりすることもできます.
依存注入の概念に基づいて,我々のフレームワークはこれらの特性を実現した.
Dependency injection ContainerはPSR-11仕様に基づいて実現され,PHPのクラス反射機能を用いてクラス定義のオブジェクト依存性をインスタンス化した.クラスのオブジェクト依存性を定義するには、コンストラクションメソッド注入(Constructor Injection)、setterメソッドまたは属性注入(Setter Injection)、匿名コールバック関数注入の3つの注入インプリメンテーションがあります.コード例は次のとおりです.
1.構造方法注入(Constructor Injection)
bar = $bar;
    }
}

/*class Bar {

}*/

class Bar {
    public $baz;

    public function __construct(Baz $baz)
    {
        $this->baz = $baz;
    }
}

class Baz {

}

$container = new Container;
$container->set(Foo::class)->addArguments(Bar::class);
$container->set(Bar::class)->addArguments(Baz::class);

$foo = $container->get(Foo::class);

var_dump($foo, $foo->bar);
var_dump($foo instanceof Foo);  // true
var_dump($foo->bar instanceof Bar); // true
var_dump($foo->bar->baz instanceof Baz); // true

2.メソッド注入(Setter Injection)
model = $model;
    }
}

class Model
{
    public $pdo;

    public function setPdo(\PDO $pdo)
    {
        $this->pdo = $pdo;
    }
}

$container = new Container;

$container->set(Controller::class)->addArguments(Model::class);
$container->set(Model::class)->addInvokeMethod('setPdo', [\PDO::class]);

$container->set(\PDO::class)
    ->addArguments(['mysql:dbname=test;host=localhost', 'root', '111111']);

$controller = $container->get(Controller::class);

var_dump($controller instanceof Controller); // true
var_dump($controller->model instanceof Model); // true
var_dump($controller->model->pdo instanceof \PDO); // true

3.匿名コールバック関数注入(Closure callable Injection)
model = $model;
    }
}

class Model
{
    public $pdo;

    public function setPdo(\PDO $pdo)
    {
        $this->pdo = $pdo;
    }
}

$container = new Container;

$container->set(Controller::class, function () {

    $pdo   = new \PDO('mysql:dbname=test;host=localhost', 'root', '111111');
    $model = new Model;

    $model->setPdo($pdo);

    return new Controller($model);
});

$controller = $container->get(Controller::class);

var_dump($controller instanceof Controller); // true
var_dump($controller->model instanceof Model); // true
var_dump($controller->model->pdo instanceof \PDO); // true

自動アセンブリ(auto wiring)
bar = $bar;
        $this->baz = $baz;
    }
}

class Bar
{
    /**
     * @var \AutoWiring\Bam
     */
    public $bam;

    /**
     * Construct.
     *
     * @param \AutoWiring\Bam $bam
     */
    public function __construct(Bam $bam)
    {
        $this->bam = $bam;
    }
}

class Baz
{
    // ..
}

class Bam
{
    // ..
}

$container = new ContainerBuilder;
$container = $container->build();

$foo = $container->get(Foo::class);

var_dump($foo instanceof Foo);           // true
var_dump($foo->bar instanceof Bar);      // true
var_dump($foo->baz instanceof Baz);      // true
var_dump($foo->bar->bam instanceof Bam); // true

ルートルート
ルーティングの使用について説明します.routeはsymfonyのhttp foundationコンポーネントを使用してHTTPリクエスト(http messages)を処理できます.
get('/articles', function () {
    return 'This is articles list';
});

$router->get('/articles/{id:\d+}', function ($id) {
    return 'Article id: ' . $id;
});

/* title      */
$router->get('/articles/{id:\d+}[/{title}]', function ($id, $title) {
    return 'Article id: ' . $id . ', title: ' . $title;
});

/*       */
$router->group('/articles', function () use ($router) {
    $router->get('/list', function() {
        return 'This is articles list';
    });

    $router->get('/detail', function ($id, $title) {
        return 'Article detail id: ' . $id . ', title: ' . $title;
    });
});

$request = new Request();
$routeHandler = $router->getRouteHandler();
$response = $routeHandler->handle($request);
echo $response;

他のORM、cache、filesystem、session、validationなどのコンポーネントはcomposerを使用してユーザーが自由に拡張できます.
プロジェクトアドレスhttps://github.com/parvin92/e...