Php 使用Zend框架的Android RESTful Web应用程序

Php 使用Zend框架的Android RESTful Web应用程序,php,android,json,zend-framework,rest,Php,Android,Json,Zend Framework,Rest,我已经编写了一个基于Zend框架(版本1.11.11)的web应用程序,我希望使用相同的后端代码来编码该应用程序的移动版本(Android)。为了实现这一点,我想以XML和JSON的形式获取控制器中每个动作的响应 但我面临的问题是: 我的控制器中的每个操作都将返回一个视图变量,然后该变量将由视图脚本进行解释。但是对于移动应用程序,我希望每个操作都返回一个JSON数组,对于基于浏览器的web应用程序,返回常规/常用的内容(视图变量) 你们谁能给我举个例子,说明如何在userscocontrolle

我已经编写了一个基于Zend框架(版本1.11.11)的web应用程序,我希望使用相同的后端代码来编码该应用程序的移动版本(Android)。为了实现这一点,我想以XML和JSON的形式获取控制器中每个动作的响应

但我面临的问题是:

我的控制器中的每个操作都将返回一个视图变量,然后该变量将由视图脚本进行解释。但是对于移动应用程序,我希望每个操作都返回一个JSON数组,对于基于浏览器的web应用程序,返回常规/常用的内容(视图变量)

你们谁能给我举个例子,说明如何在
userscocontroller
中实现
loginAction()

URL看起来像:

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

要做到这一点,我需要一些关于如何以最有效和正确的方式进行的见解和建议。我在谷歌上搜索答案,但没有找到任何关于如何实现这一点的好代码示例或实现示例。我感谢任何帮助和指导

我这样做的方式是:使用参数调用一个API,该参数将解析调用,然后将其卸载到控制器。但是编码失败了

到目前为止,我拥有的代码:

带有
loginAction()
(用于登录的用户)的
UserController

根据我的说法,我应该使用与UsersController(用于基于web和基于移动的应用程序)中的loginAction相同的逻辑或功能,如下所示:

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

因此,我想使用上面的
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);
}
同样,我想有一个登录的登录。移动应用程序的
loginAction()
外观如何,以及如何仅获取JSON vlaues(比如来自db的用户值和登录成功/失败的成功/失败)

我想要一个RESTful URL

所以我的URL看起来像:

http://{servername}/service/login
http://{servername}/service/groups/list etc.
我有一个名为ServiceController的控制器,其登录操作如下:

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);
}
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);
}
但这是使用单独的控制器操作

感谢您的帮助

谢谢。
Abhilash

禁用布局对JSON有效,但它不允许您根据请求的格式(XML、JSON等)将请求重定向到良好的控制器

然后,如何根据请求的格式决定调用哪些操作

Ajax上下文 在控制器中使用
\u init()
方法:

$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('login', 'json')
            ->addActionContext('login', 'xml')
            ->initContext();
这将有效地将XML请求重定向到与JSON请求相同的操作

如何判断应该使用哪种格式?只需向URL参数添加
?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.[您的后缀]”)

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

意识到这一点,您不应该再使用
Zend_Json_编码器了

如果您想了解更多关于RESTful API的信息,我已经阅读了一篇非常有趣的文章(目前是ZF的项目负责人),我绝对推荐它

还有一件事,您的应用程序似乎不尊重Zend Framework推荐的方法,我相信如果您遵循这一原则,它会让您更清楚地了解情况。而且,您的
loginAction()
只会从您的模型中获得一条成功或失败消息,使用上面描述的方法很容易将其转换为JSON或XML

RESTful API 为了知道请求是GET请求还是POST请求,请在控制器中使用以下方法:

  • $this->\u getAllParams()或$this->getRequest()->getParams();`将捕获所有参数,发布并获取
  • $this->getRequest()->getPost()
    检索POST参数
  • $this->getRequest()->getQuery()
    检索GET参数
要确定请求类型,可以使用以下方法:

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

更多信息。


感谢您的回复。使用ajaxContext帮助器确实有帮助。我通过init方法将所需操作的上下文设置为json,并获得所需的json响应
现在我面临另一个挑战。如何从URL知道给定的操作是GET还是POST请求
例如,对于登录操作:URL将为:[link]()
但在登录操作中,我检查给定的请求是否为post,并且仅当请求为post时进行身份验证。如何使用RESTURI实现它