phalconのチュートリアル学習記録 -Basic編-

phalconのチュートリアルを学習してみます。

こちらを元に勉強しました。
[phalconチュートリアル-Basic編-](https://docs.phalconphp.com/en/3.2/tutorial-base)

macでxamppの上に置いてやっています

#ファイル構造

xamppと一緒に使いたいので、htdocsの中にファイルを置いています。

```
┗ tutorial
   ┣ app
   ┇ ┣ controllers
   ┇ ┇ ┣ IndexController.php
   ┇ ┇ ┗ SignupController.php
   ┇ ┣ models
   ┇ ┇ ┗ Users.php
   ┇ ┗ views
   ┗ public
      ┣ css
      ┣ img
      ┣ js
      ┗ index.php
```
#チュートリアルのコードの意味を徹底解明！ ~「Hello」を出力するまで~

##まずはindex.php

一度全体を見せたあと少しずつ解剖していきます。

```public/index.php

<?php

use Phalcon\Loader; //①オートローダー使うよ！って宣言
use Phalcon\Mvc\View;　 //ビューを使用するために必要な宣言
use Phalcon\Mvc\Application;　 //MVCの煩雑な処理はこれが行なっているらしい
use Phalcon\Di\FactoryDefault; //Phalconに付属しているコンポーネントのほとんどを登録するための宣言
use Phalcon\Mvc\Url as UrlProvider; //URLを作成するために必要な宣言

// Define some absolute path constants to aid in locating resources
define('BASE_PATH', dirname(__DIR__));　//
define('APP_PATH', BASE_PATH . '/app');

// Register an autoloader
$loader = new Loader();

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

$loader->register();

// Create a DI
$di = new FactoryDefault();

// Setup the view component
$di->set(
    'view',
    function () {
        $view = new View();
        $view->setViewsDir(APP_PATH . '/views/');
        return $view;
    }
);

// Setup a base URI
$di->set(
    'url',
    function () {
        $url = new UrlProvider();
        $url->setBaseUri('/');
        return $url;
    }
);

$application = new Application($di);

try {
    // Handle the request
    $response = $application->handle();

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

```

#解剖します

```public/index.php

<?php

use Phalcon\Loader; //オートローダー使うよ！って宣言
use Phalcon\Mvc\View;　 //ビューを使用するために必要な宣言
use Phalcon\Mvc\Application;　 //MVCの煩雑な処理はこれが行なっているらしい
use Phalcon\Di\FactoryDefault; //Phalconに付属しているコンポーネントのほとんどを登録するための宣言
use Phalcon\Mvc\Url as UrlProvider; //URLを作成するために必要な宣言

```

オートローダーってなんぞや？

>Phalcon\Loader とは、PSR-4 に準拠したオートロードの機能を提供するためのクラスです。
これを利用することによって、Phalcon は Composer に依存しないオートロードを実装することが出来ます。

だそうです。
このサイトが分かりやすい
[What about Phalcon\Loader](https://qiita.com/irihit/items/de9227ab6751c6e2f331)

あとは、宣言なので、ふーんっていう感じでいいのかな？

```index.php
// Define some absolute path constants to aid in locating resources
define('BASE_PATH', dirname(__DIR__));　//
define('APP_PATH', BASE_PATH . '/app');
```

define('A', 'B');　で、AをBと定義するという用法ですね。

dirname(\__DIR__)は、そのファイルが存在するディレクトリなので、
この場合は、<strong>BASE_PATH = そのファイルが存在するディレクトリ　</strong>と定義したということですね。
同様にAPP\_PATHもパスを定義しています。

参考：[自動的に定義される定数](http://php.net/manual/ja/language.constants.predefined.php)


```
// Register an autoloader
$loader = new Loader(); //オートローダーを作る

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

$loader->register(); //上で定義したオートローダーを登録
```

これは、オートローダーを作って、ディレクトリを登録しておきます。
ここでは、controllersとmodelsを登録します。


```
// Create a DI
$di = new FactoryDefault();
```

DIを作ります。
DIは、phlconの特徴の一つでもあるので、知っておきましょう！！
[猿でも分かる! Dependency Injection: 依存性の注入](https://qiita.com/hshimo/items/1136087e1c6e5c5b0d9f)

```
// Setup the view component
$di->set(
    'view',
    function () {
        $view = new View(); //新しいviewを作る
        $view->setViewsDir(APP_PATH . '/views/'); //パスを「/views/」に指定する
        return $view; //変数viewを返します
    }
);
```

Viewの部分を作っていきます。htmlとかがある場所ですね。
viewをセットして、第二引数の関数の中に実行したいことを記します。

```
// Setup a base URI
$di->set(
    'url',
    function () {
        $url = new UrlProvider();
        $url->setBaseUri('/');
        return $url;
    }
);
```

ベースとなるURIを作ります。
[URLとURIは何が違うの？ どちらが正しい呼び方？](https://webtan.impress.co.jp/e/2010/03/09/7539)

urlをセットして、第二引数に実行したいことを記します。
変数urlに、新しいUrlProviderを作って、パスは現在置で良いので、「/」としているのでしょう。
変数urlを返します。


```
$application = new Application($di);

try {
    // Handle the request
    $response = $application->handle(); 

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

applicationの存在意義がわからない・・・そこで調べてみると、このようなことが書かれていました。難しい。

>PhalconでのMVCの操作をオーケストレーションする背後にあるすべてのハードワークは、通常、Phalcon \ Mvc \ Applicationによって行われます。このコンポーネントは、必要なすべての複雑なオペレーションをバックグラウンドでカプセル化し、必要なすべてのコンポーネントをインスタンス化し、MVCパターンを必要に応じて動作させるためにプロジェクトと統合します。

applicationに一度放り込んで、複雑な処理をするということかな？

tryは例外処理を記述する場所です。
まずは、何か実行することを記します。

何かを行うときは、handleを使うそうで、この場合、responseを使いますよっていうことかな？
applicationを代入しているので、resoponseを返すということは、applicationを実行するっていうことかな。

例外が発生したら、エラーのメッセージを返すようになっていますね。


ちなみに
例外処理の記述はこう書くそうです

```
try {
    // 例外が発生する可能性のあるコード
} catch (Exception $e) {
    // 例外が発生した場合に行う処理
}
```


##次に、コントローラーを見ていきます。

```app/controllers/IndexController.php
<?php

use Phalcon\Mvc\Controller; //コントローラーを使うために必要なやつ

class IndexController extends Controller
{
    public function indexAction()
    {

    }
}
```

Controllerを継承して、IndexControllerというクラスを作ります。
indexActionは、「index」というのviewを参照するので、index.phtmlという名前にしておきます。
ちなみに、indexControllerは、indexフォルダを参照しますので、indexフォルダのindex.htmlを参照するということになります。

indexというフォルダの中に、index.phtmlを作りましょう。

##index/phtmlを作る

```app / views / index / index.phtml
<?php echo "<h1>Hello!</h1>";
```

コントローラーから、viewが参照されたので、helloを出力するプログラムを書きます。
そうすると、xamppでローカルホストに行くと、Hello!と表示されるでしょう。


#サインアップフォームの設計の部分
##index.phtmlを書き換える

サインアップフォームの場合は、Hello!の下にsign up here!という文字を作ってみましょう！

```app / views / index / index.phtml
<?php

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

echo PHP_EOL; //改行

echo PHP_EOL; //改行

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

tag->linkTO　でリンクを生成します。
signupに行くリンクを生成します(ブラウザには、「」Sign Up Here!)と表示される。

つまり、通常のhtmlなら、こんな感じになっているということです。

```
<h1>Hello!</h1>

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

##SignupControllerを作る

```app/controllers/SignupController.php
<?php

use Phalcon\Mvc\Controller;

class SignupController extends Controller
{
    public function indexAction()
    {

    }
}
```

SignupControllerは、signupフォルダを参照します。
Controllerを継承して、SignupControllerというクラスを作り、
indexActionでindex.phtmlを参照します。

##signup用のindex.phtmlを作る

```app/views/signup/index.phtml
<h2>Sign up using this form</h2>

<?php echo $this->tag->form("signup/register"); ?> //formタグを作って、signupコントローラーのregisterActionに飛ぶように設定

    <p>
        <label for="name">Name</label> //「Name」と表示されるラベルを作る
        <?php echo $this->tag->textField("name"); ?> //テキストを書くフィールドを作る
    </p>

    <p>
        <label for="email">E-Mail</label>　　//「E-Mail」と表示されるラベルを作る
        <?php echo $this->tag->textField("email"); ?> //テキストを書くフィールドを作る
    </p>

    <p>
        <?php echo $this->tag->submitButton("Register"); ?> //Registerボタンを作る
    </p>

</form>
```

#モデルを作る

##まずデータベースの設定から


ターミナルで以下のコマンドを打ちます。これで、ターミナルからxamppのphpmyadminに入れます。
この後パスワードを入力してください。
(ここは、チュートリアルにはありません。)

```
/Applications/XAMPP/xamppfiles/bin/mysql -u root -p
```


データベースを作ります。ここでは、phalcon_testという名前のデータベースを作ってみました。
ターミナルで下記のコマンドを打ってください。
(ここはチュートリアルにありません。)

```
create database phalcon_test;
```

このデータベースを使うことを宣言します。

```
use phalcon_test;
```


次にテーブルを作ります。
これはチュートリアルのやつですね。
ターミナルに打ち込みます。

```
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/Users.php
<?php

use Phalcon\Mvc\Model; //モデルを使います！という宣言

class Users extends Model　//Modelクラスを継承して、Usersというクラスを作成(Usersテーブルを参照という意味になります)
{
    public $id; 
    public $name;
    public $email;
}
```

モデルの働きを確認すると、、、

>モデルは、主に、対応するデータベーステーブルとの相互作用のルールを管理するために使用されます。

なるほど。
データベーステーブルの情報を書いていけばいいんですね。

ちなみに、publicを使うと、どこからでも読み取り・変更できるようになるらしい・・・。publicがいまいち分からんな。。。


##データベースとの接続
チュートリアルにもある以下のコードをindex.phpに追記します。

```public/index.php

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

// Setup the database service
$di->set(
    'db',　  //DIにdbをセット
    function () {
        return new DbAdapter(
            [
                'host'     => 'localhost', //xamppでやっているのでローカルホストを指定
                'username' => 'root', //phpmyadminにログインするときのユーザー名
                'password' => 'secret',　//phpmyadminにログインするときのパスワード
                'dbname'   => 'phalcon_test',  //他のデータベース名にした人は、そのデータベース名を指定
            ]
        );
    }
);
```

##モデルを使用したデータの保存

```app/controllers/SignupController.php
<?php

use Phalcon\Mvc\Controller; //コントローラを使います！

class SignupController extends Controller　//Controllerを継承して、　SignuoControllerクラスを作成(signupフォルダを参照するようになります)
{
    public function indexAction() //index.phtmlを実行
    {

    }

    public function registerAction() register //register.phtmlがあれば、それを実行するが、ないので、以下のコードを実行
    {
        $user = new Users();  //usersを作成

        // Store and check for errors
        $success = $user->save(   //saveはレコードの作成、更新ができる
            $this->request->getPost(),　  //requestを$_POST[$name]と$_POST[$email]で返す
            [
                "name",
                "email",
            ]
        );

        if ($success) {  //もし$successがあれば(さっきのがうまくいったら)
            echo "Thanks for registering!"; //Thanks for registering!と表示
        } else {  //もし$successがなければ(さっきのがうまくいかなかったら)
            echo "Sorry, the following problems were generated: ";　 //Sorry, the following problems were generated:と表示

            $messages = $user->getMessages(); //生成されたメッセージは、getMessages()メソッドで取得できる、それを$messagesに代入

            foreach ($messages as $message) {
                echo $message->getMessage(), "<br/>"; //データを表示
            }
        }

        $this->view->disable(); //register.phtmlがあれば、それを表示しちゃうので、viewの機能を遮断しました。
    }
}
```

中に全部書いてしまった笑
終わりです。