フィボナッチ数の計算でPHP7、Perl、Ruby、Pythonをベンチマークしてみた

【PHP, Ruby, Python, Perl】ベンチマーク対決【フィボナッチ数】 という記事がありました。

PHP、Ruby、Python、Perlでフィボナッチ数の39番目「63245986」を求める時間でベンチマークするというものでした。

この記事では、PHP 5.5がRuby 2.0の2倍以上かかっていました。

language version time
PHP 5.5.5 0:20.47
Ruby 2.0.0p247 0:09.21

今回、PHP7がリリースされましたので、手許で計測してみました。

language version time
PHP 7.0.1-dev 0:06.61
Perl 5.20.2 1:06.21
Python 2.7.9 0:21.47
Ruby 2.1.5p273 0:10.88

PHP7はRuby 2.1より速くなっていました。

ソースを以下のリポジトリに置きましたので、最新のRubyだとどうなるかなど興味のある方は計測してみてください。

関連

Tags: php, php7, perl, ruby, python

CodeIgniter 3.0のモダンなインストール方法

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

今日は、CodeIgniter 3.0のモダンなインストール方法です。

ところで、モダンって何でしょうね?この用語もきちんと定義されていませんが、ここでは「何となく今っぽい」くらいの意味で使ってます。

ただ、PHPのバージョンとしては5.4以上とします。PHP 5.3でもCodeIgniter本体はインストールでき動作しますが、この記事に出てくるコンポーネントの中には動作しないものが含まれます。

なお、PHP 5.4も保守はすでに終了していますので、5.5、5.6または7.0へ移行した方がよいでしょう。

Composerのインストール

モダンPHPと言えば、Composerです。

Composerとは、PHPでの新しいパッケージ(ライブラリ)管理システムです。簡単に言うとPEARの後継みたいなものです。

Composerはパッケージ管理コマンドとしてのcomposerコマンド、パッケージのリポジトリとしてのPackagist、そしてクラスファイルをオートロードするオートローダを提供します。

PAERが主にサーバにライブラリをインストールし、各プロジェクトはそのサーバの共有ライブラリを使ったのに対し、Composerでは主にパッケージを各プロジェクト配下にインストールして使います。

Linux/Mac OS XでのComposerのインストール

以下のコマンドでインストールできます。

$ curl -sS https://getcomposer.org/installer | php
$ sudo mkdir -p /usr/local/bin
$ sudo mv composer.phar /usr/local/bin/composer

WindowsでのComposerのインストール

https://getcomposer.org/Composer-Setup.exe にインストーラがあるので、ダウンロードして実行してください。

なお、Windowsでのコマンドの実行には、Git for Windows に含まれるGit Bashを使うことをお薦めします。

CodeIgniterのインストール

さて、Composerがインストールできましたので、ここからが本題のCodeIgniterのインストールです。

CodeIgniter 3.0をインストールするには、ターミナルまたはGit Bashから以下のコマンドを実行します。最後のcodeigniterはフォルダ名なので必要なら変更してください。

$ composer create-project kenjis/codeigniter-composer-installer codeigniter

上記のコマンドは、以下を実行します。

  1. プロジェクトのフォルダを作成し、CodeIgniterをComposerでvendorフォルダ以下にインストールする
  2. applicationフォルダをプロジェクトのトップにコピーする
  3. index.phppublic/index.phpにコピーする
  4. フォルダ構成の変更に伴うパスの調整とCodeIgniterからComposerのオートローダを使えるように設定する

ここで、インストールされるCodeIgniterは本家の3.0.*です。

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

codeigniter/
├── application/
├── composer.json ... Composerの設定ファイル
├── composer.lock ... Composerのロックファイル
├── public/
│   └── index.php
└── vendor/
    └── codeigniter/
        └── framework/
            └── system/

Composerのロックファイルは自動的に生成されるものでインストールされたパッケージのバージョンなどの情報が記録されます。さわってはいけません。また、vendorフォルダ以下にパッケージのソースがインストールされます。vendorフォルダの中もComposerがすべて管理しますので、中のファイルを編集などしてはいけません。

