チュートリアル - 基本

この最初のチュートリアルでは、簡単な登録フォームのアプリケーションの作成を、基礎から一歩ずつ進めます。 次のガイドでは、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
{
    /**
     * Show form to register a new user
     */
    public function indexAction()
    {
    }

    /**
     * Register new user and show message
     */
    public function registerAction()
    {
        $user = new Users();

        // Store and check for errors
        $success = $user->save(
            $this->request->getPost(),
            ['name', 'email']
        );

        // passing the result to the view
        $this->view->success = $success;

        if ($success) {
            $message = "Thanks for registering!";
        } else {
            $message = "Sorry, the following problems were generated:<br>" . implode('<br>', $user->getMessages());
        }

        // passing a message to the view
        $this->view->message = $message;
    }
}

At the beginning of the registerAction we create an empty user object from the Users class, which manages a User's record. クラスのパブリックプロパティは、データベースのusersテーブルのフィールドにマッピングされます。 新しいレコードに関連する値を設定しsave()を呼び出すと、そのレコードのデータがデータベースに保存されます。 save()メソッドは、データの格納が成功したかどうかを示すブール値を返します。

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

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

List of users

Now let's see how to obtain and see the users that we have registered in the database.

The first thing that we are going to do in our indexAction of theIndexController is to show the result of the search of all the users, which is done simply in the following way Users::find(). Let's see how our indexAction would look

app/controllers/IndexController.php

<?php

use Phalcon\Mvc\Controller;

class IndexController extends Controller
{
    /**
     * Welcome and user list
     */
    public function indexAction()
    {
        $this->view->users = Users::find();
    }
}

Now, in our view file views/index/index.phtml we will have access to the users found in the database. These will be available in the variable $users. This variable has the same name as the one we use in $this->view->users.

The view will look like this:

views/index/index.phtml

<?php

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

echo $this->tag->linkTo(["signup", "Sign Up Here!", 'class' => 'btn btn-primary']);

if ($users->count() > 0) {
    ?>
    <table class="table table-bordered table-hover">
        <thead class="thead-light">
        <tr>
            <th>#</th>
            <th>Name</th>
            <th>Email</th>
        </tr>
        </thead>
        <tfoot>
        <tr>
            <td colspan="3">Users quantity: <?php echo $users->count(); ?></td>
        </tr>
        </tfoot>
        <tbody>
        <?php foreach ($users as $user) { ?>
            <tr>
                <td><?php echo $user->id; ?></td>
                <td><?php echo $user->name; ?></td>
                <td><?php echo $user->email; ?></td>
            </tr>
        <?php } ?>
        </tbody>
    </table>
    <?php
}

As you can see our variables $users can be iterated and counted, this we will see in depth later on when viewing the models.

Adding Style

To give a design touch to our first application we will add bootstrap and a small template that will be used in all views.

We will add an index.phtml file in theviews folder, with the following content:

app/views/index.phtml

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Phalcon Tutorial</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <?php echo $this->getContent(); ?>
</div>
</body>
</html>

The most important thing to highlight in our template is the function getContent() which will give us the content generated by the view. Now, our application will be something like this:

まとめ

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

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