使用Zend Framework的Andr​​oid基于REST的Web应用程序 [英] Android RESTful Web application using Zend Framework

查看:229
本文介绍了使用Zend Framework的Andr​​oid基于REST的Web应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了(版本1.11.11)的Web应用程序,它是基于Zend框架,我想用相同的后端code编码这个应用(安卓)的移动版本。要做到这一点,我想为获得每个控制器的XML和JSON 的行动的反应 - 移动为基础的应用程序

I have written a web application which is based on the Zend Framework (Version 1.11.11) and I want to use the SAME backend code for coding the mobile version of this application (Android). To achieve this, I want to get the response for each of the actions in the controllers in XML and JSON - for mobile-based app.

不过,我现在面临的问题是:

But the problem I am facing is:

每个在我的控制器的行动将返回一个视图变量,随后将通过视图脚本PTED跨$ P $。但我想每个操作返回一个JSON数组的情况下一个移动应用程序和普通/平常的事情(查看变量)的基于浏览器的Web应用程序。

Each of the actions in my controllers will return a view variable which will then be interpreted by the view script. But I want each of the actions to return a JSON array in case of a mobile application and the regular/usual thing (view variables) for the browser based web application.

能否有人对你给我的是如何实现的则loginAction() UsersController中为例

Can anyone of you give me an example of how it can be achieved for a loginAction() in UsersController.

该网址如下所示:

的http:// {服务器名称} /服务/登录

要做到这一点,我想就如何做到这一点的最有效和最正确的方式一些见解和建议。我用Google搜索的答案,但我没有找到什么好的code样品或样品执行就如何实现这一目标。我AP preciate任何帮助和指导。

To do this, I want some insight and advice on how to do it in the most efficient and CORRECT way. I googled for answers but I did not find any good code samples or implementation samples on how to achieve this. I appreciate any help and guidance.

就是我所做的是:有被称为与解析会调用参数,然后关闭负载到控制器的API。但不成功的编码了。

The way I have done it is: Have an API which is called with parameters which would parse the call and then off load it to the controller. But unsuccessful in coding it.

在code,我有到现在为止:

The code which I have until now:

A UserController的则loginAction()(用于用户登录):

A UserController with loginAction() (for users logging in):

据我,我应该使用相同的逻辑,或者说同样的功能在UsersController中的则loginAction(基于Web和移动应用为主),如下所示:

According to me, I should be using the same logic or rather the same function as the loginAction in UsersController (for web-based and mobile-based app) as follows:

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);
}

}

所以我想用上面的则loginAction()即使对于移动应用程序。

So I want to use the above loginAction() even for mobile based application.

接下来,我有一类叫做Service_Api具有多种功​​能。下面是一个函数,我现在已经基于ID获取用户。

Next, I have a class called Service_Api with a variety of functions. Below is a function I have now to get user based on 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);
}

同样地,我想有一个在loginAction的登录。如何将则loginAction()看我怎么会只得到JSON可用的参数(比如从数据库和成功的用户价值/失败的登录成功/失败)的移动应用程序。

Similarly I want to have a loginAction for logging in. How will the loginAction() look and how will I get only JSON vlaues (say user values from db and success/failure for login success/failure) for mobile application.

我想有一个RESTful URL。

I want to have a RESTful URL.

所以,我的网址看起来像:

So my URLs would look like:

http://{servername}/service/login
http://{servername}/service/groups/list etc.

我有一个名为ServiceController的使用则loginAction控制器如下:

I have a controller called ServiceController with loginAction as follows:

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);
}

但是,这是使用单独的控制器动作。

But this is using a separate controller action.

任何帮助是AP preciated。

Any help is appreciated.

感谢。 Abhilash

Thanks. Abhilash

推荐答案

关闭布局适用于JSON,但它不会让你按照要求的格式(XML,JSON等,将请求重定向到好的控制器)。

Disabling layouts works for JSON, but it doesn't allow you to redirect the request to the good controller according to the format requested (XML, JSON, etc.).

从那里,如何决定什么样的行动来按照要求的格式打电话?

From there, how to decides what actions to call according to the requested format?