実際にコマンドを実行すると、以下のようにインストールされます。

$ composer create-project kenjis/codeigniter-composer-installer codeigniter
Installing kenjis/codeigniter-composer-installer (v0.4.0)
  - Installing kenjis/codeigniter-composer-installer (v0.4.0)
    Downloading: 100%         

Created project in codeigniter
Loading composer repositories with package information
Installing dependencies (including require-dev)
  - Installing codeigniter/framework (3.0.3)
    Loading from cache

Writing lock file
Generating autoload files
> Kenjis\CodeIgniter\Installer::postInstall
> composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing mikey179/vfsstream (v1.1.0)
    Loading from cache

Writing lock file
Generating autoload files
> Kenjis\CodeIgniter\Installer::showMessage
==================================================
`public/.htaccess` was installed. If you don't need it, please remove it.
If you want to install translations for system messages or some third party libraries,
$ cd <codeigniter_project_folder>
$ php bin/install.php
Above command will show help message.
See <https://github.com/kenjis/codeigniter-composer-installer> for details
==================================================

はい、完了しました。

   - Installing codeigniter/framework (3.0.3)

CodeIgniter 3.0.3がインストールされたことがわかります。

追加コンポーネントのインストール

CodeIgniter本体のインストールはできましたが、本体だけでいいというケースはほとんどないと思います。

もともとCodeIgniterは最小限のパーツしか提供しないので、自分でパーツを足して作り込んでいく感じのフレームワークです。また、日本語サイトには日本語のシステムメッセージが必要です。

ということでその他必要なものを追加でインストールします。

そのためのサンプルのシェルスクリプトがbin/my-codeigniter.shにインストールされています。以下のコマンドで実行できます。

$ cd codeigniter/
$ bin/my-codeigniter.sh

このコマンドは以下をインストールします。これらは、個人的にどんなプロジェクトにも必要そうなものです。

むろん、これはサンプルなので、不要なものはインストールする必要はないですし、必要なコンポーネントなどがあれば、さらに追加することになります。

Roave Security Advisories

Roave Security Advisoriesは、FriendsOfPHP/security-advisories のデータを使い脆弱性のあるパッケージをチェックするものです。

ただし、データは日次更新のようでタイムラグがあり、リアルタイムではありません。

また、パッケージの追加および更新時にのみチェックするもので、composer.lockファイルによりcomposer installする場合にはチェックはされません。インストール後または更新後に脆弱性が報告されたパッケージはそのままデプロイされることになります。

つまり、既知の脆弱性を含むパッケージを確実にデプロイしたくない場合は、デプロイ時にsecurity-checker.pharでチェックする必要があります。

ちなみに、Vulnerability Database - SensioLabs Security Advisories Checker にCodeIgnirer 3.0.2以前を登録しましたので、3.0.2以前を新規でインストールしようとすると、以下のように失敗します。

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - codeigniter/framework 3.0.2 conflicts with roave/security-advisories[dev-master].
    - codeigniter/framework 3.0.2 conflicts with roave/security-advisories[dev-master].
    - codeigniter/framework 3.0.2 conflicts with roave/security-advisories[dev-master].
    - Installation request for codeigniter/framework 3.0.2 -> satisfiable by codeigniter/framework[3.0.2].
    - Installation request for roave/security-advisories dev-master -> satisfiable by roave/security-advisories[dev-master].

Webサーバの起動

モダンPHPには、ビルトインWebサーバがあります(PHP 5.4以降)。以下のコマンドでWebサーバが起動します。

$ bin/server.sh

これで、http://127.0.0.1:8000/ にブラウザでアクセスすれば、お馴染みのCodeIgniterのWelcomeページが表示されます。

CodeIgniterのバージョンアップ

CodeIgniterのバージョンが上がっても、CodeIgniterプロジェクトのトップディレクトリに移動し、以下のコマンドを実行すれば更新できます。

$ composer update

例えば、こんな風に更新されます。

$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Removing codeigniter/framework (3.0.2)
  - Installing codeigniter/framework (3.0.3)
    Loading from cache

