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

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

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

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

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

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

http://{servername}/service/login

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

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

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

Пользователь UserController с loginAction() (для входа пользователей):

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

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

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

Поэтому мои 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); } не 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); } не 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); } не 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); } не 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

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

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

    Это приведет к перенаправлению вашего 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. [Ваш суффикс]»).

    Обратите внимание, что с использованием AjaxContext заголовки ответов автоматически будут настроены в соответствии с запросом формата ответа.

    Осознавая это, вам больше не нужно использовать Zend_Json_Encoder .

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

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

    API RESTful

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

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

    Чтобы определить тип запроса, вы можете использовать следующие методы:

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

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