Phalconのまったくの初心者が遭遇するPhalcon

# Phalcon初心者が経験するあれこれ

Phalconについて初心者がある程度のアプリを作るまで過程を共有します。
メインはPhalconなのでフロント側はあまり触れません。

## 作りたいもの
簡易なトピックに対するコメント返しするだけのもの

### **盛り込む機能**
1. トピック投稿
2. コメント投稿
3. トピック一覧

#### **使用するライブラリなど**
0. PHP ([Phalcon](http://www.phalconphp.com/ja/))

#### **クライアント：サーバー間通信**
0. JSONを利用する

今回はPhalconのvagrantを使います。
http://www.phalconphp.com/ja/download/vagrant

環境は以下のようなものです。
* * *
**Box 2**

* Ubuntu 12.04 (Precise Pangolin) x86
* Apache 2.2
* Phalcon 1.2.5
* PHP 5.4.23
* MySQL 5.5

* MySQL ユーザー： root 　パスワード： pass
* ドキュメントルート: /var/www

```bash:vagrantをインストールしましょう
vagrant init phalconbox https://s3-eu-west-1.amazonaws.com/phalcon/phalcon125-apache2-php54-mysql55.box
vagrant up
```
***

## 画面構成
0. ホーム
1. トピック投稿
2. トピック投稿確認
3. トピック投稿完了
4. ...etc

## URL設計のURL
まずはURLを決めていきましょう。
0. ホーム (/)  index のページを見るようにデフォルト設定にしましょう
1. トピックス投稿 (topics/post)
2. トピック削除(topics/delete)
3. トピック編集(topics/edit)
4. .... etc

## モデル
0. ユーザー
1. トピック
2. コメント
3. ...etc

## 機能および表示物の仕様
0. ホーム画面には最新のトピック20件が表示されている
1. ホーム画面にはトピックについたコメント最新10件が表示されている
2. ...etc

## Phalcon Vagrant (Box2)の構造
さて、では早速作っていきましょう。

```bash:/var/wwwの配下は
cd /var/www
ls
index.html  info.php  invo  website
```
という構成になっていると思います。

* [invo](http://docs.phalconphp.com/en/latest/reference/tutorial-invo.html) (Phalconのチュートリアル)
* website (Phalconのホームページのソース)

という2つのサンプルアプリケーションが同梱されています。
開発する上で参考になるアプリケーションです。

作成するにあたってひな形を作成してくれる[デベロッパーツール](http://phalconphp.com/ja/download/tools)が便利です

```bash:composerが入っていない場合
curl -s http://getcomposer.org/installer | php
```
```json:composer.jsonの編集
{
    "require": {
        "phalcon/devtools": "dev-master"
    }
}
```
```bash:composerインストール
php composer.phar install
```
```bash:シンボリックリンクを作成しておく
ln -s インストールしたdevツール/phalcon.php /usr/bin/phalcon-dev-tool
chmod ugo+x /usr/bin/phalcon-dev-tool
```

**vagrant環境をaptitude updateしてupgradeしたとき等の注意点**
apache用とCLIでphp.iniを読み込む場所が変わっていた。

```shell-session:php.iniの場所を調べる
php -i | head
phpinfo()
PHP Version => 5.4.35-1+deb.sury.org~precise+1

System => Linux precise32 3.2.0-23-generic-pae #36-Ubuntu SMP Tue Apr 10 22:19:09 UTC 2012 i686
Build Date => Nov 19 2014 19:28:25
Server API => Command Line Interface
Virtual Directory Support => disabled
Configuration File (php.ini) Path => /etc/php5/cli
Loaded Configuration File => /etc/php5/cli/php.ini
Scan this dir for additional .ini files => /etc/php5/cli/conf.d
```

```shell-session:extensionの追加
extenson=phalcon.so
```
を追加してあげよう。


```shell-session:ここまでやって以下が出てきたら成功
phalcon

Phalcon DevTools (1.2.5)

Available commands:
  commands (alias of: list, enumerate)
  controller (alias of: create-controller)
  model (alias of: create-model)
  all-models (alias of: create-all-models)
  project (alias of: create-project)
  scaffold
  migration
  webtools
```

## Phalconの構造

> **Phalconは自由度が高く、特にフォルダ構造などには規約はありません**
[Phalconに触れながらMVCプロジェクトの構成と構造を理解しよう - Think IT](http://thinkit.co.jp/story/2014/08/08/5169)

index.php での読み込み順序・設定順序でサーバーアプリケーションの準備が整えばあとはそれに従って自由に組めるということ。
型にはまらないフレームワークですね。のっけからアプリケーション構造を設計できてないうちに組むと崩壊しそうな印象です。

 
では先ほどインストールしたPhalconのDevelopper Toolを使いひな形を展開しましょう。


```shell-session:プロジェクトを作成する
cd /var/www/
phalcon create-project idocom

Phalcon DevTools (1.2.5)

                                                         
  Success: Controller "index" was successfully created.  
                                                         
                                                       
  Success: Project 'idocom' was successfully created. 
````

```shell-session:作ったプロジェクトをtreeコマンドで見てみる
cd idocom
tree
.
|-- app
|   |-- cache
|   |-- config
|   |   |-- config.php
|   |   |-- loader.php
|   |   `-- services.php
|   |-- controllers
|   |   |-- ControllerBase.php
|   |   `-- IndexController.php
|   |-- models
|   `-- views
|       |-- index
|       |   `-- index.volt
|       |-- index.volt
|       `-- layouts
|-- index.html
`-- public
    |-- css
    |-- files
    |-- img
    |-- index.php
    |-- js
    `-- temp
```
**すでにpublic/index.php配下がドキュメントディレクトリになるようになっています。**

※今回は webtoolについては触れません。飛ばしてください。

```shell-session:ちなみにwebtoolsを有効にすると

phalcon webtools enable
tree
.
|-- app
|   |-- cache
|   |-- config
|   |   |-- config.php
|   |   |-- loader.php
|   |   `-- services.php
|   |-- controllers
|   |   |-- ControllerBase.php
|   |   `-- IndexController.php
|   |-- models
|   `-- views
|       |-- index
|       |   `-- index.volt
|       |-- index.volt
|       `-- layouts
|-- index.html
`-- public
    |-- css
    |   |-- bootstrap
    |   |   |-- bootstrap.min.css
    |   |   |-- bootstrap-responsive.min.css
    |   |   `-- index.html
    |   `-- codemirror
    |       |-- codemirror.css
    |       |-- codephalcon.css
    |       `-- index.html
    |-- files
    |-- img
    |   `-- bootstrap
    |       |-- glyphicons-halflings.png
    |       `-- index.html
    |-- index.php
    |-- js
    |   |-- bootstrap
    |   |   |-- bootstrap.min.js
    |   |   `-- index.html
    |   |-- codemirror
    |   |   |-- index.html
    |   |   |-- lib
    |   |   |   |-- codemirror.js
    |   |   |   |-- codephalcon.js
    |   |   |   `-- index.html
    |   |   `-- mode
    |   |       |-- clike
    |   |       |   |-- clike.js
    |   |       |   `-- index.html
    |   |       |-- css
    |   |       |   |-- css.js
    |   |       |   `-- index.html
    |   |       |-- index.html
    |   |       |-- php
    |   |       |   |-- index.html
    |   |       |   `-- php.js
    |   |       `-- xml
    |   |           |-- index.html
    |   |           `-- xml.js
    |   `-- jquery
    |       |-- index.html
    |       `-- jquery.min.js
    |-- temp
    |-- webtools.config.php
    `-- webtools.php
```

http://xxx.xxx.xxx.xxx/idocom/webtools.php にアクセスするとWebToolの画面が出てきます。
※今回は webtoolについては触れません。飛ばしてください。


それでは試しにControllerを追加してみましょう。
app/controllers/ の中に
Controller名は キャメルケース & ControllerのSuffix付きで追加します。

```php:PhpinfomationController.php

<?php
class PhpinfomationController extends ControllerBase
{
    public function indexAction()
    {
        phpinfo();
    }
}

```

app/chache ディレクトリが書き込み権限がないとうまく表示されないと思います。

```shell-session:キャッシュディレクトリを書き込み権限を与える
chmod -R 777 app/cache/
```

http://IPアドレス/idocom/phpinfomation
でphpinfo()の結果が出たら成功。

コントローラーの作成についてはコマンドを使っても作成できます。
まだコントローラーを作りこんでいないときは便利そうですね。

```shell-session:Testsモデルを作成する
phalcon controller tests


今度はデーターベースとつないでみましょう。
まずは設定ファイルを確認してつなげられるようにします。

```php:app/config/config.php
<?php

return new \Phalcon\Config(array(
    'database' => array(
        'adapter'     => 'Mysql',
        'host'        => 'localhost',
        'username'    => 'root',
        'password'    => 'pass',
        'dbname'      => 'idcom',
    ),
    'application' => array(
        'controllersDir' => __DIR__ . '/../../app/controllers/',
        'modelsDir'      => __DIR__ . '/../../app/models/',
        'viewsDir'       => __DIR__ . '/../../app/views/',
        'pluginsDir'     => __DIR__ . '/../../app/plugins/',
        'libraryDir'     => __DIR__ . '/../../app/library/',
        'cacheDir'       => __DIR__ . '/../../app/cache/',
        'baseUri'        => '/idocom/',
    )
));

```

簡単にtests というtableを作成します。
カラムは1個です。
test_id

```php:app/model/Tests.php
<?php

class Tests extends \Phalcon\Mvc\Model
{
    /**
     *
     * @var integer
     */
    public $test_id;

    /**
     * Independent Column Mapping.
     */
    public function columnMap()
    {
        return array(
            'test_id' => 'test_id'
        );
    }
}
```

```php:app/controller/DatabasetestController.php
<?php

class DatabasetestController extends ControllerBase
{

    public function indexAction()
    {
        $tests = Tests::find();
        foreach($tests as $test){
            echo $test->test_id, PHP_EOL;
        }
    }
}
```

http://IPアドレス/idocom/databasetest で挿入したidが出てきたら成功です。


モデルの作成についてはコマンドを使っても作成できます。
Databaseが既にあって、まだModelを作りこんでいないときは便利そうですね。

```shell-session:Testsモデルを作成する
phalcon model tests
```

##テンプレートエンジンvoltを触ってみましょう。

```shell-session:app/views/
|-- body.volt
|-- footer.volt
|-- header.volt
|-- index
|   `-- index.volt
|-- index.volt
`-- layouts
```

```php:header.volt
{# header.volt #}
<!DOCTYPE html>
<html>
        <head>
                <meta content="utf-8" />
                <title>IdoCom</title>
        <!-- Latest compiled and minified CSS -->
                {{ stylesheet_link("css/bootstrap.min.css") }}
                <!-- Optional theme -->
                {{ stylesheet_link("css/bootstrap-theme.min.css") }}
    </head>
```

```php:body.volt
<body>
{{ content() }}

<!-- Latest compiled and minified JavaScript -->
{{ javascript_include("js/bootstrap.min.js") }}
{{ javascript_include("js/jquery-2.1.1.min.js") }}
{{ javascript_include("js/angular.min.js") }}
</body>

```

```php:footer.volt 
</html>
```


```php:index.volt
<?= $this->partial("header") ?>
<?= $this->partial("body") ?>
<?= $this->partial("footer") ?> 
```

###Phalcon のviewを触ってみてわかったこと
* partial() は呼びたいところに作成したテンプレートを呼べる
* stylesheet_linkやjavascript_includeで意味づけを行ってファイルをURLを作成することができる

便利だ。

[Volt: Template Engine](http://docs.phalconphp.com/en/latest/reference/volt.html)
※partialはFunctionsの所を参照


##Phalconを初回に触って悩んだこと

0. モデルってどう繋がるん？（テストテーブルにつながったときにだいたいわかった）
1. ルーターってどこに設置したらええん？
2. ライブラリーを自動でロードさせるにはどうするん？

1.は解決済みなので2.から。


###ルーターの設置

```php:app/config/router.php
<?php

// Create the router
$router = new \Phalcon\Mvc\Router();

$router->add(
    "/api/get/thread_list_home",
            array(
            "controller" => "api",
            "action"     => "thread_list_read_home"
                    )
                );
$router->add(
    "/api/get/thread_list",
                array(
                "controller" => "api",
                "action"     => "thread_list_read"
                  )
                );
/** 省略 **/

$router->handle();

```

的な感じに書いて

```php:app/config/services.php
/**
 * add routing capabilities
 */
  $di->set('router', function(){
      require __DIR__ . '/../../app/config/router.php';
      return $router;
  });
```

で繋げます。
これでルーティングが有効になります。

[ルーティング](http://docs.phalconphp.com/ja/latest/reference/routing.html)


###ライブラリーを自動でロード

```shell-session:libraryの置き場所を作る
mkdir app/library
```

ライブラリの置き場所などは

```php:app/config/config.php   
<?php

return new \Phalcon\Config(array(
    'database' => array(
        'adapter'     => 'Mysql',
        'host'        => 'localhost',
        'username'    => 'root',
        'password'    => 'pass',
        'dbname'      => 'idocom',
    ),
    'application' => array(
        'controllersDir' => __DIR__ . '/../../app/controllers/',
        'modelsDir'      => __DIR__ . '/../../app/models/',
        'viewsDir'       => __DIR__ . '/../../app/views/',
        'pluginsDir'     => __DIR__ . '/../../app/plugins/',
        'libraryDir'     => __DIR__ . '/../../app/library/',
        'cacheDir'       => __DIR__ . '/../../app/cache/',
        'baseUri'        => '/idocom/',
    )
));

```

をご確認ください。


```php:app/config/loader.php_ライブラリーを自動で読み込めるようにする
<?php

$loader = new \Phalcon\Loader();

/**
 * We're a registering a set of directories taken from the configuration file
 */
$loader->registerDirs(
    array(
        $config->application->controllersDir,
        $config->application->modelsDir,
        $config->application->libraryDir
    )
)->register();
```

$config->application->libraryDir

を追加すると ライブラリーが読み込まれるようになります。

##捕まったエラーたち
* **Extends statement must be placed at the first line in the template**

これは{% extends "xxxx.volt" %} を置いた前に volt等phpのコメント以外の文字列が挿入されているとエラーと警告されます。

* **Child templates only may contain blocks**

{* extends "xxxx.volt" *} 同じテンプレート内で二回呼ぶとエラーになります

* **画面がわからないけど真っ白になる**

エラーログを見ましょう。
原因はだいたい設定周辺のエラーです。

##感想
**ここまでありがとうございました！**
拙筆もうしわけねぇもうしわけねぇヽ('ω')ﾉ三ヽ('ω')ﾉ

ざっと想定した設定で何か成果物を出すまでにいろいろ試しながらあったっていくというPhalconって修行みたいなフレームワークかな？と一瞬、困惑しちゃいます。
これもドキュメントがPhalconの性能やフレームワークの機能の使い方にフォーカスしていて、全体の大まかな流れが不明になって「わからない」を産みそうです、ベストとまでも行かなくても基礎部分の繋ぐところをババッとドキュメントに書いてほしいですね。
「こーやっていけば」ミニマムのプロダクト作れるからみたいな。
あるにはあるんですが、それだけ？もっと知りたいけど続きないの？惜しいですｗ
開発者を置いていくぐらい速いフレームワークです。

これも、「**Phalconは自由度が高く、特にフォルダ構造などには規約はありません**」＜これがあるので十人十色のプロジェクトができる感じですかね。

Phalconは自由度があって尚且つ途轍もなく速く動くフレームワークなら、Phalconの機能を余すところなく使ってユーザーに対しての速度面でのリターンを押していきたいですね。

ある程度試してみましたが、構造が見えてきました。
とてもシンプルな構造なので開発面やコードの運用面にも気を配って書けば面白そうです。

ほんとはもっと書きたかったんですが、時間切れ！

Let's Try Phalcon!!