一种方法是使用.htaccess
或等效工具从服务器重定向(apache 不是唯一的网络服务器)并强制重定向。它已经包含在其他答案中。但是有一种不同的方法。一个实际上会使用 MVC 的方法:根本不重定向。
MVC设计模式的简要背景
在正确实现的 MVC 中,视图实例将包含所有 UI 逻辑。他们将从模型层获取数据(“如何”构成了 Model2、MVP 和 MVVM 之间的大部分区别),决定从哪些模板组装响应,或者即使响应需要比 HTTP 位置标头更多的东西。
移动版和桌面版之间的差异将包含在视图实例中,由控制器辅助,在正确的 MVC 结构中只会改变模型层和当前视图的状态。它所做的更改应取决于用户输入。
全部设置好
以下代码将是bootstrap.php
or的一部分init.php
:
// the request instance acts like abstraction for all the user input
$request = new Request;
$request->setUri();
// instantiate the routing mechanism
$router = new Router( new RouteBuilder );
$router->import('/path/to/config.file');
// apply rules from router so that request instance now
// contains the parsed values from URI
$router->route( $request );
// handling of model layer
$serviceFactory = new ServiceFactory;
// since in MVC the controllers are closely tied to views
// (1 controller for 1 view), usually it is convenient to use same class names
$resource = $request->getParameter('resource');
// instantiation of view and controller
$class = '\\View\\' . $resource;
$view = new {$class}( $serviceFactory );
$class = '\\Controller\\' . $resource;
$controller = new {$class}( $serviceFactory, $view);
// i find it convenient to have controller's action be made from
// both REQUEST_METHOD and command name
$action = $request->getMethod() . $request->getParameter('command');
// run it all
$controller->{$action}( $request );
echo $view->render();
这样,当执行到控制器的动作时,它会提供一个完全准备好的实例Request
。所述实例决定了用户设备的详细信息,并为读取这些详细信息提供了一个简单的界面。
控制器还可以访问模型层和当前视图,这两者都是通过构造函数注入其中的。
决定展示什么。
最直接的方法是让控制器改变当前视图的状态。
namespace Conroller;
class SomeThing
{
public function getUserDetails( $request )
{
if ( $request->isFromMobile() )
{
$this->view->adjustFor( $request->getDeviceType() );
}
$community = $this->serviceFactory->create('Community');
$community->loadUser( $request->getParameter('id'));
}
}
在这种情况下,该adjustFor()
方法通知当前视图实例,它需要使用模板,这些模板适用于某些非默认设备。
这种方法有一个非常重要的缺点:它违反了 SOLID 原则中的OCP(对于懒惰的人:短版本),因为如果您决定为现有项目添加移动版本,则必须重写每个控制器方法。
.. 有一个更好的方法
虽然下面的代码比较容易理解,但还是有一点缺陷:
$resource = $request->getParameter('resource');
// instantiation of view and controller
$class = '\\View\\' . $resource;
$view = new {$class}( $serviceFactory );
即使您只需要同时提供 HTML 和 JSON/XML 响应,它也会开始崩溃。视图开始IF
在整个代码中累积相同的重复 s。这是一个明确的信号,表明您应该使用polymorphism,而这些行将是使用它的地方。
除了上面显示的代码,您可以使用以下代码:
$resource = $request->getParameter('resource');
$class = '\\View\\' . $request->getDeviceType . $resource;
$view = new {$class}( $serviceFactory );
现在,当您拥有移动/桌面应用程序时,您有两个类:\View\DekstopSomething
和\View\MobileSomething
. 它们每个都可以有单独的逻辑,并从模型层请求完全不同的数据。
同时,您的其余代码与输出形式完全分离。
有什么好处?
几个原因,而不是使用服务器重定向,您应该更好地选择这种方法:
您的应用程序变得独立于服务器软件
并非所有地方都有 Apache(高负载站点通常使用 Nginx 或 Lighttpd),即使您有 Apache,您使用mod_rewrite的能力也取决于服务器的配置。
您网站中所有链接的统一方案
无论您使用什么设备,查看某些新闻的链接总是相同的。它使 URL 的共享和书签变得更加容易。
单点变化
这种方法让您最初为桌面用户创建站点,然后添加移动/平板电脑支持,而无需重写任何现有代码。
您可能也有兴趣阅读关于MVC 上下文中模型层实现和访问控制主题的两篇较早的文章。