チュートリアル - 基本

この最初のチュートリアルでは、簡単な登録フォームのアプリケーションの作成を、基礎から一歩ずつ進めます。 次のガイドでは、Phalconフレームワークの設計面をご紹介します。

このチュートリアルでは、単純なMVCアプリケーションの実装について説明し、Phalconを使用してどのように迅速かつ簡単に実行できるかを示します。 このチュートリアルでは、多くのニーズに対応できるように、拡張可能なアプリケーションを作成するのに役立ちます。 このチュートリアルのコードは、他のPhalcon固有の概念やアイデアを学ぶための遊び場としても使用できます。

とにかく始めたいのであれば、このガイドをスキップして、developer tools を使ってPhalconプロジェクトを自動的に作成することができます。 (あなたが立ち往生した場合、ここに戻って来ると良いでしょう)

このガイドを使用する最善の方法は、一緒に楽しく進めることです。 完全なコードはここで取得できます。 どうすることもできない場合は、DiscordまたはForumにアクセスしてください。

ファイル構成

Phalcon の主な特徴である 疎結合 により、開発したいアプリケーションに応じて最適なディレクトリ構成を持つ Phalcon プロジェクトを構築することができます。 他の人と共同作業するときに、ある種の統一性が役立ちます。このチュートリアルでは、過去に他のMVCを使っていた場合に親近感を覚えるはずの "Standard" な構造を使用します。

.
└── tutorial
    ├── app
    │   ├── controllers
    │   │   ├── IndexController.php
    │   │   └── SignupController.php
    │   ├── models
    │   │   └── Users.php
    │   └── views
    └── public
        ├── css
        ├── img
        ├── index.php
        └── js

全く初めて作る場合いは、Phalcon Devtoolsをインストールすることをお勧めします。.htrouterをプロジェクトのルートに追加してPHPのビルトインサーバーを利用すれば、Webサーバーの設定をしなくてもアプリケーションを稼働させることができます。

それ以外に、Nginxを使用したい場合は、ここにいくつかの追加設定があります。

もしApacheを使いたい場合は、こちらで追加設定をしてください。

最後に、もしCherokeeがお好みの場合はここで設定してください。

Bootstrap

はじめに作成する必要があるファイルは bootstrap ファイルです。 このファイルは、アプリケーションのエントリポイント、そして設定ファイルとして機能します。 このファイルでは、アプリケーションの動作と同様に、コンポーネントの初期化を実装できます。

このファイルは3つのことを処理します:

  • オートローダーコンポーネントの登録
  • サービスの設定とDependency Injectionへの登録
  • アプリケーションのHTTPリクエストの処理

オートローダー

オートローダーはPhalconの実行中にPSR-4準拠のファイルローダーを提供します。 通常、オートローダーに追加する必要があるのはControllerとModelです。 アプリケーションの名前空間内で、ファイルを検索するディレクトリを登録できます。 他の方法でオートローダーを使いたい場合、こちらをご覧ください。

まず、アプリケーションのcontrollersmodelsディレクトリを登録します。 Phalcon\Loaderのローダーを含めることを忘れないでください。

public/index.php

<?php

use Phalcon\Loader;

// リソースの特定に役立つ絶対パス定数を定義する
define('BASE_PATH', dirname(__DIR__));
define('APP_PATH', BASE_PATH . '/app');
// ...

$loader = new Loader();

$loader->registerDirs(
    [
        APP_PATH . '/controllers/',
        APP_PATH . '/models/',
    ]
);

$loader->register();

依存関係の管理

Phalconは疎結合で実装されており、サービスはDependency Managerに登録されているため、IoCコンテナにラップされたコンポーネントやサービスに自動的に挿入できます。 Dependency Injectionの略語であるDIが出てくることがよくあります。 Dependency InjectionとInversion of Control(IoC) は複雑な機能のような聞こえるかもしれませんが、ファルコンでの使用は非常にシンプルで実用的です。 PhalconのIoCコンテナは、以下の概念で構成されています。

  • サービスコンテナ: アプリケーションから使用する関数を実装したサービスをグローバルに格納するための大きなバッグ。
  • サービスまたはコンポーネント: コンポーネントに注入されるデータ処理オブジェクト

