質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • PHP

    20285questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

このコードの引数はエラーにならない?

受付中

回答 3

投稿

  • 評価
  • クリップ 2
  • VIEW 231

kyoppyy

score 2

https://qiita.com/ritukiii/items/de30b2d944109521298f#%E3%81%9D%E3%81%93%E3%81%A7%E3%82%88%E3%81%86%E3%82%84%E3%81%8Fdi%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A


このサイトのcontainer.phpに質問があります。

$container['file.logger'] = $container->protect(function($logFileName) {
    return new FileLogger($logFileName);
});

$container['twitter.manager'] = function ($c) {
    $logger = $c['file.logger']('twitter_manager.log');
    return new TwitterManager($logger);
};

$container['database.authenticator'] = function ($c) {
    return new DatabaseUserAuthenticator();
};

$container['sample'] = function ($c) {
    return new Sample($c['file.loggger']('sample.log'), $c['twitter.manager'], $c['database.authenticator']);
};


こんな風にプログラムを書いてますが、その下で

$sample = $container['sample'];


としています。

これだと

$container['sample'] = function ($c) {
    return new Sample($c['file.loggger']('sample.log'), $c['twitter.manager'], $c['database.authenticator']);
};


$cに何も入らないんじゃないかと思うんですが、なぜこんな風になっているんでしょうか?

ためしに

<?php
$container['sample'] = function ($c) {
    var_dump("test" . $c);
    return "Hello" . $c;
};
$test = $container['sample'];
var_dump($test);
?>


と書いて実行しましたが、

object(Closure)[1]
  public 'parameter' => 
    array (size=1)
      '$c' => string '<required>' (length=10)


となりました。
クロージャが返されたのはわかるんですが、なんで$cに<required>という文字が入ってるんでしょうか?普通nullとかになると思ったんですが....
あと、sampleの関数の中のvar_dumpが実行されていないようで、何も出力されませんでした。これもなぜなのかわからないです。

そして、引数をあげるとどっちもちゃんと動いていました

<?php
$container['sample'] = function ($c) {
    var_dump("test" . $c);
    return "Hello" . $c;
};
$test = $container['sample']("Hello");
var_dump($test);
?>
string 'testHello' (length=9)
string 'HelloHello' (length=10)

質問のところを太字にしました
初心者ですが、よろしくお願いします

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+3

参考にされている記事は一見、インスタンスの生成を配列で取り回しているように見えるかもしれません。
ですが実際にはDIコンテナとしてPimpleというライブラリが使用されています。
おそらく質問者さんのコードではPimpleを使用せずに配列を使っているのではないでしょうか。

use Pimple\Container;

// Pimple\Containerのインスタンスを生成
$container = new Container();

(略)

// キー(添え字)を指定して代入
$container['sample'] = function ($c) {
    return new Sample($c['file.loggger']('sample.log'), $c['twitter.manager'], $c['database.authenticator']);
};

(略)

// キー(添え字)を指定して取り出し
$sample = $container['sample'];

元記事の$containerは配列ではなく、Pimple\Containerクラスのインスタンス(オブジェクト)になります。
本来オブジェクトは配列のようにキーを指定して、値を出し入れすることはできませんが、
Pimple\ContainerクラスはArrayAccessというインターフェイスを実装しているためこれが可能になっています。

ArrayAccessが実装されたオブジェクトに配列として代入を行うとoffsetSetというメソッドが呼び出されます。
Pimpleでは代入された無名関数をprivate変数の配列に格納しています。
逆に配列として値が取り出される際にはメソッドoffsetGetが呼び出されます。
格納しておいた関数を取り出して、コンテナ自身を引数に実行しています。

$raw = $this->values[$id]; // 無名関数を取り出して、
$val = $this->values[$id] = $raw($this); // コンテナ自身を引数に実行

値を取り出すだけで処理が実行されるのはコンテナがArrayAccessを実装したクラスだから。
引数$cが渡って来るのはメソッドoffsetGet内でそう書かれているためというのが回答になります。

 参考

PHP: ArrayAccess - Manual
http://php.net/manual/ja/class.arrayaccess.php

Pimple\Container::offsetSet
https://github.com/silexphp/Pimple/blob/master/src/Pimple/Container.php#L79

Pimple\Container::offsetGet
https://github.com/silexphp/Pimple/blob/master/src/Pimple/Container.php#L98

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

文章で説明するのちょい難しいですが、

本来の振る舞いと違うかもしれませんがニュアンス的には、Closureクラスの__debugInfoがそのような出力をしているっていうだけのはずです。

<required>って入ってる理由は必要な引数ですよって言うことを出力で分かるようにしているだけになり、
そしてClosureを実行したわけではないのでsampleの関数の中のvar_dumpが実行されません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

var_dump($test('wow'));

としてみると理解しやすいかもしれません。
あしからず。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    20285questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。