Aura.Cli_ProjectでCodeIgniter 3.0用のコマンドラインツールを作成した話①

Aura for PHP Advent Calendar 2015 の3日目、および、CodeIgniter Advent Calendar 2015 の13日目です。どちらもまだ、空きがありますので、興味のある方は気軽に参加してください。

みなさん、Aura for PHP 使ってますか?

Auraとは、高品質で、よくテストされ、セマンティックバージョンイングに従い、標準に準拠した、独立したライブラリパッケージを提供しているプロジェクトです。

たぶん、モダンなコードを書いているPHPユーザは何かしらAuraのライブラリを使っていることでしょう。

PHPのライブラリとしてはSymfonyコンポーネントが有名ですが、それ以外の有力な選択肢の一つとしてAuraがあります。キーワードはDecouplingです。

Auraは、コマンドラインから実行するスクリプトの作成を支援するライブラリやフレームワークも提供しています。

CLIプロジェクトの雛形としてAura.Cli_Projectがあります。

今日は、このAura.Cli_Projectを使い、CodeIgniterのコマンドラインツールを作成した話です。

Aura.Cli_Projectのインストール

Aura.Cli_ProjectはCLIプロジェクトの雛形です。

インストールしてみましょう。なお、PHP 5.4以上が必要です。

$ composer create-project aura/cli-project
Installing aura/cli-project (2.0.2)
  - Installing aura/cli-project (2.0.2)
    Downloading: 100%         

Created project in /home/kenji/tmp/cli-project
Loading composer repositories with package information
Installing dependencies (including require-dev)
  - Installing aura/dispatcher (2.0.3)
    Loading from cache

  - Installing aura/cli (2.1.1)
    Loading from cache

  - Installing psr/log (1.0.0)
    Loading from cache

  - Installing aura/di (2.2.3)
    Loading from cache

  - Installing aura/project-kernel (2.1.1)
    Loading from cache

  - Installing aura/cli-kernel (2.0.3)
    Loading from cache

  - Installing monolog/monolog (1.17.2)
    Loading from cache

monolog/monolog suggests installing graylog2/gelf-php (Allow sending log messages to a GrayLog2 server)
monolog/monolog suggests installing raven/raven (Allow sending log messages to a Sentry server)
monolog/monolog suggests installing doctrine/couchdb (Allow sending log messages to a CouchDB server)
monolog/monolog suggests installing ruflin/elastica (Allow sending log messages to an Elastic Search server)
monolog/monolog suggests installing videlalvaro/php-amqplib (Allow sending log messages to an AMQP server using php-amqplib)
monolog/monolog suggests installing ext-amqp (Allow sending log messages to an AMQP server (1.0+ required))
monolog/monolog suggests installing ext-mongo (Allow sending log messages to a MongoDB server)
monolog/monolog suggests installing aws/aws-sdk-php (Allow sending log messages to AWS services like DynamoDB)
monolog/monolog suggests installing rollbar/rollbar (Allow sending log messages to Rollbar)
monolog/monolog suggests installing php-console/php-console (Allow sending log messages to Google Chrome)
Writing lock file
Generating autoload files

フォルダ構成は以下のようになっています。

cli-project/
├── cli/
│   └── console.php ... コマンドファイル
├── config/          ... 設定を配置
│   ├── Common.php
│   ├── Dev.php
│   ├── Prod.php
│   ├── Test.php
│   └── _env.php
├── src/             ... ソースを配置
├── tests/           ... テストを配置
├── tmp/
│   ├── cache/
│   └── log/        ... ログファイル
└── vendor/

依存コンポーネントは以下です。

$ composer show -i
aura/cli            2.1.1  Provides the equivalent of request (Context) and response (Stdio) classes for a command line environm...
aura/cli-kernel     2.0.3  The kernel files for an Aura CLI project.
aura/di             2.2.3  Provides a dependency injection container system with native support for constructor- and setter-base...
aura/dispatcher     2.0.3  Creates objects from a factory and invokes methods using named parameters; also provides a trait for ...
aura/project-kernel 2.1.1  The shared kernel files for an Aura project.
monolog/monolog     1.17.2 Sends your logs to files, sockets, inboxes, databases and various web services
psr/log             1.0.0  Common interface for logging libraries

Auraのライブラリ以外には、monologに依存しているだけです。

aura/diはDIコンテナです。「PHP - auraで覚える Dependency Injection - Qiita」を参照してください。

コマンドの使い方

早速コマンドを実行してみましょう。

$ cd cli-project/
$ php cli/console.php
hello
    A demonstration 'hello world' command.
