マイクロアプリケーション
========================
マイクロフレームワークライクなアプリケーションを構築することができます。
PHPアプリケーションを最小のコードで書くことが可能です。
マイクロアプリケーションは、小規模アプリケーションやAPI、プロトタイプを実装するのに適切です。
.. code-block:: php
get(
"/say/welcome/{name}",
function ($name) {
echo "
Welcome $name!
";
}
);
$app->handle();
マイクロアプリケーションの作成
------------------------------
:doc:`Phalcon\\Mvc\\Micro <../api/Phalcon_Mvc_Micro>` は、マイクロアプリケーションを実装するためのクラスです。
.. code-block:: php
` は、ルーティングを管理します。
ルートは、常に/から開始しなければいけません。ルートを設定する際に、HTTPメソッドを任意に制限することができます。
指定したHTTPメソッドに一致したリクエストがあった場合にのみ、正しくルーティングされます。
以下の例では、GETメソッドのルーティングの設定方法を表記しています。
.. code-block:: php
get(
"/say/hello/{name}",
function ($name) {
echo "Hello! $name
";
}
);
"get"メソッドは、HTTPメソッドのGETであることを指しています。:code:`/say/hello/{name}` というルートは、:code:`{$name}` というパラメータを持っています。
このパラメータは、無名関数で設定されているハンドラーに渡されます。ハンドラーは、ルートが一致した場合のみ実行されます。
以下の例では、何種類かあるハンドラーの設定方法を表記しています。
.. code-block:: php
Hello! $name";
}
$app->get(
"/say/hello/{name}",
"say_hello"
);
// 静的メソッドを使う
$app->get(
"/say/hello/{name}",
"SomeClass::someSayMethod"
);
// オブジェクト内のメソッドを使う
$myController = new MyController();
$app->get(
"/say/hello/{name}",
[
$myController,
"someAction"
]
);
// 無名関数
$app->get(
"/say/hello/{name}",
function ($name) {
echo "Hello! $name
";
}
);
:doc:`Phalcon\\Mvc\\Micro <../api/Phalcon_Mvc_Micro>` はHTTPメソッドを指定するためのメソッドを提供しています。
ルートは以下のように制限できます。
.. code-block:: php
get(
"/api/products",
"get_products"
);
// HTTP メソッドが POST の場合
$app->post(
"/api/products/add",
"add_product"
);
// HTTP メソッドが PUT の場合
$app->put(
"/api/products/update/{id}",
"update_product"
);
// HTTP メソッドが DELETE の場合
$app->delete(
"/api/products/remove/{id}",
"delete_product"
);
// HTTP メソッドが OPTIONS の場合
$app->options(
"/api/products/info/{id}",
"info_product"
);
// HTTP メソッドが PATCH の場合
$app->patch(
"/api/products/update/{id}",
"info_product"
);
// HTTP メソッドが GET または POST の場合
$app->map(
"/repos/store/refs",
"action_product"
)->via(
[
"GET",
"POST",
]
);
To access the HTTP method data :code:`$app` needs to be passed into the closure:
.. code-block:: php
post(
"/api/products/add",
function () use ($app) {
echo $app->request->getPost("productID");
}
);
パラメータ付きのルーティング
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
パラメータ付きのルートは、上記の例のように簡単に設定できます。パラメータ名は括弧で括る必要があります。
パラメータのフォーマットは正規表現を使用して設定できます。
.. code-block:: php
get(
"/posts/{year:[0-9]+}/{title:[a-zA-Z\-]+}",
function ($year, $title) {
echo "Title: $title
";
echo "Year: $year
";
}
);
トップルート
^^^^^^^^^^^^^^
通常、アプリケーションのトップルートは、/となり、ほとんどの場合、GETメソッドにてアクセスされると思います。
.. code-block:: php
get(
"/",
function () {
echo "Welcome!
";
}
);
Rewriteルール
^^^^^^^^^^^^^
URisのrewriteは、以下のようにApacheで制限します。
.. code-block:: apacheconf
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((?s).*)$ index.php?_url=/$1 [QSA,L]
レスポンス
----------------------
ハンドラーの中では自由にレスポンスを設定できます。直接出力したり、テンプレートエンジンを使用したり、ビューをインクルードしたり、JSONを返したり、など。
.. code-block:: php
get(
"/say/hello",
function () {
echo "Hello! $name
";
}
);
// Requiring another file
$app->get(
"/show/results",
function () {
require "views/results.php";
}
);
// Returning JSON
$app->get(
"/get/some-json",
function () {
echo json_encode(
[
"some",
"important",
"data",
]
);
}
);
レスポンスについての詳細は、:doc:`"response" ` を参照してください。
.. code-block:: php
get(
"/show/data",
function () use ($app) {
// Set the Content-Type header
$app->response->setContentType("text/plain");
$app->response->sendHeaders();
// Print a file
readfile("data.txt");
}
);
レスポンスオブジェクトを作成して、ハンドラーから返す方法もあります。
.. code-block:: php
get(
"/show/data",
function () {
// Create a response
$response = new Phalcon\Http\Response();
// Set the Content-Type header
$response->setContentType("text/plain");
// Pass the content of a file
$response->setContent(file_get_contents("data.txt"));
// Return the response
return $response;
}
);
リダイレクト
-------------------
リダイレクトによって、別のルートへフォワードすることができます。
.. code-block:: php
post("/old/welcome",
function () use ($app) {
$app->response->redirect("new/welcome");
$app->response->sendHeaders();
}
);
$app->post("/new/welcome",
function () use ($app) {
echo "This is the new Welcome";
}
);
ルーティングのURL生成
--------------------------
:doc:`Phalcon\\Mvc\\Url ` では、設定したルーティングに基づいてURLを作成できます。
これを使用するためには、ルートに名前を定義する必要があります。
.. code-block:: php
get(
"/blog/{year}/{title}",
function ($year, $title) use ($app) {
// ... Show the post here
}
)->setName("show-post");
// Produce a URL somewhere
$app->get(
"/",
function () use ($app) {
echo ' "show-post",
"title" => "php-is-a-great-framework",
"year" => 2015
]
), '">Show the post';
}
);
Interacting with the Dependency Injector
----------------------------------------
In the micro application, a :doc:`Phalcon\\Di\\FactoryDefault ` services container is created implicitly; additionally you
can create outside the application a container to manipulate its services:
.. code-block:: php
set(
"config",
function () {
return new IniConfig("config.ini");
}
);
$app = new Micro();
$app->setDI($di);
$app->get(
"/",
function () use ($app) {
// Read a setting from the config
echo $app->config->app_name;
}
);
$app->post(
"/contact",
function () use ($app) {
$app->flash->success("Yes!, the contact was made!");
}
);
The array-syntax is allowed to easily set/get services in the internal services container:
.. code-block:: php
"localhost",
"username" => "root",
"password" => "secret",
"dbname" => "test_db"
]
);
};
$app->get(
"/blog",
function () use ($app) {
$news = $app["db"]->query("SELECT * FROM news");
foreach ($news as $new) {
echo $new->title;
}
}
);
Not-Found ハンドラ
------------------
未定義のルートにアクセスした場合、マイクロアプリケーションでは、"Not-Found"ハンドラーが実行されます。
.. code-block:: php
notFound(
function () use ($app) {
$app->response->setStatusCode(404, "Not Found");
$app->response->sendHeaders();
echo "This is crazy, but this page was not found!";
}
);
マイクロアプリケーションにおけるモデル
--------------------------------------
マイクロアプリケーションで、:doc:`Models ` が使用することができます。
モデルは自動読み込みで行う必要があります。
.. code-block:: php
registerDirs(
[
__DIR__ . "/models/"
]
)->register();
$app = new \Phalcon\Mvc\Micro();
$app->get(
"/products/find",
function () {
$products = Products::find();
foreach ($products as $product) {
echo $product->name, "
";
}
}
);
$app->handle();
マイクロアプリケーション イベント
---------------------------------
:doc:`Phalcon\\Mvc\\Micro <../api/Phalcon_Mvc_Micro>` is able to send events to the :doc:`EventsManager ` (if it is present).
Events are triggered using the type "micro". The following events are supported:
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
| Event Name | Triggered | Can stop operation? |
+=====================+============================================================================================================================+======================+
| beforeHandleRoute | The main method is just called, at this point the application doesn't know if there is some matched route | Yes |
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
| beforeExecuteRoute | A route has been matched and it contains a valid handler, at this point the handler has not been executed | Yes |
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
| afterExecuteRoute | Triggered after running the handler | No |
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
| beforeNotFound | Triggered when any of the defined routes match the requested URI | Yes |
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
| afterHandleRoute | Triggered after completing the whole process in a successful way | Yes |
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
In the following example, we explain how to control the application security using events:
.. code-block:: php
attach(
"micro:beforeExecuteRoute",
function (Event $event, $app) {
if ($app->session->get("auth") === false) {
$app->flashSession->error("The user isn't authenticated");
$app->response->redirect("/");
$app->response->sendHeaders();
// Return (false) stop the operation
return false;
}
}
);
$app = new Micro();
// Bind the events manager to the app
$app->setEventsManager($eventsManager);
ミドルウェアイベント
--------------------
In addition to the events manager, events can be added using the methods 'before', 'after' and 'finish':
.. code-block:: php
before(
function () use ($app) {
if ($app["session"]->get("auth") === false) {
$app["flashSession"]->error("The user isn't authenticated");
$app["response"]->redirect("/error");
// Return false stops the normal execution
return false;
}
return true;
}
);
$app->map(
"/api/robots",
function () {
return [
"status" => "OK",
];
}
);
$app->after(
function () use ($app) {
// This is executed after the route is executed
echo json_encode($app->getReturnedValue());
}
);
$app->finish(
function () use ($app) {
// This is executed when the request has been served
}
);
You can call the methods several times to add more events of the same type:
.. code-block:: php
finish(
function () use ($app) {
// First 'finish' middleware
}
);
$app->finish(
function () use ($app) {
// Second 'finish' middleware
}
);
Code for middlewares can be reused using separate classes:
.. code-block:: php
getRewriteUri());
// Check if the request is cached
if ($cache->exists($key)) {
echo $cache->get($key);
return false;
}
return true;
}
}
Then add the instance to the application:
.. code-block:: php
before(
new CacheMiddleware()
);
以下のミドルウェアイベントが利用可能です。
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
| Event Name | Triggered | Can stop operation? |
+=====================+============================================================================================================================+======================+
| before | Before executing the handler. It can be used to control the access to the application | Yes |
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
| after | Executed after the handler is executed. It can be used to prepare the response | No |
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
| finish | Executed after sending the response. It can be used to perform clean-up | No |
+---------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------+
ハンドラでコントローラの使用
-----------------------------
:code:`Mvc\Micro` を使用した中規模アプリケーションでは、コントローラーを使用する場合があると思います。
:doc:`Phalcon\\Mvc\\Micro\\Collection <../api/Phalcon_Mvc_Micro_Collection>` を使用することによって、コントローラーのグルーピングができます。
.. code-block:: php
setHandler(
new PostsController()
);
// Set a common prefix for all routes
$posts->setPrefix("/posts");
// Use the method 'index' in PostsController
$posts->get("/", "index");
// Use the method 'show' in PostsController
$posts->get("/show/{slug}", "show");
$app->mount($posts);
'PostsController'を以下の例のように記載します。
.. code-block:: php
setHandler("PostsController", true);
$posts->setHandler("Blog\Controllers\PostsController", true);
レスポンスのリターン
--------------------
ハンドラーは、:doc:`Phalcon\\Http\\Response ` を使用した生のレスポンスを返したり、または、ビューなどのインターフェイスコンポーネントを返したりすると思います。
ハンドラーによってレスポンスが返されるとき、アプリケーションによって自動的にそれが送信されます。
.. code-block:: php
get(
"/welcome/index",
function () {
$response = new Response();
$response->setStatusCode(401, "Unauthorized");
$response->setContent("Access is not authorized");
return $response;
}
);
ビューのレンダリング
--------------------
:doc:`Phalcon\\Mvc\\View\\Simple ` はビューをレンダリングするために使用します。
.. code-block:: php
setViewsDir("app/views/");
return $view;
};
// Return a rendered view
$app->get(
"/products/show",
function () use ($app) {
// Render app/views/products/show.phtml passing some variables
echo $app["view"]->render(
"products/show",
[
"id" => 100,
"name" => "Artichoke"
]
);
}
);
Please note that this code block uses :doc:`Phalcon\\Mvc\\View\\Simple <../api/Phalcon_Mvc_View_Simple>` which uses relative paths instead of controllers and actions.
If you would like to use :doc:`Phalcon\\Mvc\\View\\Simple <../api/Phalcon_Mvc_View_Simple>` instead, you will need to change the parameters of the :code:`render()` method:
.. code-block:: php
setViewsDir("app/views/");
return $view;
};
// Return a rendered view
$app->get(
"/products/show",
function () use ($app) {
// Render app/views/products/show.phtml passing some variables
echo $app["view"]->render(
"products",
"show",
[
"id" => 100,
"name" => "Artichoke"
]
);
}
);
Error Handling
--------------
A proper response can be generated if an exception is raised in a micro handler:
.. code-block:: php
get(
"/",
function () {
throw new \Exception("An error");
}
);
$app->error(
function ($exception) {
echo "An error has occurred";
}
);
If the handler returns "false" the exception is stopped.
関連ソース
---------------
* :doc:`Creating a Simple REST API ` is a tutorial that explains how to create a micro application to implement a RESTful web service.
* `Stickers Store `_ is a very simple micro-application making use of the micro-mvc approach [`Github `_].