Writing lock file
Generating autoload files

ただし、もし、applicationフォルダ内のファイルやindex.phpが変更されている場合は、それらを手動で更新する必要があります。その場合は、ユーザガイドに従って作業してください。

systemフォルダ以下は完全に更新されますので、systemフォルダ以下のファイルを直接変更してはいけません。バージョンアップ時に変更が消えてなくなります。というか、vendorフォルダ以下はComposerが管理するので、ファイルの変更や追加をしてはいけません。

まとめ

  • Composerは、PHPの新しいパッケージ(ライブラリ)管理システムです。
  • CodeIgniter 3.0はComposerでモダンにインストールすることもできます。

関連

Tags: codeigniter

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

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

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

前回は、Aura.Cli_Projectをインストールし、helloコマンドをクラス化しました。

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

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

コマンドファイル

さて、コマンドファイルはどのようになっているか確認してみましょう。

cli/console.php

<?php
/**
 * 
 * This file is part of Aura for PHP.
 * 
 * @package Aura.Cli_Project
 * 
 * @license http://opensource.org/licenses/bsd-license.php BSD
 * 
 */
$path = dirname(__DIR__);  // (1)
require "{$path}/vendor/autoload.php";  // (2)
$kernel = (new \Aura\Project_Kernel\Factory)->newKernel(  // (3)
    $path,                                                // (3)
    'Aura\Cli_Kernel\CliKernel'                           // (3)
);                                                        // (3)
$status = $kernel();  // (4)
exit($status);
  1. $pathにプロジェクトのルートディレクトリを設定
  2. Composerのオートローダの読み込み
  3. Aura\Project_Kernel\Factoryクラスからカーネルを生成
  4. カーネルの実行

をしていることがわかります。

CodeIgnirerへの統合

Auraを使いCodeIgniterのコマンドラインツールを作成したわけですが、統合といってもできるだけAuraそのままで統合しています。

フォルダ構成は以下のようになってます。clicli/console.phpに相当します。

codeigniter/
├── application/
├── ci_instance.php ... CodeIgniterインスタンスを生成するスクリプト
├── cli             ... コマンドファイル
├── config/         ... 設定を配置
├── src/            ... ソースを配置
└── vendor/

ソースは以下にあります。

CodeIgniter用コマンドファイル

コマンドファイルは以下のようになりました。

cli

#!/usr/bin/env php
<?php
/**
 * Part of Cli for CodeIgniter
 *
 * @author     Kenji Suzuki <https://github.com/kenjis>
 * @license    MIT License
 * @copyright  2015 Kenji Suzuki
 * @link       https://github.com/kenjis/codeigniter-cli
 */

$path = __DIR__;
chdir($path);  // (1)

/** @const ROOTPATH CodeIgniter project root directory */
define('ROOTPATH', __DIR__ . '/');  // (2)

require "{$path}/vendor/autoload.php";

// generate CodeIgniter instance
$ci = require "{$path}/ci_instance.php";  // (3)

class_alias('Kenjis\CodeIgniter_Cli\Command\Command', 'Command');  // (4)
class_alias('Kenjis\CodeIgniter_Cli\Command\Seed',    'Seeder');   // (4)
class_alias('Aura\Cli\Help', 'Help');                              // (4)

$kernel = (new \Aura\Project_Kernel\Factory)->newKernel(
    $path,
    'Aura\Cli_Kernel\CliKernel'
);
$status = $kernel();
exit($status);

Auraのものとほとんど変わらないのですが、

  1. プロジェクトのルートディレクトリへのchdir()
  2. 定数ROOTPATHの追加
  3. CodeIgniterインスタンスの生成
  4. クラスエイリアスの設定

が追加されています。

「CodeIgniterインスタンス」というのは、いわゆる「神オブジェクト」的なCodeIgniterのオブジェクトで、このオブジェクトのプロパティにCodeIgniterのライブラリなどがロードされます。

以下のようなCodeIgniterのコントローラやモデルのコードではこのCodeIgniterインスタンスを利用しています。

$this->load->library('form_validation');
$this->form_validation->set_rules('username', 'Username', 'required');

