Я пытаюсь изучить код для Slim framework. В конструкторе для класса Slim $ c передается в закрытие (например, при сохранении/установке объекта запроса/ответа в контейнере):
public function __construct(array $userSettings = array())
{
// Setup IoC container
$this->container = new \Slim\Helper\Set();
$this->container['settings'] = array_merge(static::getDefaultSettings(), $userSettings);
// Default request
$this->container->singleton('request', function ($c) {
return new \Slim\Http\Request($c['environment']);
});
// Default response
$this->container->singleton('response', function ($c) {
return new \Slim\Http\Response();
});
Но $ c не определяется/не объявляется нигде до этого утверждения, так как это работает? Я начал прослеживать все с самого начала, и я не могу найти $ c где-нибудь до того, как он будет использоваться таким образом.
$ c - параметр функции замыкания. Представьте, что у вас есть функция сама по себе:
function myFunction($c) {
echo $c;
}
В случае закрытия вы можете сохранить анонимную функцию в переменной:
$someFunction = function ($c) {
echo $c;
}
$someFunction("hello world");
Поэтому вместо прямого хранения замыкания в переменной код выше передает анонимную функцию в качестве параметра для $this-> container-> singleton(). Таким образом, $ c не создается до тех пор, пока не будет вызвано замыкание. Метод singleton сохраняет это в переменной с именем $ value, поэтому, если эта функция работает:
$value(array('environment'=>'test'));
$ c теперь будет содержать массив ('environment' => 'test')
Slim также использует малые методы __get() __set() совсем немного, поэтому из кода примера, который вы установили, в классе Slim можно было бы вызвать:
$request = $this->container->request(array('environment'=>'test'));
Контейнер имеет класс Slim\Helper\Set. Поскольку это не имеет метода запроса, это вызовет метод __get() контейнера. Он будет искать сохраненный метод, сконфигурированный выше для "запроса", и передать массив в виде $ c
$c
является ссылкой на сам контейнер, так что любые зависимости будут автоматически разрешены при вызове.
Таким образом, используя, например, объект запроса:
// Default request
$this->container->singleton('request', function ($c) {
return new \Slim\Http\Request($c['environment']);
});
Посмотрев на конструктор Request
вы увидите, что он ожидает экземпляр Environment
, который мы только что сказали, что контейнер должен быть уже доступен с помощью ключевой "среды".
Я думаю, что хартнетт дал прекрасный ответ. Чтобы сделать это более понятным для вас, пример.
Когда вы определяете функцию, вы описываете, как она работает. Вы не задаете никаких конкретных значений. Например, когда я пишу:
function sum($a, $b) {
return $a + $b;
}
Я не говорю, что здесь значения $a
и $b
. Я просто описываю, что я делаю с этими переменными, чтобы вычислить результат. Пока я не вызываю эту функцию, я работаю с фактическими значениями:
sum(3, 4); // returns 7
В вашем вопросе переменная $c
похожа на переменную $a
и $b
.
Как показал хартнетт в его ответе, он работает следующим образом:
// Definition time
$someFunction = function ($c) {
echo $c;
}
// Calling time
$someFunction("hello world");
Только время вызова, которое получает значение $c
(в этом примере значение "hello world").