読者です 読者をやめる 読者になる 読者になる

k-holyのPHPとか諸々メモ

Webで働くk-holyがPHP(スクリプト言語)とか諸々のことをメモしていきます。ソースコードはだいたいWindowsで動かしてます。

Composerの使い方を調べたメモ(1)

PHP Composer

Composer の使い方を調べたメモ。
Ryuzee.comの記事で分からなかった部分を実際に使って試してみました。
以下、内容はほぼ推測なので、間違いがあれば指摘していただけると嬉しいです。

composer.json

上記の定義で "php composer.phar install" した結果、symfony/class-loader のソースがPackagist経由で https://github.com/symfony/ClassLoader から取得され、/vendor/symfony/class-loader/Symfony/Component/ClassLoader 以下にインストールされる。
composerによって生成された /vendor/autoload.php を読み込むことでcomposerのオートローダが利用できる。
composerのオートローダではライブラリ側のcomposer.jsonの設定に従って生成された、/vendor/composer/autoload_namespaces.php の内容が有効になるようだ。

/vendor/composer/autoload_namespaces.php

ライブラリ側のcomposer.jsonを見てみる。
https://github.com/symfony/ClassLoader/blob/master/composer.json

{
    "name": "symfony/class-loader",
    "type": "library",
    "description": "Symfony ClassLoader Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "require-dev": {
        "symfony/finder": "2.1.*"
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\ClassLoader": "" }
    },
    "target-dir": "Symfony/Component/ClassLoader",
    "extra": {
        "branch-alias": {
            "dev-master": "2.1-dev"
        }
    }
}

ここで定義した name が利用側の require で使われるパッケージ名になり、vendorディレクトリのインストール先になる。(vendor/symfony/class-loader)
ライブラリ側でも利用側と同じ依存性チェックが行われるため、この例だとPHP 5.3.3以上でないとインストール時に警告を受ける。
require-dev についてはよく分からない。必須じゃないけどオプションで、という場合に指定するもの?

autoload は psr-0 以外に何があるのか分からないけど、ここに定義したネームスペースが /vendor/composer/autoload_namespaces.php で使われている。
また、その下の target-dir はvendorディレクトリのインストール先に補完される。(vendor/symfony/class-loader/Symfony/Component/ClassLoader)
Symfonyフレームワークの一部を構成しつつ単独のライブラリとしても提供しており、なおかつPSR-0に従うため、このように設定されているのだろう。


次に、BEAR.Sundayのcomposer.jsonを例に、Packagist以外のパターンも見てみる。(かなり長いけど)

https://github.com/koriym/BEAR.Sunday/blob/master/composer.json