フレームワークがコンポーネントやサービスを必要とするたびに、サービスに紐づけられた名前を使用してコンテナに問い合わせます。 Phalcon\Diをサービスコンテナの設定に含めることを忘れないでください。

Factory Default

Phalcon\Di\FactoryDefaultPhalcon\Di の一種です。 実装を簡単にするために、Phalconに付属するほとんどのコンポーネントは自動的に登録されます。 Dependency Managementに慣れやすくする為にも、サービスを手動で登録することをお勧めします。 後で、このコンセプトに慣れたらいつでも指定できます。

サービスはいくつかの方法で登録することができますが、このチュートリアルでは無名関数を使用します。

public/index.php

<?php

use Phalcon\Di\FactoryDefault;

// ...

// DIの生成
$di = new FactoryDefault();

次のパートでは、フレームワークがビューファイルを見つけるディレクトリを指し示した "view" サービスを登録します。 ビューはクラスに対応していないため、オートローダを利用することができません。

public/index.php

<?php

use Phalcon\Mvc\View;

// ...

// viewコンポーネントを設定します
$di->set(
    'view',
    function () {
        $view = new View();
        $view->setViewsDir(APP_PATH . '/views/');
        return $view;
    }
);

次に、Phalconによって生成されたすべてのURIがアプリケーションのベースパス "/"と一致するようにベースURIを登録します。 Phalcon\Tag クラスを使用してハイパーリンクを生成する場合、この設定はチュートリアルの後半で重要になります。

public/index.php

<?php

use Phalcon\Mvc\Url as UrlProvider;

// ...

// ベースURIの設定
$di->set(
    'url',
    function () {
        $url = new UrlProvider();
        $url->setBaseUri('/');
        return $url;
    }
);

アプリケーションのリクエストを処理する

このファイルの最後の部分には、Phalcon\Mvc\Application があります。 その目的は、リクエスト環境変数を初期化し、受け取ったリクエストをルーティング、検出されたアクションにディスパッチすることです。レスポンスを集約し、処理が完了したときにそれを返却します。

public/index.php

<?php

use Phalcon\Mvc\Application;

// ...

$application = new Application($di);
$response = $application->handle();
$response->send();

全てを配置

tutorial/public/index.php ファイルは、次のようになります。

public/index.php

<?php

use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Application;
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Url as UrlProvider;

// リソースの特定に役立つ絶対パス定数を定義する
define('BASE_PATH', dirname(__DIR__));
define('APP_PATH', BASE_PATH . '/app');

// オートローダーの登録
$loader = new Loader();

$loader->registerDirs(
    [
        APP_PATH . '/controllers/',
        APP_PATH . '/models/',
    ]
);

$loader->register();

// DIの生成
$di = new FactoryDefault();

// ビューコンポーネントの設定
$di->set(
    'view',
    function () {
        $view = new View();
        $view->setViewsDir(APP_PATH . '/views/');
        return $view;
    }
);

// ベースURIの設定
$di->set(
    'url',
    function () {
        $url = new UrlProvider();
        $url->setBaseUri('/');
        return $url;
    }
);

$application = new Application($di);

try {
    // リクエストのハンドリング
    $response = $application->handle();

    $response->send();
} catch (\Exception $e) {
    echo 'Exception: ', $e->getMessage();
}

ご覧のように、ブートストラップファイルは非常に短く、追加のファイルを含める必要はありません。 おめでとうございます、30行以下のコードで柔軟なMVCアプリケーションを作成できました。

Controllerの作成