また、CodeIgniterインスタンスは以下のようにget_instance()関数で取得できるシングルトン的なオブジェクトです。

$CI =& get_instance();

CodeIgniterインスタンスの注入

そして、CodeIgniterインスタンスをコマンドクラスで使えるように、DIコンテナに設定します。

config/Common.php

    public function define(Container $di)
    {
        ...

        /* @var $ci \CI_Controller */
        $ci =& get_instance();

        // register built-in command classes
        foreach ($this->commands as $command) {
            $class = 'Kenjis\CodeIgniter_Cli\Command\\' . $command;
            $di->params[$class] = [
                'context' => $di->lazyGet('aura/cli-kernel:context'),
                'stdio' => $di->lazyGet('aura/cli-kernel:stdio'),
                'ci' => $ci,  // ここ
            ];
        }

        ...
    }

これで、コマンドクラスのコンストラクタにCodeIgniterインスタンスが注入されます。

コマンドクラス

コマンドクラス(コマンドを実装するクラス)では、コンストラクタ引数にCodeIgniterインスタンスが注入されるので、以下のようにプロパティに代入すればクラス内で使えます。

以下は、親クラスとなる抽象クラスのコードです。

src/Command/Command.php

    public function __construct(Context $context, Stdio $stdio, CI_Controller $ci)
    {
        $this->context = $context;
        $this->stdio = $stdio;
        $this->ci = $ci;

        $this->ci->load->database();
        $this->db = $this->ci->db;
        $this->ci->load->dbforge();
        $this->dbforge = $this->ci->dbforge;
    }

さらに、CodeIgniterインスタンスのプロパティがコマンドクラスでも使えるように、マジックメソッドを追加しました。

src/Command/Command.php

public function __get($property)
    {
        if (! property_exists($this->ci, $property)) {
            ob_start();
            var_dump(debug_backtrace());
            $backtrace = ob_get_clean();
            file_put_contents(ROOTPATH . '/tmp/backtrace.log', $backtrace, LOCK_EX);
            $this->stdio->errln(
                '<<red>>No such property: ' . $property . ' in CodeIgniter instance<<reset>>'
            );
            $this->stdio->errln('Backtrace was saved in tmp/backtrace.log');
            throw new RuntimeException('Property does not exist');
        }

        return $this->ci->$property;
    }

これで、コマンドクラス内でも以下のようにCodeIgniterのライブラリが使えます。

        $this->load->library('migration');
        $this->load->config('migration');

以下は、マイグレーションを実行するコマンドクラスです。

src/Command/Migrate.php

<?php
/**
 * Part of Cli for CodeIgniter
 *
 * @author     Kenji Suzuki <https://github.com/kenjis>
 * @license    MIT License
 * @copyright  2015 Kenji Suzuki
 * @link       https://github.com/kenjis/codeigniter-cli
 */

namespace Kenjis\CodeIgniter_Cli\Command;

use Aura\Cli\Status;

/**
 * @property \CI_Migration $migration
 * @property \CI_Loader    $load
 * @property \CI_Config    $config
 */
class Migrate extends Command
{
    public function __invoke($command = null)
    {
        $this->load->library('migration');
        $this->load->config('migration');

        if ($command === 'status') {
            $this->listMigrationFiles();
            return;
        }

        if ($command === 'version') {
            $this->showVersions();
            return;
        }

        // if argument is digits, migrate to the version
        if (ctype_digit($command)) {
            if ($this->migrateToVersion($command) === false) {
                return Status::FAILURE;
            } else {
                $this->showVersions();
                return;
            }
        }

        if ($command !== null) {
            $this->stdio->errln(
                '<<red>>No such command: ' . $command . '<<reset>>'
            );
            return Status::USAGE;
        }

        // if no argument, migrate to current
        if ($this->migration->current() === false) {
            $this->stdio->errln(
                '<<red>>' . $this->migration->error_string() . '<<reset>>'
            );
            return Status::FAILURE;
        } else {
            $this->showVersions();
        }
    }

    ...
}

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

関連

Tags: aura, cli, codeigniter, php