#php #slim
#php #тонкий
Вопрос:
Я использую Slim Framework версии 3.
Я следовал руководству по созданию приложения. Частично это включает в себя настройку classes
каталога, в который вы можете поместить свои собственные классы PHP.
Чего я не могу понять, так это как вы можете получить доступ к Slim внутри них. Например, если у меня есть класс src/classes/Users.php
и я хотел использовать тонкий код ответа, например
return $response->withStatus(302)->withHeader('Location', 'login');
Очевидно, $response
, на данный момент недоступен. Кажется, что это только в index.php
где каждый обратный вызов получает его в качестве аргумента.
Должен ли я передавать что-то каждому конструктору моих собственных классов, или операторам use
or require
в моих классах?
Комментарии:
1. Вы должны передавать все, что вам нужно, в свои классы, подробнее о внедрении зависимостей: phptherightway.com/#dependency_injection
2. @JimL Спасибо за ссылку, но мне нужны конкретные указания по выполнению этого, а не только теория. В основном все, что я пытаюсь сделать, это использовать объект ответа (или как вы его называете) в моем Users.php класс. Я не знаю, что передать в мой класс или куда.
Ответ №1:
Я бы сказал, когда компонентам уровня домена требуется доступ к компонентам уровня приложения — это запах кода. Итак, подумайте о том, чтобы поступить иначе, объект запроса описывает запрос. Запрос содержит некоторые данные, и эти данные должны быть переданы вашему User
классу, а не самому объекту запроса.
Если вы все еще хотите использовать Request
объект в Users
классе, просто передайте его в качестве аргумента, вот так:
// in your routes
$app->post('users', function($request, $response) {
$user = new User;
$user->hydrateAndPersist($request); // there you pass it as argument
});
// in your user class
class User
{
public function hydrateAndPersist(
PsrHttpMessageServerRequestInterface $request,
PsrHttpMessageResponseInterface $response // yes, you force yourself into injecting response object
) {
// request is here, let's extract data from it
$submittedData = $request->getParams();
// terrible indeed, but this is just an example:
foreach ($submittedData as $prop => $value) {
$this->prop = $value;
}
$result = $this->save();
return $response->withJson($result);
}
}
Однако в этом случае ваш User
класс сильно связан с объектами запроса и ответа PSR-7. Иногда соединение не является проблемой, но в вашем случае User
класс принадлежит к уровню домена (поскольку он описывает пользовательскую сущность), в то время как $request
и $response
являются компонентами уровня приложения.
Попробуйте уменьшить сцепление:
$app->post('users', function($request, $response) {
$submittedData = $request->getParams();
$user = new User;
$result = $user->hydrateAndPersist($submittedData);
// response is already declared in this scope, let's "put" result of the operation into it
$response = $response->withJson($result);
return $response;
});
class User
{
public function hydrateAndPersist(array $data) : bool
{
$result = false;
foreach ($submittedData as $prop => $value) {
$this->prop = $value;
}
$result = $this->save();
return $result;
}
}
Видите преимущество? User::hydrateAndPersist
теперь принимает array в качестве аргумента, он не знает о $request
и $response
. Таким образом, он не привязан к HTTP ( PSR-7
описывает HTTP-сообщения), он может работать с чем угодно. Классы разделены, слои разделены, простота обслуживания.
Подводя итог: вы можете получить доступ к $request
объекту в вашем User
классе, просто перейдя $request
к одному из User
методов. Однако это плохой дизайн, который снизит удобство сопровождения вашего кода.