デフォルトでは、PhalconはIndexControllerという名前のコントローラを探します。 これは、リクエストでコントローラまたはアクションが渡されていないときの開始点です。 (例えば http://localhost:8000/). IndexControllerIndexActionは、次の例のようになります:

app/controllers/IndexController.php

<?php

use Phalcon\Mvc\Controller;

class IndexController extends Controller
{
    public function indexAction()
    {
        echo '<h1>Hello!</h1>';
    }
}

コントローラクラスには後ろにControllerが必要であり、コントローラのアクションには後ろにActionをつける必要があります。 ブラウザからアプリケーションにアクセスすると、次のように表示されます。

おめでとう、あなたはPhalconで飛び立つことができました!

View に出力を送る

コントローラーから画面に出力を送信することは時に必要ですが、MVCコミュニティの多くの純粋主義者が証明する様に、望ましくはありません。 すべてを画面上の出力データとしてビューに渡す必要があります。 Phalconは、最後に実行されたコントローラーと同じ名前のディレクトリー配下にある、最後に実行されたアクションと同じ名前のビューを探します。 今回の場合は (app/views/index/index.phtml) です。

app/views/index/index.phtml

<?php echo "<h1>Hello!</h1>";

私たちのコントローラー (app/controllers/IndexController.php) は空のアクションが定義されています:

app/controllers/IndexController.php

<?php

use Phalcon\Mvc\Controller;

class IndexController extends Controller
{
    public function indexAction()
    {

    }
}

ブラウザの出力は変わらないはずです。 静的コンポーネントの Phalcon\Mvc\View は、アクションの実行が終了すると自動的に作成されます。 ビューの詳しい使い方はこちら

サインアップフォームのデザイン

今度はindex.phtmlビューファイルを変更して、 "signup"という名前の新しいコントローラへのリンクを追加します。 目標は、ユーザーがアプリケーション内でサインアップできるようにすることです。

app/views/index/index.phtml

<?php

echo "<h1>Hello!</h1>";

echo PHP_EOL;

echo PHP_EOL;

echo $this->tag->linkTo(
    'signup',
    'Sign Up Here!'
);

生成されたHTMLコードでは、新しいコントローラにリンクするアンカータグ (<a>) を表示します:

app/views/index/index.phtml (レンダリング後)

<h1>Hello!</h1>

<a href="/signup">Sign Up Here!</a>

タグを生成するにはPhalcon\Tagクラスを使用します。 これは、フレームワークの規約に従ったHTMLタグを生成することを可能にするユーティリティクラスです。 このクラスはDIに登録されたサービスでもあるため、$this->tagを使用してアクセスします。

HTML生成に関するより詳細な記事はここにあります

Signupコントローラは次のとおりです (app/controllers/SignupController.php):

app/controllers/SignupController.php

<?php

use Phalcon\Mvc\Controller;

class SignupController extends Controller
{
    public function indexAction()
    {

    }
}

空のindexアクションは、フォーム定義を持つビューに対して何も渡しません (app/views/signup/index.phtml):

app/views/signup/index.phtml

<h2>Sign up using this form</h2>

<?php echo $this->tag->form("signup/register"); ?>

    <p>
        <label for="name">Name</label>
        <?php echo $this->tag->textField("name"); ?>
    </p>

    <p>
        <label for="email">E-Mail</label>
        <?php echo $this->tag->textField("email"); ?>
    </p>

    <p>
        <?php echo $this->tag->submitButton("Register"); ?>
    </p>

</form>

ブラウザでフォームを確認すると、次のように表示されます:

Phalcon\Tagは、フォーム要素を構築するための便利なメソッドも提供します。

Phalcon\Tag::form()メソッドは、例えばアプリケーション内の controller/action に対する相対URIを唯一のパラメータとして受け取ります。

「送信」ボタンをクリックすると、フレームワークから例外がスローされ、signupコントローラーのregisterアクションが無いことがわかります。 public/index.phpファイルは以下の例外を投げます:

Exception: Action "register" was not found on handler "signup"

このメソッドを実装すると、例外が無くなります:

app/controllers/SignupController.php

<?php

use Phalcon\Mvc\Controller;

class SignupController extends Controller
{
    public function indexAction()
    {

    }

    public function registerAction()
    {

    }
}

もう一度 "Send" ボタンをクリックすると、空白のページが表示されます。 ユーザーが入力したnameとemailはデータベースに保存する必要があります。 MVCのガイドラインによれば、オブジェクト指向のきれいなコードを確保するために、データベースのやりとりをモデルを通じて行う必要があります。

Modelの作成

Phalconは、C言語で書かれた初めてのPHP用ORMを提供します。 これは、開発の複雑さを増やすのではなく単純化します。

最初のモデルを作成する前に、Phalconがマッピングできる様にデータベースのテーブルを作成する必要があります。 登録ユーザーを格納するためのシンプルなテーブルは、次のように作成できます:

create_users_table.sql

CREATE TABLE `users` (
    `id`    int(10)     unsigned NOT NULL AUTO_INCREMENT,
    `name`  varchar(70)          NOT NULL,
    `email` varchar(70)          NOT NULL,

    PRIMARY KEY (`id`)
);

モデルは、app/modelsディレクトリに配置する必要があります (app/models/Users.php)。 このモデルは "users" テーブルにマッピングされます:

app/models/Users.php

<?php

use Phalcon\Mvc\Model;

class Users extends Model
{
    public $id;
    public $name;
    public $email;
}

データベース接続の設定

モデルからデータベース接続を使用してデータにアクセスできるようにするには、ブートストラップの処理中にデータベースの接続を設定する必要があります。 データベース接続は、アプリケーションの他のコンポーネントから利用できるサービスです:

public/index.php

<?php

use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;

// データベースの設定
$di->set(
    'db',
    function () {
        return new DbAdapter(
            [
                'host'     => '127.0.0.1',
                'username' => 'root',
                'password' => 'secret',
                'dbname'   => 'tutorial1',
            ]
        );
    }
);

適切なデータベースのパラメータを設定することでモデルは利用可能になり、アプリケーションの他の部分とやりとりできるようになります。

モデルを使ったデータの保存

app/controllers/SignupController.php

<?php

use Phalcon\Mvc\Controller;

class SignupController extends Controller
{
    public function indexAction()
    {

    }

    public function registerAction()
    {
        $user = new Users();

        // 保存とエラーのチェック
        $success = $user->save(
            $this->request->getPost(),
            [
                "name",
                "email",
            ]
        );

        if ($success) {
            echo "Thanks for registering!";
        } else {
            echo "Sorry, the following problems were generated: ";

            $messages = $user->getMessages();

            foreach ($messages as $message) {
                echo $message->getMessage(), "<br/>";
            }
        }

        $this->view->disable();
    }
}

registerActionの最初にユーザーのレコードを管理するUsersクラスから空のユーザーオブジェクトを作成しています。 クラスのパブリックプロパティは、データベースのusersテーブルのフィールドにマッピングされます。 新しいレコードに関連する値を設定しsave()を呼び出すと、そのレコードのデータがデータベースに保存されます。 save()メソッドは、データの格納が成功したかどうかを示すブール値を返します。

ORMは自動的に入力をエスケープしてSQLインジェクションを防ぐので、私たちはリクエストをsave()メソッドに渡すだけ良いです。

not null (required) として定義されているフィールドでは、追加のバリデーションが自動的に実行されます。 サインアップフォームに必要なフィールドを入力しないと、画面は次のようになります。

まとめ

ご覧のとおり、Phalconを使用してアプリケーションを構築するのは簡単です。 Phalconがextensionから実行されているという事実は、プロジェクトのフットプリントを大幅に減らし、パフォーマンスを大幅に向上させます。

あなたがもっと学ぶ準備ができているなら、次にRestチュートリアルをチェックしてください。