help
    Gets the available commands, or the help for one command.

php cli/console.phpと引数なしで実行すると、コマンドの一覧が表示されます。

helloコマンドとhelpコマンドがあることがわかります。

helloコマンドを実行してみましょう。

$ php cli/console.php hello
Hello World!

引数を追加してみましょう。

$ php cli/console.php hello Aura
Hello Aura!

とまあ、使い方はこんな感じです。

helloコマンドのソース

さて、helloコマンドのソースを探してみましょう。以下にあります。

config/Common.php

    protected function modifyCliDispatcher(Container $di)
    {
        $context = $di->get('aura/cli-kernel:context');
        $stdio = $di->get('aura/cli-kernel:stdio');
        $logger = $di->get('aura/project-kernel:logger');
        $dispatcher = $di->get('aura/cli-kernel:dispatcher');
        $dispatcher->setObject(
            'hello',
            function ($name = 'World') use ($context, $stdio, $logger) {
                $stdio->outln("Hello {$name}!");
                $logger->debug("Said hello to '{$name}'");
            }
        );
    }

$diはDIコンテナですから、DIコンテナからcontext、stdio、logger、dispatcherを取得して、dispatcherにhelloをクロージャで登録していることがわかります。

以下で標準出力に出力していることがわかります。

                $stdio->outln("Hello {$name}!");

このように、コマンドを書く場合は、DIコンテナからcontext、stdio、loggerなどを取得して処理をすればいいということがわかります。

ちなみに、config/Common.phpはプロジェクトの設定ファイルです。なぜ、そんなところにコマンドを書いているのか?と疑問に思われると思いますが、これは、ルーティング設定にコントローラのコードを書くような感じです。

クラスファイルにするまでもないので、設定ファイルに書いてしまっているということです。もちろん、実際に使うコードでは通常はクラスにすることになるでしょう。

helloコマンドをクラス化

それでは、helloコマンドをクラス化してみましょう。

HelloCommandクラスは以下のようになります。

src/HelloCommand.php

<?php

use Aura\Cli\Stdio;
use Aura\Cli\Context;
use Psr\Log\LoggerInterface;

class HelloCommand
{
    public function __construct(
        Context $context, Stdio $stdio, LoggerInterface $logger
    )
    {
        $this->context = $context;
        $this->stdio = $stdio;
        $this->logger = $logger;
    }

    public function __invoke($name = 'World')
    {
        $this->stdio->outln("Hello {$name}!");
        $this->logger->debug("Said hello to '{$name}'");
    }
}

そして、設定を上記のクラスを使うように変更します。

--- a/config/Common.php
+++ b/config/Common.php
@@ -9,6 +9,12 @@ class Common extends Config
     public function define(Container $di)
     {
         $di->set('aura/project-kernel:logger', $di->newInstance('Monolog\Logger'));
+
+        $di->params['HelloCommand'] = [
+            'context' => $di->lazyGet('aura/cli-kernel:context'),
+            'stdio' => $di->lazyGet('aura/cli-kernel:stdio'),
+            'logger' => $di->lazyGet('aura/project-kernel:logger'),
+        ];
     }

     public function modify(Container $di)
@@ -35,16 +41,11 @@ class Common extends Config

     protected function modifyCliDispatcher(Container $di)
     {
-        $context = $di->get('aura/cli-kernel:context');
-        $stdio = $di->get('aura/cli-kernel:stdio');
-        $logger = $di->get('aura/project-kernel:logger');
         $dispatcher = $di->get('aura/cli-kernel:dispatcher');
+
         $dispatcher->setObject(
             'hello',
-            function ($name = 'World') use ($context, $stdio, $logger) {
-                $stdio->outln("Hello {$name}!");
-                $logger->debug("Said hello to '{$name}'");
-            }
+            $di->lazyNew('HelloCommand')
         );
     }

以下の最初の変更箇所は、コンストラクタインジェクションです。

        $di->params['HelloCommand'] = [
            'context' => $di->lazyGet('aura/cli-kernel:context'),
            'stdio' => $di->lazyGet('aura/cli-kernel:stdio'),
            'logger' => $di->lazyGet('aura/project-kernel:logger'),
        ];

これで完了です。本当はヘルプクラスも必要ですが、とりあえず省略です。

$ php cli/console.php hello
Hello World!
$ php cli/console.php hello Aura
Hello Aura!

はい、同じように動作しました。

長くなりそうなので、続きは次回にしたいと思います。

関連

Tags: aura, cli, codeigniter, php