{
    "name": "BEAR.Sunday",
    "description": "BEAR.Sunday, a resource oriented framework",
    "keywords": ["rest", "framework", "api"],
    "homepage": "https://github.com/koriym/BEAR.Sunday",
    "version": "0.1.1",
    "license": "BSD",
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "smarty/smarty",
                "version": "3.1.8",
                "dist": {
                    "url": "http://www.smarty.net/files/Smarty-3.1.8.zip",
                    "type": "zip"
                },
                "source": {
                    "url": "http://smarty-php.googlecode.com/svn/",
                    "type": "svn",
                    "reference": "tags/Smarty_3_1_8/distribution/"
                }
            }
        },
        {
            "type": "package",
            "package": {
                "name": "crodas/haanga",
                "version": "1.0.4",
                "dist": {
                    "url": "https://github.com/crodas/Haanga/zipball/master",
                    "type": "zip"
                },
                "source": {
                    "url": "https://github.com/crodas/Haanga.git",
                    "type": "git",
                    "reference": "master"
                }
            }
        },
        {
            "type": "package",
            "package": {
                "name": "zend/zend-log",
                "version": "2.0.0beta3",
                "dist": {
                    "url": "http://packages.zendframework.com/get/Zend_Log-2.0.0beta3.tgz",
                    "type": "pear"
                },
                "autoload": {
                    "psr-0": {
                        "Zend\\Log": "php/"
                    }
                }
            }
        },        {
            "type":"package",
            "package": {
                "name": "zend/zend-cache",
                "version": "2.0.0beta3",
                "dist": {
                    "url": "http://packages.zendframework.com/get/Zend_Cache-2.0.0beta3.tgz",
                    "type": "pear"
                },
                "autoload": {
                    "psr-0": {
                        "Zend\\Cache": "php/"
                    }
                }
            }
        },
        {
            "type":"package",
            "package": {
                "name": "zend/zend-stdlib",
                "version": "2.0.0beta3",
                "dist": {
                    "url": "http://packages.zendframework.com/get/Zend_Stdlib-2.0.0beta3.tgz",
                    "type": "pear"
                },
                "autoload": {
                    "psr-0": {
                        "Zend\\Stdlib": "php/"
                    }
                }
            }
        },
        {
            "type":"package",
            "package": {
                "name": "zend/zend-eventmanager",
                "version": "2.0.0beta3",
                "dist": {
                    "url": "http://packages.zendframework.com/get/Zend_EventManager-2.0.0beta3.tgz",
                    "type": "pear"
                },
                "autoload": {
                    "psr-0": {
                        "Zend\\EventManager": "php/"
                    }
                }
            }
        },
        {
            "type":"package",
            "package": {
                "name": "xhprof/xhprof",
                "version": "1.0.0",
                "target-dir": "xhprof",
                "dist": {
                    "url": "https://github.com/koriym/xhprof/zipball/master",
                    "type": "zip"
                },
                "source": {
                    "url": "https://github.com/koriym/xhprof.git",
                    "type": "git",
                    "reference": "master"
                }
            }
        }
    ],
    "require": {
        "php": ">=5.4.0",
        "ext-apc": "*",
        "ext-curl": "*",
        "Aura/Autoload": "dev-master",
        "Aura/Di": "dev-master",
        "Aura/Router": "dev-master",
        "Aura/Signal": "dev-master",
        "Aura/Web": "dev-master",
        "BEAR/Resource": "dev-master",
        "doctrine/common": "2.2.*",
        "doctrine/dbal": "dev-master",
        "symfony/console": "2.0.*",
        "symfony/http-foundation": "2.0.*",
        "Ray/Aop": "dev-master",
        "Ray/Di": "dev-master",
        "smarty/smarty": "3.1.*",
        "guzzle/guzzle": "2.5.*",
        "monolog/monolog": ">=1.0.0",
        "zend/zend-cache": "2.0.0beta3",
        "zend/zend-stdlib": "2.0.0beta3",
        "zend/zend-eventmanager": "2.0.0beta3",
        "zend/zend-log": "2.0.0beta3"
    },
    "authors": [
        {
            "name": "Akihito Koriyama",
            "email": "akihito.koriyama@gmail.com"
        }
    ],
    "require-dev": {
        "crodas/haanga": "dev-master",
        "twig/twig": "dev-master"
    },
    "autoload": {
        "psr-0": {
            "BEAR\\Sunday": "src/",
            "Aura\\Di": "vendor/Aura/Di/src/",
            "Aura\\Router": "vendor/Aura/Router/src/",
            "Aura\\Signal": "vendor/Aura/Signal/src/",
            "Aura\\Web": "vendor/Aura/Web/src/"
        }
    }
}

smarty/smartyはパッケージをzip,ソースをSVNリポジトリから取得する例、crodas/haangaとxhprof/xhprofはGitHubにあるPackagist未登録のものを取得する例、zend/zend-log以下のZendライブラリは外部のpearサーバから取得する例として参考になる。
Packagistに登録されていないものを依存に含める場合は、最低限 repositories で name と version と dist を割り当てる必要があるということ?

Githubにある自分のライブラリで試してみる。
上記のcrodas/haangaと同様、Packagist未登録でcomposer.jsonも置いてないケース。

これで php composer.phar update すると、/vendor/phanda/pathtranslator にソースがそのまま展開された。
もちろんcomposerのautoloadでは利用できず、/vendor/composer/installed.json のみ下記のような記述が追加されている。

このライブラリはPEAR形式のファイル名なので、Symfony\Component\ClassLoader\UniversalClassLoader を使ってロードできる。

composer.json を置いてうまいこと定義すれば、名前空間使っていないライブラリでもcomposerのautoloadに登録してくれるんだろうか。

[追記]
続きを書きました。Composerの使い方を調べたメモ(2) GitHubのリポジトリをPackagistに登録してcomposerでインストール