Open DanielPlainview opened 11 years ago
Я уже написал комментарий в коде что сейчас ModelAndView это просто контейнер. Ну можно добавить в него ещё переменных которые будут возвращаться из контроллера и это будет дельно. Но заставлять его render'ить уже лишнее. Подобную логику стоит держать в отдельном классе обработавающим ModelAndView.
Но заставлять его render'ить уже лишнее.
Спорно. ModelAndView
вполне может делать render сам, чтобы соблюдать tell don't ask. В OnPHP вообще есть что-то типа FrontController'а? Иначе получается, что у многих будет повторение вида
$view = $mav->getView();
$headerCollection = $mav->getHeaderCollection();
$cookieCollection = $mav->getCookieCollection();
$status = $mav->getStatus();
if (is_string($view)) {
$view = ...;
}
header($status->toString());
// send $headerCollection
$cookieCollection->httpSetAll();
echo $view->render($mav->getModel());
Мне кажется странным использовать ModelAndView для писем.
Ну MaV сейчас ни для чего не используется кроме передачи model и view. Странным может казаться любое его использование.
Так ведь BC это не ломает, а странность его использования только подтолкнёт к рефакторингу.
Надо подумать по поводу FrontController.
Я положительно отношусь к необходимости где-то (не во вью) аккумулировать заголовки и все остальное, что связано с http, но ИМХО ModelAndView не совсем удачное место для этого.
Вот например, у меня сейчас в проекте почти везде два представления - html или json поэтому заголовки в MaV мне не нужны, ибо они разные будут, и только фронт-контроллер знает какие отдавать. А контроллеру приложения пофиг, он свою работу выполнил - данные собрал, объекты обновил.
Более того, есть случаи, когда контекст http вообще отсутствует, при этом стандартная MVC вполне может быть.
Вот например, у меня сейчас в проекте почти везде два представления - html или json поэтому заголовки в MaV мне не нужны
А откуда заголовки будут браться?
Более того, есть случаи, когда контекст http вообще отсутствует, при этом стандартная MVC вполне может быть.
Я не вижу реального кейса. Сейчас у нас есть HttpRequest
, но внезапно нет HttpResponse
. Я могу сделать отдельный класс, но это потребует существенной переработки существующего кода в проекте. Везде ожидается ModelAndView
и с этим надо как-то жить.
фронт-контроллер знает какие отдавать
Не во FrontController, допустим. А в каком-то фильтре. Причём мне это видится как-то так:
class UserController implements Controller
{
public function handleRequest(HttpRequest $request)
{
$user = User::dao()->getById($request->getGetVar('id'));
return
ModelAndView::create()->
setView('viewUser')->
setModel(
Model::create()->set('user', $user)
);
}
}
class ResponseFormatFilter extends DecoratorController
{
private $view;
public function __construct(CustomView $view)
{
$this->view = $view;
}
public function handleRequest(HttpRequest $request)
{
$response = parent::handleRequest($request);
$format = $request->hasAttachedVar('format'); // Enumeration (HTML, JSON, XML, Protobuf, etc.)
if (!$format->isHtml()) {
$response->getHeaderCollection()->set('Content-Type', $format->getContentType());
$response->setView($this->view->setFormat($format));
}
return $response;
}
}
class CustomView implements View
{
private $serializer;
private $format;
public function __construct(JMS\Serializer $serializer)
{
$this->serializer = $serializer;
}
public function setFormat(Format $format)
{
$this->format = $format;
return $this;
}
public function render(Model $model)
{
echo $this->serializer($model->toArray(), $this->format->getName());
return $this;
}
}
GET /42.user.html
=> ...<span class="name">Blah</span>...
GET /42.user.json
=> {"user": {"id": 42, "name": "Blah"}}
GET /42.user.pb
=> бинарый protobuf response
Кстати, а для ObjectNotFoundException
можно запилить такой фильтр:
class NotFoundResourcesFilter extends DecoratorController
{
private $logger;
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
public function handleRequest(HttpRequest $request)
{
try {
$response = parent::handleRequest($request);
} catch (ObjectNotFoundException $e) {
$this->logger->logException($e);
$response = $this->createNotFoundResponse();
}
return $response;
}
}
Тогда в коде выше проверка наличия юзера не нужна и будет вполне RESTful.
Примеры выше это примеры лишь одного проекта. В других проектах другие решения. То что тут делает ResponseFormatFilter, в других местах делают другие классы подругому.
Идея поместить в MAV данные о заголовках, сомнительна
Может в мав помещать view а в в него уже заголовки ?
Позволяет делать редирект, выставлять заголовки/cookies более православно.
Во front controller будет что-то типа