FuelPHP 1.8-dev 公式ドキュメントの翻訳が完了しました!

FuelPHP Advent Calendar 2015 の1日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。

FuelPHPドキュメント翻訳の歴史

そもそもFuelPHPの公式ドキュメントの翻訳が始まったのは、2011年11月10日に遡ります。

GitHubで本家のドキュメントリポジトリがフォークされ、日本語翻訳のためのリポジトリが作成されました。

その時のFuelPHPのバージョンは1.2でした。

▼コミットのグラフ(本家リポジトリでのコミットも含む)

それから4年、ずっと翻訳は続き、今回初めて全ページの翻訳が完了し、本家の最新ドキュメント(1.8-dev)に追いつきました!

FuelPHP日本語ドキュメントの現状

最新の日本語ドキュメントは以下から閲覧できます。

これは、本家1.8/developブランチのドキュメントの翻訳です。つまり、1.x系の最新の開発版のドキュメントです。原文の内容は開発やドキュメントのバグ修正に伴い変わっていきます。php7に対応したFuelPHP 1.7.4がリリースされれば、その時点では1.7.4のドキュメントになります。

一方、以下はFuelPHP 1.7.0がリリースされる直前の本家1.7/developブランチが原文のため、かなり古いです。ご注意下さい。

1.7.4がリリースされたら、1.8/develop_japaneseをこのURLにマージできれば、わかりやすくなると思います。

日本のFuelPHPコミュニティは素晴らしい

FuelPHPはコミュニティにより開発されているフレームワークであり、この翻訳もコミュニティにより進められています。

翻訳が今まで続き、一通り完了したことは、ひとえに日本のコミュニティの力であり、日本のFuelPHPコミュニティは本当に素晴らしいです。

今までに以下の方がこの翻訳に参加しています(クレジットに名前を記載していない人は除く)。

https://github.com/NEKOGET/FuelPHP_docs_jp/blob/1.8/develop_japanese/CREDITS.md より。

翻訳に参加したい方へ

翻訳はGitHubのリポジトリにPull Requestすることで進められています。細かいことは、以下のREADMEをご覧下さい。

一通り完了したとはいえ、今後も原文の更新に合わせて翻訳は続いていきます。

また、既存の翻訳の誤り、日本語としてこなれていない箇所、表記の不統一など改良の余地はまだあると思います。

そういうわけで、みなさんのご参加をお待ちしています。

GitHubやGitの細かい使い方がよくわからないという方は、私の電子書籍『FuelPHPに貢献する方法』をご覧下さい(無料で入手できます)。一部、GitHubのスクリーンショットが古いですが、最近、半分以上を最新のものに更新しました。

ドキュメント翻訳に関して一番言いたいこと

さて、FuelPHPのドキュメントは一通り翻訳が完成して万歳!という感じですが、ドキュメントの翻訳という問題は今後もドキュメントが更新される度に、また、他のオープンソースプロジェクトにも存在します。

基本的には多くのプロジェクトで翻訳に参加する人が足りず、あまり翻訳が進まない、あるいは、うまく行っていそうなプロジェクトでも1人か2人でやっているという、トラックナンバー(その人数がトラックに引かれたらプロジェクトが進まなくなる数のこと)が非常に少ない危険な状態だったりすることもあります。

ということで、少しでも翻訳に興味があれば、是非、自分の使っているソフトウェアの翻訳プロジェクトに参加してみてください。技術文書の翻訳は基本的にはそんなに難しくありません。

また、母国語でドキュメントが読める、学習できるということは非常に重要なことです。もし、あなたが日本語で学習してきた経験があるなら、これから学習する人も日本語で学習できるように少しだけ手助けすることについて考えてみてください。

例えば、FuelPHPのドキュメントは現在163ページあります。仮に163人で翻訳すれば1人1ページで完成します。

それから、翻訳を改善するフィードバック方法があり機能している限り、翻訳が間違っていたり、よくない翻訳だったりすることは問題ではありません。翻訳は誰がやっても間違えるものです。

「腐った翻訳」などとブログで一方的に批難する必要はありませんし、あまり有効な方法とは言えません。誤訳を修正し、翻訳の質を改善したものをフィードバックしてください。FuelPHPのドキュメント翻訳では Pull Request です。

少なくとも、SNSやブログなどで一方的に翻訳について批難するのは、フィードバック方法がなかったりまったく機能していない場合の最後の手段にするのがよいと思います。

