Abh*_*nmi 5 php rest android json zend-framework
我编写了一个基于Zend Framework(版本1.11.11)的Web应用程序,我想使用SAME后端代码来编写此应用程序的移动版本(Android).为实现这一目标,我希望获得XML和JSON控制器中每个操作的响应 - 基于移动的应用程序.
但我面临的问题是:
我的控制器中的每个操作都将返回一个视图变量,然后由视图脚本解释.但是我希望每个动作在移动应用程序的情况下返回JSON数组,并且为基于浏览器的Web应用程序返回常规/常规事物(视图变量).
你们谁能给我如何能为实现一个例子loginAction()在UsersController.
URL看起来像:
http://{servername}/service/login
要做到这一点,我需要一些有关如何以最有效和最正确的方式做到这一点的见解和建议.我搜索了答案,但我没有找到任何关于如何实现这一目标的良好代码示例或实现示例.我感谢任何帮助和指导.
我这样做的方法是:使用参数调用API,该参数将解析调用然后将其卸载到控制器.但编码不成功.
我到目前为止的代码:
一个UserController与loginAction()(用户登录):
据我所知,我应该使用与UsersController中的loginAction相同的逻辑或相同的功能(对于基于Web和基于移动的应用程序),如下所示:
public function loginAction()
{
// Already logged in
if( Engine_Api::_()->user()->getViewer()->getIdentity() ) {
$this->view->status = false;
$this->view->error = Zend_Registry::get('Zend_Translate')->_('You are already signed in.');
if( null === $this->_helper->contextSwitch->getCurrentContext() ) {
$this->_helper->redirector->gotoRoute(array(), 'default', true);
}
return;
}
// Make form
$this->view->form = $form = new User_Form_Login();
$form->setAction($this->view->url(array('return_url' => null)));
$form->populate(array(
'return_url' => $this->_getParam('return_url'),
));
// Render
$this->_helper->content
//->setNoRender()
->setEnabled()
;
// Not a post
if( !$this->getRequest()->isPost() ) {
$this->view->status = false;
$this->view->error = Zend_Registry::get('Zend_Translate')->_('No action taken');
return;
}
// Form not valid
if( !$form->isValid($this->getRequest()->getPost()) ) {
$this->view->status = false;
$this->view->error = Zend_Registry::get('Zend_Translate')->_('Invalid data');
return;
}
// Check login creds
extract($form->getValues()); // $email, $password, $remember
$user_table = Engine_Api::_()->getDbtable('users', 'user');
$user_select = $user_table->select()
->where('email = ?', $email); // If post exists
$user = $user_table->fetchRow($user_select);
// Get ip address
$db = Engine_Db_Table::getDefaultAdapter();
$ipObj = new Engine_IP();
$ipExpr = new Zend_Db_Expr($db->quoteInto('UNHEX(?)', bin2hex($ipObj->toBinary())));
// Check if user exists
if( empty($user) ) {
$this->view->status = false;
$this->view->error = Zend_Registry::get('Zend_Translate')->_('No record of a member with that email was found.');
$form->addError(Zend_Registry::get('Zend_Translate')->_('No record of a member with that email was found.'));
// Code
return;
}
// Check if user is verified and enabled
if( !$user->enabled ) {
if( !$user->verified ) {
// Code here.
// End Version 3 authentication
} else {
$form->addError('There appears to be a problem logging in. Please reset your password with the Forgot Password link.');
// Code
return;
}
} else { // Normal authentication
$authResult = Engine_Api::_()->user()->authenticate($email, $password);
$authCode = $authResult->getCode();
Engine_Api::_()->user()->setViewer();
if( $authCode != Zend_Auth_Result::SUCCESS ) {
$this->view->status = false;
$this->view->error = Zend_Registry::get('Zend_Translate')->_('Invalid credentials');
$form->addError(Zend_Registry::get('Zend_Translate')->_('Invalid credentials supplied'));
//Code
return;
}
}
// -- Success! --
// Register login
$loginTable = Engine_Api::_()->getDbtable('logins', 'user');
$loginTable->insert(array(
'user_id' => $user->getIdentity(),
'email' => $email,
'ip' => $ipExpr,
'timestamp' => new Zend_Db_Expr('NOW()'),
'state' => 'success',
'active' => true,
));
$_SESSION['login_id'] = $login_id = $loginTable->getAdapter()->lastInsertId();
$_SESSION['user_id'] = $user->getIdentity();
// Some code.
// Do redirection only if normal context
if( null === $this->_helper->contextSwitch->getCurrentContext() ) {
// Redirect by form
$uri = $form->getValue('return_url');
if( $uri ) {
if( substr($uri, 0, 3) == '64-' ) {
$uri = base64_decode(substr($uri, 3));
}
if($viewer->is_vendor) {
return $this->_helper->redirector->gotoRoute(array('module' => 'user' ,'controller' => 'vendors', 'action' => 'mydeals'), 'vendor_mydeals', true);
} else {
return $this->_helper->redirector->gotoRoute(array('action' => 'index'), 'user_searchquery', true);
}
//return $this->_redirect($uri, array('prependBase' => false));
}
return $this->_helper->redirector->gotoRoute(array('action' => 'index'), 'user_searchquery', true);
}
Run Code Online (Sandbox Code Playgroud)
}
所以我想使用上面loginAction()甚至基于移动的应用程序.
接下来,我有一个名为Service_Api的类,它具有各种功能.下面是我现在根据id获取用户的函数.
private function getUser(array $params)
{
$userData = array();
$usersTable = Engine_Api::_()->getDbtable('users', 'user');
$select = $usersTable->select()->where('user_id = ?', $params['user']);
$user = $usersTable->findOne($params['user']);
if($user) {
$userData = $user->exportToArray();
}
return Zend_Json_Encoder::encode($userData);
}
Run Code Online (Sandbox Code Playgroud)
同样地,我希望有一个loginAction用于登录.loginAction()外观如何,我将如何获得移动应用程序的JSON值(例如来自db的用户值以及登录成功/失败的成功/失败).
我想要一个RESTful URL.
所以我的网址看起来像:
http://{servername}/service/login
http://{servername}/service/groups/list etc.
Run Code Online (Sandbox Code Playgroud)
我有一个名为ServiceController的控制器,带有loginAction,如下所示:
public function loginAction()
{
$this->_helper->viewRenderer->setNoRender();
$this->_helper->layout->disableLayout(true);
/*
* Fetch Parameters and Parameter Keys
* We don't need the controller or action!
*/
$params = $this->_getAllParams();
unset($params['controller']);
unset($params['action']);
unset($params['module']);
unset($params['rewrite']);
$paramKeys = array_keys($params);
/*
* Whitelist filter the Parameters
*/
Zend_Loader::loadClass('Zend_Filter_Input');
$filterParams = new Zend_Filter_Input($params);
/*
* Build a request array, with method name to call
* on handler class for REST server indexed with
* 'method' key.
*
* Method name is constructed based on valid parameters.
*/
$paramKeysUc = array();
foreach($paramKeys as $key)
{
$paramKeysUc[] = ucfirst($key);
}
$methodName = 'getBy' . implode('', $paramKeysUc);
$request = array(
'method'=>$methodName
);
/*
* Filter parameters as needed and add them all to the
* $request array if valid.
*/
foreach($paramKeys as $key)
{
switch($key)
{
case'tag':
$request[$key] = $filterParams->testAlnum($key);
break;
default:
$request[$key] = $params[$key];
}
if(!$request[$key])
{
// need better handling of filter errors for a real webservice…
throw new Exception($request[$key] . ' contained invalid data');
}
}
/*
* Setup Zend_Rest_Server
*/
require_once 'Zend/Rest/Server.php';
$server = new Zend_Rest_Server;
$server->setClass('Service_API');
echo $server->handle($request);
}
Run Code Online (Sandbox Code Playgroud)
但这是使用单独的控制器操作.
任何帮助表示赞赏.
谢谢.Abhilash
禁用布局适用于JSON,但它不允许您根据请求的格式(XML,JSON等)将请求重定向到良好的控制器.
从那里,如何根据请求的格式决定要调用的操作?
在控制器方法中使用AjaxContext_init():
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('login', 'json')
->addActionContext('login', 'xml')
->initContext();
Run Code Online (Sandbox Code Playgroud)
这将使您的XML请求重定向到与JSON请求相同的操作.
如何判断应该使用哪种格式?只需添加?format=xml或/format/xml(或json)到URL参数.你的网址看起来像这样:http://{servername}/service/login/format/json.
从您的操作,如何知道请求的格式?你没有任何事可做,AjaxContext已经完成了所有工作.
如果是JSON请求:
JSON.JSON上下文将"Content-Type"响应头设置为"application/json",将视图脚本后缀设置为"json.phtml".
但是,默认情况下,不需要查看脚本.它将简单地序列化所有视图变量,并立即发出JSON响应.
如果是XML请求:
将视图后缀更改为"xml.phtml"(或者,如果使用备用视图后缀,则为"xml.[your suffix]").
请注意,使用AjaxContext时,将根据请求的响应格式自动设置响应头.
意识到这一点,你不应该再使用Zend_Json_Encoder了.
如果你想了解更多有关RESTful API的信息,我已经阅读了Matthew Weier O'Phinney(现为ZF项目负责人)撰写的一篇非常有趣的ppt幻灯片,我绝对推荐它.
还有一件事,你的应用程序似乎不尊重Zend Framework推荐的Skinny控制器和Fat模型约定,我相信如果你遵循这个原则,它会让事情变得更加清晰.而且,您loginAction()只能从模型中获得成功或失败消息,这很容易使用上述方法转换为JSON或XML.
要知道请求是GET请求还是POST请求,请在控制器中使用以下方法:
$this->_getAllParams(); 或$ this-> getRequest() - > getParams();`将捕获所有参数,POST和GET.$this->getRequest()->getPost() 检索POST参数.$this->getRequest()->getQuery() 检索GET参数.要确定请求类型,您可以使用以下方法:
isGet()isPost()isPut()isDelete()手册中有更多信息.