我正在使用MVC技术实现PHP应用程序。加载http://site/photos/25?options
的简要介绍,重写为http://site/index.php?page=photos&id=25&options
:
index.php
- >实例化并调用PhotoController
object PhotoController
实例化PhotoView
并将正确的Photo
(模型)加载到其中PhotoController
调用PhotoView->render()
和页眉/页脚视图PhotoView
可以访问Photo
模型及其所需的其他模型数据 PhotoView
将输出HTML并希望超链接到不同的页面。当该视图生成超链接时,我对哪个层应该拥有URL感到困惑。我看到的选项概述如下。请帮我选择正确的方法。
模型图层拥有网址
模型有
getURL()
方法
优点:
View
类可以包含Open Graph属性PhotoView
可以执行此操作:$folderHref = $photo->getFolder()->url
缺点:
LoginController
,AdminController
,我如何获取这些的网址?控制器拥有网址
控制器具有
url
和title
属性。要创建链接,呈现控制器将创建目标控制器并传递给视图。该视图从传递的对象访问url
和title
。
优点:
index.php
中),因此反之亦然缺点:
需要其他视图的网址的视图需要以下丑陋的黑客之一:
查询不相关的控制器$folderHref = Controllers\FolderController::urlForFolder($photo->getFolder())
了解他们的控制器$folderHref = $photo->getFolder()->getControllerAndSetURL()->getURL()
视图与其控制器$folderHref = $this->delegate->getURLForFolder($photo->getFolder())
和$adminHref = $this->delegate->getURLForAdminHref()
之间的过度通信,delegate
有多种方法
每个人都拥有网址
基类
OpenGraphObject
是Controllers
ANDModels
的父类,其方法为getURL()
Controllers
和Models
只有在没有参数的情况下才能运行它。 (例如PhotoController
返回NULL,因为URL取决于Photo
将显示的内容。
优点:
缺点
答案 0 :(得分:0)
为了解决问题,我会将其分解为:
/**
* Responsible for processing and rendering user output
*/
interface View {
public function render();
}
/**
* Used just to further formalize the messages between Photo and View
*/
interface PhotoView extends View {
public function setPhotoData($id, $title, $link);
}
/**
* Among other things knows how to generate URLs to routes
*/
interface Router {
/**
* Returns the URL to route based on route name
* @param string $routeName
* @param array $params
*/
public function urlTo($routeName, $params = null);
}
我不打算实现每个类,你可以使用大量的现成解决方案,例如模板引擎和路由器。
基于id显示图像的示例控制器可以是:
class PhotoController {
public function displayAction($photoId) {
$photo = Photo::findById($photoId);
$templateFile = $this->pathTo('photo-template.php');
//can be a singleton for example, it holds all the routes for the application
//and knows how to render them based on the name and parameters
$router = AppRouter::instance();
return $photo->render(new ConcretePhotoView($templateFile, $router));
}
}
在此示例中,Photo需要能够从数据库中获取自身,然后将自身呈现给PhotoView:
class Photo {
private $id;
private $title;
private $sourceLink;
//other methods...
public function render(PhotoView $view) {
$view->setPhotoData($this->id, $this->title, $this->sourceLink);
return $view->render();
}
}
假设HTML模板photo-template.php
如下所示:
<a href="<?= $userLogin['href'] ?>"><?= $userLogin['label'] ?></a>
<a href="<?= $userRegister['href'] ?>"><?= $userRegister['label'] ?></a>
<div>
<img src="<?= $photo['src'] ?>" title="<?= $photo['title'] ?>" />
<a href="<?= $photoLink['href'] ?>"><?= $photoLink['label'] ?></a>
</div>
应该清楚这个模板需要什么变量。没有逻辑,只是纯粹的显示,虽然一些基本的控制是可以的。
剩下的就是编写ConcretePhotoView代码,它将使用提供的模板文件和路由器来调整域对象Photo和具体的html模板之间的数据:
class ConcretePhotoView implements PhotoView {
private $templateEngine;
private $router;
public function __construct($templateFile, Router $router) {
$this->templateEngine = new SomeTemplateEngine($templateFile);
$this->router = $router;
}
public function render() {
//router has a route userLogin with no params
$this->templateEngine->assign('userLogin', array(
'href' => $this->router->urlTo('userLogin'),
'label' => 'Login'
));
$this->templateEngine->assign('userRegister', array(
//router has a route named userRegister that requires no params
'href' => $this->router->urlTo('userRegister'),
'label' => 'Register'
));
return $this->templateEngine->render();
}
public function setPhotoData($id, $title, $link) {
$this->templateEngine->assign('photo', array(
'src' => $link,
'title' => $title
));
$this->templateEngine->assign('photoLink', array(
//router has a route named photo that requires an id
'href' => $this->router->urlTo('photo', array('id' => $id)),
'label' => $title
));
}
}
最后回答“谁拥有网址?”的问题。 - 路由器。该知识封装在那里,并且特定于应用程序配置。其他对象使用它来生成链接。