まとめ

  • 4年の歳月をかけ、FuelPHPドキュメントの翻訳が完了しました。この偉業をみなさん褒めたたえましょう!
  • できたらドキュメント翻訳プロジェクトに参加してみましょう。
  • よくない翻訳を見かけたら、修正をフィードバックしましょう。

関連

Tags: fuelphp

PHP7の開発環境をVagrant+CentOS7上に30分で構築する

PHP7の正式リリースが12/3に迫っています。

今日は、VirtualBoxとVagrantを使って、PHP7の開発環境を簡単に作成します。

VirtualBoxとVagrantのインストール

フリーな仮想化ソフトウェアであるVirtualBoxを、以下からダウンロードしインストールします(執筆時の動作確認バージョンはVirtualBox 5.0.10)。

VirtualBoxの仮想イメージを操作するツールであるVagrantを、以下からダウンロードしインストールします(執筆時の動作確認バージョンはVagrant 1.7.4)。

PHPプロジェクトの準備

まず、PHPプロジェクトを用意します。PHP7で動作するものを用意してください。

ここでは、Fat-Free Framework をインストールします(ただし、Fat-Free 3.5.0がPHP7に完全に対応しているかどうかは不明です)。

https://github.com/bcosca/fatfree/archive/master.zip をダウンロードして展開します。

次にWebのドキュメントルートを仮想マシンでの設定に合わせるため、プロジェクトの直下にpublcフォルダのシンボリックリンクを作成します。

$ cd fatfree-master/
$ ln -s . public

これで準備完了です。

仮想マシンの作成

PHPプロジェクトのルートディレクトリ(ここではfatfree-master)に vagrant-fuelphp-centos7 をインストールします。

$ cd fatfree-master/
$ git clone https://github.com/kenjis/vagrant-centos7-php.git

仮想マシンを構築します。

$ cd vagrant-fuelphp-centos7/
$ vagrant up

初回はCentOS7の仮想イメージをダウンロードするため、時間がかかりますので気長に待ちます(このダウンロード時間を含めると30分で開発環境を構築するのは無理かもしれません)。

これで、仮想マシンが作成され、PHPでの開発に必要なサーバなどもインストール設定されます。

これで、http://localhost:8000/ にアクセスすれば、以下のページが表示されます。

ディレクトリ構成

ホスト(手許のPC)側

fatfree-master/ ... PHPプロジェクトのトップ
├── public/     ... Webドキュメントルート
└── vagrant-fuelphp-centos7/

ゲスト(仮想マシン)側

/mnt/project/
├── public/
└── vagrant-fuelphp-centos7/

仮想マシンから、ホスト側のfatfree-masterフォルダを共有しているので、ホスト側から好きなエディタでソースを変更すれば、仮想マシンに自動的に反映されます。

SSHでのアクセス

vagrant-fuelphp-centos7フォルダから、vagrant sshコマンドで仮想マシンにSSHで接続できます。

$ cd fatfree-master/vagrant-fuelphp-centos7/
$ vagrant ssh

なお、ホームディレクトリにシンボリックリンクが張ってあるので、/mnt/projectフォルダには~/projectでアクセスできます。

サーバ環境

vagrant-fuelphp-centos7で作成される仮想マシンのサーバ環境は以下のようになっています。

  • メモリ 480MB
  • HDD 40GB
  • OS CentOS 7.1 (64bit)
  • Apache 2.4.6
  • MariaDB 5.5.44
  • PHP 7.0-RC8 (Remi RPM)
  • phpMyAdmin 4.4.15.1 (Remi RPM)
  • PHPUnit 5.0
  • Composer 1.0-dev

ホスト側のポート8000が仮想マシンのポート80に転送されるようになっています。仮想マシンに直接アクセスする場合は、http://192.168.33.33/ にアクセスします。

ホストのPHPプロジェクトのフォルダが仮想マシンの/mnt/projectにマウントされるようになっています。

また、http://localhost:8000/phpmyadmin/ から、phpMyAdminにアクセスできます。MariaDBのrootアカウントのパスワードはrootです。

仮想マシンの起動と停止

仮想マシンの停止は、vagrant-fuelphp-centos7フォルダに移動して、

$ vagrant halt

とします。vagrant suspendコマンドを実行すれば、仮想マシンをシャットダウンせずに状態を保存したまま停止できます。

仮想マシンの起動は、

$ vagrant up

仮想マシンを破棄するには、

$ vagrant destroy

とします。

その他のVagrant環境

今回の開発環境はCentOS 7.1を使ったものですが、Debian 8を使ったRasmusさんの開発環境が公開されています。

関連

Tags: php7, php, vagrant, centos7, centos