使用<一个href="http://framework.zend.com/manual/en/zend.controller.actionhelpers.html#zend.controller.actionhelpers.contextswitch"相对=nofollow> AjaxContext 在控制器 _init()方法:

$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('login', 'json')
            ->addActionContext('login', 'xml')
            ->initContext();

这将对影响到你的XML请求重定向到同一个动作,你的JSON请求。

This will have for effect to redirect your XML request to the same action that your JSON request.

如何让知道应该用哪种格式?的只需添加?格式= XML /格式/ XML (或JSON)的URL参数。您网址宁愿是这样的:的http:// {服务器名称} /服务/登录/格式/ JSON

How to make tell which format should be used? Simply add ?format=xml or /format/xml (or json) to the URL parameters. You URL would rather look like this: http://{servername}/service/login/format/json.

从你的行动,如何知道哪些格式已要求?的你没有什么关系,AjaxContext采取一切都已经照顾。

From your action, how to know which format has been requested? You don't have anything to do, AjaxContext takes care of everything already.

如果一个JSON请求:

JSON。 JSON上下文设置'Content-Type'响应头   应用/ JSON,设置视图脚本后缀为'json.phtml。

JSON. The JSON context sets the 'Content-Type' response header to 'application/json', and the view script suffix to 'json.phtml'.

在默认情况下,但是,没有视图脚本是必需的。它只会   系列化所有的视图变量,立即发出JSON响应。

By default, however, no view script is required. It will simply serialize all view variables, and emit the JSON response immediately.

如果一个XML请求:

修改视图后缀为'xml.phtml(或者,如果使用备用   视图后缀,'XML。[你的后缀]')。

Change the view suffix to 'xml.phtml' (or, if you use an alternate view suffix, 'xml.[your suffix]').

请注意,使用AjaxContext,响应头是自动将设置根据响应的格式要求。

Note that using AjaxContext, response headers are automatically going to be set according to the response format requested.

意识到这一点,你不应该需要使用 Zend_Json_En codeR 了。

Aware of that, you shouldn't need to use Zend_Json_Encoder anymore.

如果您想了解更多关于REST的API,我读过一个非常有趣的写的马修纬二路O'Phinney (ZF目前项目主管)PPT幻灯片,我绝对推荐它。

If you want to know more about RESTful API, I've read a very interesting ppt slide written by Matthew Weier O'Phinney (currently Project Lead of ZF), I definitely recommended it.

还有一件事,你的应用程序似乎并不尊重的瘦控制器和高脂模型会建议Zend框架,我认为,如果你按照此原则,这会使事情方式更加清晰的给你。而且,你的则loginAction()只会获得了成功或失败的消息从模型,这将很容易使用转换为JSON或XML我上面的方法。

One more thing, your application doesn't seem to respect the Skinny controller and Fat model convention recommended by Zend Framework, I believed that if you're following this principle it would make things way more clearer to you. And also, your loginAction() would only get a success or failure message from your model, which would be easy to convert to JSON or XML using the method I described above.

为了知道是否请求是GET请求或POST请求,使用这些方法在你的控制器:

In order to know if the request is a GET request or a POST request, use these methods in your controllers:

  • $这个 - &GT; _getAllParams(); 或$这个 - >调用getRequest() - > getParams()方法;`会抓住所有的参数,POST和GET
  • $这个 - &GT;调用getRequest() - &GT;的getPost()检索POST参数
  • $这个 - &GT;调用getRequest() - &GT; getQuery()检索GET参数
  • $this->_getAllParams(); or $this->getRequest()->getParams();` will catch all parameters, POST and GET.
  • $this->getRequest()->getPost() retrieves POST parameters.
  • $this->getRequest()->getQuery() retrieves GET parameters.

和确定请求类型,您可以使用这些方法:

And to determine the request type, you can uses these methods:

  • isGet()
  • isPost()
  • isPut()
  • isDelete()
  • isGet()
  • isPost()
  • isPut()
  • isDelete()

更多信息<一个href="http://framework.zend.com/manual/en/zend.controller.request.html#zend.controller.request.http.method"相对=nofollow>在这里的手工。

这篇关于使用Zend Framework的Andr​​oid基于REST的Web应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