Android RESTful веб-приложение с использованием Zend Framework

Я написал веб-приложение, основанное на Zend Framework (версия 1.11.11), и хочу использовать один и тот же внутренний код для кодирования мобильной версии этого приложения (Android). Чтобы добиться этого, я хочуполучить ответ для каждого из действий в контроллерах в XML и JSON - для мобильного приложения.

Но проблема, с которой я сталкиваюсь:

Каждое из действий в моих контроллерах будет возвращать переменную представления, которая затем будет интерпретироваться сценарием представления. Но я хочу, чтобы каждое из действий возвращало массив JSON в случае мобильного приложения и обычную / обычную вещь (просмотр переменных) для веб-приложения на основе браузера.

Может ли кто-нибудь из вас дать мне пример того, как этого можно достичь заloginAction() вUsersController.

URL будет выглядеть так:

http://{servername}/service/login

Чтобы сделать это, я хочу получить некоторое представление и совет о том, как сделать это наиболее эффективным и ПРАВИЛЬНЫМ способом. Я гуглил ответы, но не нашел хороших примеров кода или примеров реализации того, как этого добиться. Я ценю любую помощь и руководство.

Я сделал это так: Иметь API, который вызывается с параметрами, которые будут анализировать вызов, а затем загружать его в контроллер. Но безуспешно в кодировании.

Код, который у меня есть до сих пор:

A UserController с участиемloginAction() (для пользователей, которые входят в систему):

По моему мнению, я должен использовать ту же логику или, скорее, ту же функцию, что и loginAction в UsersController (для веб-приложений и приложений для мобильных устройств):

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() даже для мобильного приложения.

Далее у меня есть класс с именем Service_Api с множеством функций. Ниже приведена функция, которую я сейчас имею, чтобы получить пользователя на основе идентификатора.

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 (скажем, пользовательские значения из db и success / fail для успешной / неудачной регистрации) для мобильного приложения.

Я хочу иметь RESTful URL.

Так что мои URL будут выглядеть так:

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

У меня есть контроллер с именем 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);
}

Но это использование отдельного действия контроллера.

Любая помощь приветствуется.

Благодарю. Abhilash

Ответы на вопрос(1)

но не позволяет перенаправить запрос на хороший контроллер в соответствии с запрошенным форматом (XML, JSON и т. Д.).

Оттуда, как решить, какие действия вызывать в соответствии с запрошенным форматом?

Ajax Context

использованиеAjaxContext в вашем контроллере_init() метод:

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

В результате это перенаправит ваш XML-запрос на то же действие, что и ваш JSON-запрос.

Как сделать, чтобы сказать, какой формат следует использовать? Просто добавь?format=xml или же/format/xml (или JSON) к параметрам URL. Ваш 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_Encoder больше.

Если вы хотите узнать больше о RESTful API, я прочитал очень интересныйppt слайд, написанный Мэтью Вейером О'Финни (в настоящее время Project Lead of ZF), я определенно рекомендовал это.

Еще одна вещь, ваше приложение, кажется, не уважаетТощий контроллер и модель Fat рекомендованный Zend Framework, я полагал, что если вы будете следовать этому принципу, это будет намного понятнее для вас. А также вашloginAction() будет толькополучить сообщение об успехе или неудаче от вашей модели, который будет легко преобразовать в JSON или XML, используя метод, который я описал выше.

RESTful API

Чтобы узнать, является ли запрос запросом GET или запросом POST, используйте эти методы в своих контроллерах:

$this->_getAllParams(); или $ this-> getRequest () -> getParams (); `перехватит все параметры, POST и GET.$this->getRequest()->getPost() извлекает параметры POST$this->getRequest()->getQuery() извлекает параметры GET

И чтобы определить тип запроса, вы можете использовать эти методы:

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

Больше информацииздесь, в руководстве.

 Abhilash Chiganmi27 мар. 2012 г., 22:05
<br/> Спасибо за ответ. Использование помощника ajaxContext действительно помогло. Я устанавливаю контексты как json для необходимых действий, выиграв метод init, и получаю желаемый ответ json. <br/> Теперь у меня есть еще один вызов. Как узнать по URL-адресу, было ли данное действие запросом GET или POST? <br/> Например, для действия входа: URL будет: [ссылка] (локальный: 6600 / ...) <br/> Но в рамках loginAction я проверяю, соответствует ли данный запрос посту, и аутентифицируюсь только в том случае, если запрос является постом. Как этого добиться используя REST URI
 Liyali28 мар. 2012 г., 07:56
Я отредактировал свой ответ.

Ваш ответ на вопрос