2013-05-13 3 views
1

젠드 프레임 워크 1.12.3을 사용하여 API를 개발 중입니다. 이후,Zend Rest Route - 계층 적 URL을 만드는 방법?

나는이 방법을 사용하는 고려 중이 야 : 계층 URL을 가지고 나는 Zend_Rest_Route를 사용하고 있지만, 내가 좋아하는 것 특정 교수에게 특정 과목을 할당해야하며이 스키마가 깔끔하게 해결할 수 있다고 생각합니다.

그러나 계층 적 URL을 얻는 데 어려움을 겪고 있습니다. 의 설정 .ini 파일에 체인으로

  1. Zend_Controller_Router_Route를하지만 항상 같은 행동을 지적 http://api.example.com/professors/:professorId/subjects에 액세스 할 때, 즉 (지정할 수 컨트롤러와 액션 모두 이후 : 난 이미 시도했습니다 호출 메소드가 무엇이든 - POST, PUT, GET, DELETE - 항상 config .ini 파일에 지정된 작업을 가리 킵니다. 예를 들어, 설정 파일에서 getAction을 지정했다면, 체인을 사용하여 내가 사용한 메소드가 무엇이든 항상 getAction을 호출합니다. 현재 POST 호출이있을 때 실제로 postAction()을 호출합니다 (PUT, GET, DELETE, PATCH, HEAD 및 OPTIONS에 대해 유사하게 발생 함). 내 컨트롤러 파일은 다음과 같다 :

    class V1_ProfessorsController extends REST_Controller 
    { 
         public function optionsAction() 
         { 
           // code goes here 
         } 
    
         public function headAction() 
         { 
           // code goes here 
         } 
    
         public function indexAction() 
         { 
           // code goes here - list of resources 
         } 
    
         public function getAction() 
         { 
           // code goes here 
         } 
    
         public function postAction() 
         { 
           // code goes here 
         } 
    
         public function putAction() 
         { 
           // code goes here 
         } 
    
         public function patchAction() 
         { 
           // code goes here 
         } 
    
         public function deleteAction() 
         { 
           // code goes here 
         } 
    
    } 
    
  2. 가 Zend_Rest_Route 하위 클래스와 here을 지적 경기() 함수를 오버라이드 (override). 문제는 http://api.example.com/professors/:professorId/subjects을 호출 할 때 작동하지만, 여전히 http://api.example.com/professors을 호출 할 때 사용되는 것과 동일한 ProfessorsController를 사용한다는 것입니다. 이 문제에 대해서는 잘 모르겠지만 자체 컨트롤러 (예 : ProfessorsSubjectsController)를 사용하는 것이 가장 좋을 것이라고 생각합니다.

또한 질문이 있습니다. 계층 적 경로는 어떻게 작동해야합니까? 다른 리소스/하위 리소스에 대해 서로 다른 컨트롤러를 갖는 것이 더 낫습니까? 예 : http://api.example.com/professors/:professorId의 ProfessorsController와 http://api.example.com/professors/:professorId/subjects/:subjectId의 ProfessorsSubjectsController가 있습니까?

+2

이것에 대한 답변을 찾는 과정이 있습니까? 똑같은 문제로 고뇌. – Gabriel

+0

@Gabriel 불행히도, 아직 없습니다. API의 다른 부분을 개발 중이므로 계층 구조 URL을 마지막으로 남겨 둘 것이라고 생각했습니다. 해결책을 찾으면 여기에 게시하겠습니다. 네가 그렇게한다면 나는 그것을 고맙게 생각한다. – Daniel

+0

할 것입니다. 체인 루트를 사용할 솔루션이 있는지 확인합니다. – Gabriel

답변

3

어딘가 약간 수정 한 해결책을 찾았습니다. 이것은 우리 모두가하고 싶다고 생각하는 것을 수행하는 커스텀 라우트 클래스입니다. 이것은 나를 위해 매력으로 작동

$route = new Rest_Controller_Route($front, 'customers/*', array('controller' => 'customers')); 
$router->addRoute('customers', $route); 

$route = new Rest_Controller_Route($front, 'customers/:customer_id/documents/*', array('controller' => 'customers-documents')); 
$router->addRoute('customersdocuments', $route); 

:

<?php 

require_once "modules.inc"; 

class Rest_Controller_Route extends Zend_Controller_Router_Route 
{ 

/** 
* @var Zend_Controller_Front 
*/ 
protected $_front; 

protected $_actionKey  = 'action'; 

/** 
* Prepares the route for mapping by splitting (exploding) it 
* to a corresponding atomic parts. These parts are assigned 
* a position which is later used for matching and preparing values. 
* 
* @param Zend_Controller_Front $front Front Controller object 
* @param string $route Map used to match with later submitted URL path 
* @param array $defaults Defaults for map variables with keys as variable names 
* @param array $reqs Regular expression requirements for variables (keys as variable names) 
* @param Zend_Translate $translator Translator to use for this instance 
*/ 
public function __construct(Zend_Controller_Front $front, $route, $defaults = array(), $reqs = array(), Zend_Translate $translator = null, $locale = null) 
{ 
    $this->_front  = $front; 
    $this->_dispatcher = $front->getDispatcher(); 

    parent::__construct($route, $defaults, $reqs, $translator, $locale); 
} 



/** 
* Matches a user submitted path with parts defined by a map. Assigns and 
* returns an array of variables on a successful match. 
* 
* @param string $path Path used to match against this routing map 
* @return array|false An array of assigned values or a false on a mismatch 
*/ 
public function match($path, $partial = false) 
{ 

    $return = parent::match($path, $partial); 

    // add the RESTful action mapping 
    if ($return) { 
     $request = $this->_front->getRequest(); 
     $path = $request->getPathInfo(); 
     $params = $request->getParams(); 

     $path = trim($path, '/'); 

     if ($path != '') { 
      $path = explode('/', $path); 
     } 

     $lastParam = array_pop($path); 

     // Determine Action 
     $requestMethod = strtolower($request->getMethod()); 
     if ($requestMethod == 'head') { 
      if (is_numeric($lastParam)) { 
       $return[$this->_actionKey] = 'head'; 
       $return["id"] = $lastParam; 
      } 
     } else if ($requestMethod != 'get') { 
      if ($request->getParam('_method')) { 
       $return[$this->_actionKey] = strtolower($request->getParam('_method')); 
      } elseif ($request->getHeader('X-HTTP-Method-Override')) { 
       $return[$this->_actionKey] = strtolower($request->getHeader('X-HTTP-Method-Override')); 
      } else { 
       $return[$this->_actionKey] = $requestMethod; 
      } 

      // Map PUT, DELETE and POST to actual create/update/delete actions 
      // based on parameter count (posting to resource or collection) 
      switch($return[$this->_actionKey]){ 
       case 'post': 
        $return[$this->_actionKey] = 'post'; 
        break; 
       case 'put': 
        $return[$this->_actionKey] = 'put'; 
        $return["id"] = $lastParam; 
        break; 
       case 'delete': 
        $return[$this->_actionKey] = 'delete'; 
        $return["id"] = $lastParam; 
        break; 
      } 
     } else { 
      // if the last argument in the path is a numeric value, consider this request a GET of an item 
      if (is_numeric($lastParam)) { 
       $return[$this->_actionKey] = 'get'; 
       $return["id"] = $lastParam; 
      } else { 
       if (isset($data[0]) && is_numeric($data[0])) { 
        $return[$this->_actionKey] = 'get'; 
        $return["id"] = $lastParam; 
       } else { 
        $return[$this->_actionKey] = 'index'; 
       } 
      } 
     } 
    } 

    return $return; 

} 

} 

이를 사용하려면 부트 스트랩 또는 index.php 파일, 두 가지 예에서이 같은 모든 경로를 만들 수 있습니다. 너는 이것이 나의 마지막 해결책이 아니라고 생각한다. 그래서 내가 발견하지 못한 용들이 있을지도 모른다. :)

+0

해결책을 가져 주셔서 감사합니다. 그것은 작동하는 것,하지만 내 젠드 환경에서 일부 설정을 변경해야한다고 생각합니다. application.ini에서 Zend_Rest_Route를 사용했습니다. 하지만 솔루션을 작동 시키려면이 Zend_Rest_Route의 사용을 중지해야합니다. 따라서 색인/get/put/post/patch/delete .phtml을 찾으려고합니다. 보기 폴더에있는 파일. – Daniel

+0

또한 본문에 매개 변수를 보낼 수없는 것 같습니다 (예 : curl -v -X http://api.example.com/customers -d foo = bar). – Daniel

+0

그것은 이상한 일입니다. Im. Im it doing. 컬링에 익숙하지 않아서 파이어 폭스 플러그인을 사용합니다. 네가하는 일이나 뭘 할 수 있니? – Gabriel