我在 Zend Framework 中创建了一个巨大的网站(前端和管理端),现在我想在 ZF 中做同样的项目,但用于移动设备。
我肯定会使用 HTML5 和 jQuery 移动版,但在继续并开始我的移动网站开发之前,我想问专家什么是好的、简单、高效和优化的方法?
我在 Zend Framework 中创建了一个巨大的网站(前端和管理端),现在我想在 ZF 中做同样的项目,但用于移动设备。
我肯定会使用 HTML5 和 jQuery 移动版,但在继续并开始我的移动网站开发之前,我想问专家什么是好的、简单、高效和优化的方法?
您可能需要查看 ContextSwitch View Helper - 它允许您根据“格式”参数切换视图脚本。您可以使用它(或扩展它)将视图切换到更适合移动设备的模板。
具体看一下JSON Context,它禁用了布局——如果检测到移动请求,可以使用相同的技术来切换布局。
当然,如果你可以通过一些 CSS 媒体查询来完成你需要的事情,那肯定是要走的路。
您可能还会发现Zend_Http_UserAgent
检测移动设备的可用功能很有用。同样,类似于媒体查询的可能性,但仍然可能有用。
但底线是不需要“转换”网站,有很多工具可以让桌面和移动用户都可以访问同一个网站。
点击 我,阅读我,我相信你会喜欢我
正如 Fawad Ghafoor 的回答者一样从互联网上消失了(仍然可以在网络档案中找到https://web.archive.org/web/20110225213957/http://www.web-punk.com/2010/03/zend-框架-应用程序-for-iphone-blackberry-co/)
我不知道这样行不行,但我会在这里复制并格式化网站的内容。
适用于 iPhone、BlackBerry 和 Co 的 Zend Framework 应用程序
在过去的几年里,移动设备变得非常重要。本教程将向您展示如何修改您的网站并使其为 iPhone、BlackBerry 等移动设备做好准备。
在我们开始之前:与本博客的所有其他帖子一样,我希望您是一名软件工程师,并使用 MVC(模型/视图/控制器)模式实现您的 Web 应用程序,并且可能还使用 Zend_Layout。
1. 我们需要什么
基本上,在为移动设备准备好 Web 应用程序时,您唯一需要做的就是 a) 检测用户是使用移动设备还是非移动设备浏览您的网站,以及 b) 根据结果更改 MVC 中的 V一)。
但是,我发现稍微扩展这种方法非常有用。除了用移动设备的视图替换视图之外,我们还将做两件事:我们还将替换用于 Web 应用程序的布局 (Zend_Layout),我们将使用不同的翻译文件 (Zend_Translation)。很明显为什么替换布局很有用,但为什么我们需要使用不同的翻译文件呢?好吧,实际上我们不必这样做,但我发现如果你有大屏幕的翻译文件(你可能想要使用 looong 文本描述)和移动设备的翻译文件(有清晰的描述,错误消息、标签等)
正如我们稍后将看到的,Zend 框架的上下文切换(http://framework.zend.com/manual/en/zend.controller.actionhelpers.html)是(几乎)我们所需要的…… ContextSwitch 是一个动作助手,它“旨在促进根据请求返回不同的响应格式”。这个动作助手带有两种不同的即用型上下文:JSON 和 XML。对于我们的示例,我们将创建一个名为“mobile”的附加上下文。
控制流模式丢失了......在某些时候它在这里:http ://www.web-punk.com/wp-content/uploads/2010/03/mobile_wf-300x94.png
基本上,我们的控制流必须按照图“控制流”中的描述工作(点击图放大)。如果用户浏览http://mobile.example.com/controller/action,我们直接设置正确的上下文“mobile”。如果用户浏览http://www.example.com/controller/action,我们会检查他是否使用移动设备。如果他使用的是移动设备,我们会询问用户他是想使用我们的网络应用程序的移动版还是桌面版。由于我们不想在用户每次请求页面时询问他是否要使用移动版本,我们会将她/他的决定存储在会话变量中(并且只会再次询问她,如果她不活动几分钟)。
作为此工作流程的示例,请查看http://www.qulpa.com
2. 创建我们的移动插件 为了实现我们的目标,我们将实现一个小插件。在实现这个插件之前,我们需要一个函数来检查当前用户是否在使用移动设备。您可以使用 WURFL 之类的智能解决方案来执行此操作。但是,对于我们的示例,我们将使用一个简单的函数,如果用户正在使用移动设备,则返回 true,否则返回 false。如果你用谷歌搜索它,你会发现几十个可以完成这项工作的函数。我将使用我在 Brain Handles 找到的一个函数。
现在,让我们创建我们的插件。在您的 \plugins 文件夹中,创建一个名为 Mobile.php 的文件,然后复制并粘贴以下源代码:
<?php
class Plugin_Mobile extends Zend_Controller_Plugin_Abstract
{
// instead of defining all these parameters here,
// you could also put them into your application.ini
// if user is inactive for X minutes and surfs to
// www.example.com, we'll ask him again if he wants
// to user mobile or desktop version
private $ask_again_after_x_minutes = 10;
// used to test your mobile layout. Set this
// to 1 to emulate a mobile device
private $test_mobile = 0;
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
// did we already ask the user?
if (isset($_SESSION['mobileasked'])) {
// is mobile session still valid?
if (time() < $_SESSION['mobileasked']) {
// update session
$_SESSION['mobileasked'] = time() + $this->ask_again_after_x_minutes * 60;
// continue with requested page
return $request;
}
}
// otherwise, check if user is using a mobile device
// or if we are in test mode.
if ($this->checkmobile() || ($this->test_mobile == 1)) {
// if requested page != MOBILE.example.com
if (!(Zend_Registry::isRegistered('directmobile') && Zend_Registry::get('directmobile') == '1')) {
// set mobile session
$_SESSION['mobileasked'] = time() + $this->ask_again_after_x_minutes * 60;
// ask user if he wants to use mobile or desktop version
$request->setControllerName('index')
->setActionName('askmobile')
->setParam('format', 'mobile')
->setParams($request->getParams())
->setDispatched(false);
}
}
return $request;
}
/**
* This function returns true if user is using a mobile device. False otherwise.
* (c) by http://www.brainhandles.com/techno-thoughts/detecting-mobile-browsers
*/
private function checkmobile(){
if(isset($_SERVER["HTTP_X_WAP_PROFILE"])) return true;
if(preg_match("/wap\.|\.wap/i",$_SERVER["HTTP_ACCEPT"])) return true;
if(isset($_SERVER["HTTP_USER_AGENT"])){
// Quick Array to kill out matches in the user agent
// that might cause false positives
$badmatches = array("OfficeLiveConnector","MSIE\ 8\.0","OptimizedIE8","MSN\ Optimized","Creative\ AutoUpdate","Swapper");
foreach($badmatches as $badstring){
if(preg_match("/".$badstring."/i",$_SERVER["HTTP_USER_AGENT"])) return false;
}
// Now we'll go for positive matches
$uamatches = array("midp", "j2me", "avantg", "docomo", "novarra", "palmos", "palmsource", "240x320", "opwv", "chtml", "pda", "windows\ ce", "mmp\/", "blackberry", "mib\/", "symbian", "wireless", "nokia", "hand", "mobi", "phone", "cdm", "up\.b", "audio", "SIE\-", "SEC\-", "samsung", "HTC", "mot\-", "mitsu", "sagem", "sony", "alcatel", "lg", "erics", "vx", "NEC", "philips", "mmm", "xx", "panasonic", "sharp", "wap", "sch", "rover", "pocket", "benq", "java", "pt", "pg", "vox", "amoi", "bird", "compal", "kg", "voda", "sany", "kdd", "dbt", "sendo", "sgh", "gradi", "jb", "\d\d\di", "moto","webos");
foreach($uamatches as $uastring){
if(preg_match("/".$uastring."/i",$_SERVER["HTTP_USER_AGENT"])) return true;
}
}
return false;
}
确保你注册了这个插件!为此,您需要在引导程序中执行以下操作:
// init PluginLoader. Adopt folder to your application...
$loader = new Zend_Loader_PluginLoader(array(
'Plugin' => APPLICATION_PATH . '/application/controllers/plugins',
));
// define plugin names and classes
$pluginList = array(
'plugin1' => $loader->load('Plugin1'),
'plugin2' => $loader->load('Plugin2'),
// [...]
'mobile' => $loader->load('Mobile'),
);
// get your front controller
$frontController = Zend_Controller_Front::getInstance();
// Register your plugins
foreach ($pluginList as $pluginClass) {
$frontController->registerPlugin(new $pluginClass());
}
3.上下文检测
这就是您在移动插件中所要做的一切。接下来我们要做的是确保我们检测到正确的上下文。我们将在我们的引导程序中执行此操作。打开你的 bootstrap.php 并在里面放这样的东西:
// set correct context
$domains = explode('.', $_SERVER['HTTP_HOST']);
if ($domains[0] == 'mobile' || $frontController->getParam('format') == 'mobile') {
if ($domains[0] == 'mobile') {
// if set, user will be redirected directly to requested page
Zend_Registry::set('directmobile', '1');
}
Zend_Registry::set('context', '\mobile');
} else {
Zend_Registry::set('context', '');
}
4.询问用户
由于我们想询问用户是否想使用我们应用程序的移动版或桌面版,我们将在索引控制器中创建一个简单的操作。我们将在我们的移动插件中将用户重定向到这个控制器/动作(见第 2 章)。
打开您的 IndexController.php 并创建一个 askmobileAction:
public function askmobileAction()
{
// nothing to do here...
}
这个动作基本上是……好吧,没什么;-)。现在,让我们看一下 askmobile 视图。在您的视图文件夹中,可能是 \views\scripts\index,创建一个名为 askmobile.mobile.view 的文件,并在其中放入如下内容:
How do you want to use this application?<br/>
<a href="<?= 'http://mobile.fopp.de' . $_SERVER["REQUEST_URI"]?>">MOBILE VERSION</a>
<br></br>
<a href="<?= 'http://dev.fopp.de' . $_SERVER["REQUEST_URI"] ?>">DESKTOP VERSION</a>
这并不复杂,不是吗?如您所见,此视图的名称与所有其他视图的名称不同。正如我们将在本教程后面看到的那样,如果我们在上下文 MOBILE 中,ContextSwitch 将确保调用视图 name.MOBILE.phtlm 而不是 name.phtml。
5.您的移动布局
下一步是为我们的移动版本创建一个独特的布局。这是否必要取决于您的应用程序。但是,在大多数情况下,对应用程序的桌面版本进行复杂布局和对移动版本进行轻量级布局是有意义的。首先,在您的\layouts 文件夹中创建一个名为\mobile 的目录(完整路径可能类似于\application\layouts\mobile,但这取决于您的应用程序)。在此文件夹中创建一个名为 layout.phtml 的文件,并在其中放入以下内容:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<?php echo $this->headTitle() . "\n" ?>
<?php echo $this->headLink() . "\n" ?>
</head>
<body>
<div id="header">This is your header</div>
<div id="content"><?= $this->layout()->content ?></div>
<div id="footer">This is your footer</div>
</body>
</html>
这是我们非常简单的移动环境布局。即使您为移动设备创建布局,您的布局也很可能会更加复杂,因为您可能会包含 CSS 文件等。
6. 把所有东西放在一起
我们已经快完成了。最后一步是在控制器中使用上下文。在本教程中,我们将使用 IndexController 的 init() 方法,您可以将其用作应用程序中所有其他控制器的模板。实际上,与其将这段代码复制到所有控制器,我更喜欢一种更智能的方式,它利用 OO 设计范例(例如,创建一个扩展 Zend_Controller_Action 并从 application.ini 获取所有必要参数的 MyMobileController 类),但是,这将完成本教程的工作。
打开您的 IndexController.php 文件并将以下源代码复制并粘贴到其中: /** * 初始化控制器和上下文 * * @return void */ public function init() { parent::init();
// are we in the mobile context?
if (Zend_Registry::get('context') == '\mobile' || $this->getRequest()->getParam('format') == 'mobile')
{
// Mobile format context
$mobileConfig =
array(
'mobile' => array(
'suffix' => 'mobile',
'headers' => array(
'Content-type' => 'text/html; charset=utf-8')),
);
// Init the action helper
$contextSwitch = $this->_helper->contextSwitch();
// Add new context
$contextSwitch->setContexts($mobileConfig);
// This is where you have to define
// which actions are available in the mobile context
// ADOPT THIS TO YOUR NEEDS!
$contextSwitch->addActionContext('index', 'mobile');
$contextSwitch->addActionContext('askmobile', 'mobile');
// enable layout but set different path to layout file
$contextSwitch->setAutoDisableLayout(false);
$this->getHelper('layout')->setLayoutPath(APPLICATION_PATH . '/application/layouts/mobile');
// Initializes action helper
$contextSwitch->initContext('mobile');
}
}
7. 创建您的移动视图
最后,您必须创建移动视图。对于移动上下文中可用的每个视图(如控制器的 init() 方法中定义的那样),您必须创建一个移动视图。因此,如果您有一个名为 myaction 的操作,您将需要一个用于桌面版的 myaction.phtml 和一个用于移动版应用程序的 myaction.mobile.phtml。
恭喜!您刚刚创建了您的第一个移动 Web 应用程序;-)
附录:移动设备的翻译文件
正如第 1 章所承诺的,我们将为我们的移动设备/移动上下文使用不同的翻译文件。这非常方便,因为您可能想要更短的标签、描述文本、错误消息等。当然,如果你不需要这样的东西,你可以直接跳过这个附录。
基本上,您需要做的就是检查应用程序在哪个上下文中并加载相应的翻译文件。
假设您将翻译文件存储在 \application\translations\ 文件夹中,并且您的应用程序有英语和法语版本。除了你的 fr.php 和 en.php 文件,你应该在你的翻译文件夹中为每种语言提供一个移动版本:mobile_en.php 和 mobile_fr.php。以下代码片段将加载相应的翻译文件:
// Init Zend_Locale with corresponding language (assuming that $lang is set to 'en' or 'fr')
// and store the Zend_Locale object in the registry
Zend_Registry::set('Zend_Locale', new Zend_Locale($lang));
// Load translation file and store it in the registry
$langFile = APPLICATION_PATH . '/application/translations/';
if (Zend_Registry::get('context') == '\mobile') {
// if context = mobile, get translation file for mobile device
$langFile.= 'mobile_' . Zend_Registry::get('Zend_Locale')->getLanguage() . '.php';
} else {
$langFile.= Zend_Registry::get('Zend_Locale')->getLanguage() . '.php';
}
Zend_Registry::set(
'Zend_Translate', new Zend_Translate('array', $langFile)
);