SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

PHPカンファレンス実行委員プレゼンツ PHPの最前線

【PHPの最前線】PHPカンファレンス実行委員と読み解く「PHPの中身」

PHPカンファレンス実行委員プレゼンツ PHPの最前線 第1回

  • X ポスト
  • このエントリーをはてなブックマークに追加

PHP独自の機能は? 「ext/standard」のソースコードを見てみよう

 ext ディレクトリの下には、PHP本体にバンドルされている拡張モジュールのソースがありますが、この中で特に面白いのはext/standardです。この中にはかなり多くのファイルが含まれていて、いわゆるPHP標準の組み込み関数の多くもここにあります。標準の組み込み関数も「standard」という拡張モジュールの形式で実装されているのが面白いですね。

 それでは実際のPHP標準関数として explode() を例にソースコードを見ていきましょう。

explode() のソースを探る

 ext/standardで"explode"をファイル検索すると、簡単に該当部分が見つかります。割と短いのですべて引用しましょう。

PHP_FUNCTION(explode)
{
        zend_string *str, *delim;
        zend_long limit = ZEND_LONG_MAX; /* No limit */
        zval tmp;

        ZEND_PARSE_PARAMETERS_START(2, 3)
                Z_PARAM_STR(delim)
                Z_PARAM_STR(str)
                Z_PARAM_OPTIONAL
                Z_PARAM_LONG(limit)
        ZEND_PARSE_PARAMETERS_END();

        if (ZSTR_LEN(delim) == 0) {
                zend_argument_value_error(1, "cannot be empty");
                RETURN_THROWS();
        }

        array_init(return_value);

        if (ZSTR_LEN(str) == 0) {
                if (limit >= 0) {
                        ZVAL_EMPTY_STRING(&tmp);
                        zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
                }
                return;
        }

        if (limit > 1) {
                php_explode(delim, str, return_value, limit);
        } else if (limit < 0) {
                php_explode_negative_limit(delim, str, return_value, limit);
        } else {
                ZVAL_STR_COPY(&tmp, str);
                zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
        }
}

 普通のC言語のソースコードとは結構違いますね。まず関数宣言からしてPHP_FUNCTION()という見知らぬ記述で書かれています。ある程度大規模なプロジェクトではよくありますが、これはC言語のマクロを利用して実際の複雑なコードを隠蔽している記述方法です。

 ここで使われているZEND_ZSTR_で始まっている関数形式のものはすべてマクロで、Zend EngineやPHP独自の内部実装を使いやすく記述するためのものです。

 そもそもなぜこのようなマクロが必要なのでしょうか?

 PHPは言語機能としてC言語にはないさまざまな特徴を提供しており、そのために値や関数、クラスの持ち方もPHP独自の実現方法を持っています。その仕組みを毎回考慮してソースコードを書かなくても済むように、これらのマクロを利用してコードをわかりやすくしているわけです。

explode() の引数

 上記のexplode()の実装部分を見ればわかりますが、PHPのexplode()の引数はC言語の関数の引数として渡ってきてはいません。引数の受取り部分は以下となります。

       ZEND_PARSE_PARAMETERS_START(2, 3)
                Z_PARAM_STR(delim)
                Z_PARAM_STR(str)
                Z_PARAM_OPTIONAL
                Z_PARAM_LONG(limit)
        ZEND_PARSE_PARAMETERS_END();

 ZEND_PARSE_PARAMETERS_STARTZEND_PARSE_PARAMETERS_ENDというマクロで挟んだ部分で各引数を受け取っています。

 ZEND_PARSE_PARAMETERS_STARTマクロはZend/Zend_API.hで定義されていて

#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args) \
        ZEND_PARSE_PARAMETERS_START_EX(0, min_num_args, max_num_args)

必須の引数の数が2で、最大の数が3であるという意味ですね。PHP関数のexplode()の定義は

explode(string $separator, string $string, int $limit = PHP_INT_MAX): array

となっているので、$separatorと$stringという2つの引数が必須で、オプションとして$limitを渡すことができると、両者の意味がマッチしているのがわかります。

 C言語ソースコード側のexplode関数は、引数を受け取ったあとはその引数のチェックを行い、limitの値によって

  • php_explode()
  • php_explode_negative_limit()

の2つの内部関数を呼び分けていることがわかります。実際のソースコードの引用は行いませんが、これらの2つは通常のCの関数なので、PHP独自の値の扱いを除けば普通にC言語のプログラムとして読むことができます。

次のページ
PHPソースコードを読むうえで欠かせない「zval」とは?

関連リンク

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
PHPカンファレンス実行委員プレゼンツ PHPの最前線連載記事一覧
この記事の著者

小山 哲志(コヤマ テツジ)

日本PHPユーザ会、合同会社ほげ技研。フリーランスのソフトウェアエンジニア。2001年より日本のPHPコミュニティに関わる。以降のPHPカンファレンスでの登壇やスタッフとして、日本のPHPコミュニティの発展に尽力している。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/19994 2024/08/07 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング