2011-09-13 2 views
3

최근에 나는 SEO에 대한 연구와 하이픈이나 밑줄을 사용하는 URI가 어떻게 다르게 취급되는지, 특히 하이픈을 구분 기호로 사용하는 Google이 어떻게 대처하는지 살펴 보았습니다.Kohana 3.2. - URI에서 하이픈을 사용하려면 어떻게해야합니까?

어쨌든이 기준을 충족시키기 위해 현재 프로젝트를 수정하고 싶습니다. Kohana가 함수 이름을 사용하여 페이지를 정의하기 때문에 예기치 않은 '-'경고가 나타났습니다.

내가 Kohana에서의 URI의 사용을 가능하게 할 수있는 방법이 있었는지 궁금 좋아 : 이것에 대한

http://www.mysite.com/controller/function-name 

분명히 내가 설정이 할 수있는 routeHandler ...하지만 사용자가 컨텐츠를 생성 가지고 있다면, 즉 뉴스. 그런 다음 데이터베이스에서 모든 기사를 가져와 URI를 생성 한 다음 각 URI에 대한 라우팅을 수행해야합니다.

대체 솔루션이 있습니까?

답변

3

참고 :이 방법은 Laurent's answer과 같은 방식으로 약간 더 OOP 적입니다. Kohana를 사용하면 시스템 클래스에 매우 쉽게 과부하가 걸릴 수 있으므로 입력을 절약하고 나중에 더 깨끗한 업데이트를 할 수 있습니다.

Kohana의 요청 흐름에 플러그인을 삽입하고 URL의 액션 부분에 대시를 수정할 수 있습니다. 이를 위해서 우리는 Request_Client_Internal 시스템 클래스를 오버라이드 할 것이고 execute_request() 메소드가 될 것이다.request-> action에 대시가 있는지 검사하고, 그렇다면 PHP가 메소드를 제대로 호출 할 수 있도록 밑줄로 바꿀 것입니다.

1 단계을 엽니 다 응용 프로그램/bootstrap.php이 줄을 추가 : 당신이 필요로하는 경우

define('URL_WITH_DASHES_ONLY', TRUE); 

당신은 신속하게 몇 가지 요청에이 기능을 사용하지 않으려면이 상수를 사용하는 URL에 밑줄 .

2 단계는 새로운 PHP 파일 만들기 :이 코드 응용 프로그램/클래스/요청/클라이언트/internal.php를 붙여 넣기 :이 단순히 모든 대시를 대체 무엇을

<?php defined('SYSPATH') or die('No direct script access.'); 

class Request_Client_Internal extends Kohana_Request_Client_Internal { 

    /** 
    * We override this method to allow for dashes in the action part of the url 
    * (See Kohana_Request_Client_Internal::execute_request() for the details) 
    * 
    * @param Request $request 
    * @return Response 
    */ 
    public function execute_request(Request $request) 
    { 
     // Check the setting for dashes (the one set in bootstrap.php) 
     if (defined('URL_WITH_DASHES_ONLY') and URL_WITH_DASHES_ONLY == TRUE) 
     { 
      // Block URLs with underscore in the action to avoid duplicated content 
      if (strpos($request->action(), '_') !== false) 
      { 
       throw new HTTP_Exception_404('The requested URL :uri was not found on this server.', array(':uri' => $request->uri())); 
      } 

      // Modify action part of the request: transform all dashes to underscores 
      $request->action(strtr($request->action(), '-', '_')); 
     } 
     // We are done, let the parent method do the heavy lifting 
     return parent::execute_request($request); 
    } 

} // end_class Request_Client_Internal 

을 밑줄이있는 $ request-> action에서 url이 /something/foo-bar 인 경우 Kohana는 이제이를 action_foo_bar() 메소드로 전달합니다.

같은 시간에 중복 된 콘텐츠 문제를 피하기 위해 모든 작업을 밑줄로 차단합니다.

+0

이것은 (액션이 아니라 컨트롤러. 'Unofficial Kohana 3.0 Wiki'에는 액션과 컨트롤러 모두에서 작동하지만 중복 된 내용을 처리하지 않는 Konaha_Request (http://kerkness.ca/kowiki/doku.php?id=routing:using_hyphen_in_urls)를 확장하는 비슷한 솔루션이 있습니다. . – ChrisV

1

하이픈으로 연결된 문자열을 PHP 함수에 직접 매핑 할 방법이 없으므로 라우팅을 수행해야합니다.

사용자가 생성 한 콘텐츠까지 스택 Exchange처럼 할 수 있습니다. 사용자 컨텐트가 데이터베이스에 저장 될 때마다 슬러그 (kohana-3-2-how-can-i-use-hyphens-in-uris)가 생성되고 다른 정보와 함께 저장됩니다. 그런 다음 링크해야 할 때 고유 한 ID를 사용하고 가독성을 위해 슬러그를 끝에 붙입니다 (예 : http://stackoverflow.com/questions/7404646/kohana-3-2-how-can-i-use-hyphens-in-uris).

+0

좋아요. 예를 들어, 단지 합법적 인 페이지 mysite.com/legal/terms-and-conditions를 작성하는 기능인 경우입니다. 내가 좋아하는 모든 것을위한 개별 경로를 만들어야합니까? – diggersworld

+0

'//구조로 맞지 않는 것에는 그렇습니다. 따라서 예제에서 하이픈으로 연결된 URL 부분을 원한다면해야 할 것입니다. – Brandon

+0

밑줄이있는 작업 기능을 생성 할 수 없습니까? 단순히 하이픈을 밑줄로 바꾸려면 문자열 바꾸기를 사용하십시오. – diggersworld

0

당신은 그런 Request::current()->param('identifier')와 기능에 콘텐츠 식별자를 수신하고 관련 데이터를 찾아 수동으로 분석

Route::set('route', '<controller>/<identifier>', array(
    'identifier' => '[a-zA-Z\-]*' 
)) 
->defaults(array(
    'controller' => 'Controller', 
    'action'  => 'show', 
)); 

뭔가를 할 수 있습니다.

0

시도 다양한 솔루션을 가진 후, 내가 가장 쉽고 안정적인 방법은 Kohana_Request_Client_Internal::execute_request을 무시하는 것으로 나타났습니다. 예를 들어, 하이픈 조치를 추가하는 그런

<?php defined('SYSPATH') or die('No direct script access.'); 
class Kohana_Request_Client_Internal extends Request_Client { 

    /** 
    * @var array 
    */ 
    protected $_previous_environment; 

    /** 
    * Processes the request, executing the controller action that handles this 
    * request, determined by the [Route]. 
    * 
    * 1. Before the controller action is called, the [Controller::before] method 
    * will be called. 
    * 2. Next the controller action will be called. 
    * 3. After the controller action is called, the [Controller::after] method 
    * will be called. 
    * 
    * By default, the output from the controller is captured and returned, and 
    * no headers are sent. 
    * 
    *  $request->execute(); 
    * 
    * @param Request $request 
    * @return Response 
    * @throws Kohana_Exception 
    * @uses [Kohana::$profiling] 
    * @uses [Profiler] 
    * @deprecated passing $params to controller methods deprecated since version 3.1 
    *    will be removed in 3.2 
    */ 
    public function execute_request(Request $request) 
    { 
     // Create the class prefix 
     $prefix = 'controller_'; 

     // Directory 
     $directory = $request->directory(); 

     // Controller 
     $controller = $request->controller(); 

     if ($directory) 
     { 
      // Add the directory name to the class prefix 
      $prefix .= str_replace(array('\\', '/'), '_', trim($directory, '/')).'_'; 
     } 

     if (Kohana::$profiling) 
     { 
      // Set the benchmark name 
      $benchmark = '"'.$request->uri().'"'; 

      if ($request !== Request::$initial AND Request::$current) 
      { 
       // Add the parent request uri 
       $benchmark .= ' « "'.Request::$current->uri().'"'; 
      } 

      // Start benchmarking 
      $benchmark = Profiler::start('Requests', $benchmark); 
     } 

     // Store the currently active request 
     $previous = Request::$current; 

     // Change the current request to this request 
     Request::$current = $request; 

     // Is this the initial request 
     $initial_request = ($request === Request::$initial); 

     try 
     { 
      if (! class_exists($prefix.$controller)) 
      { 
       throw new HTTP_Exception_404('The requested URL :uri was not found on this server.', 
                array(':uri' => $request->uri())); 
      } 

      // Load the controller using reflection 
      $class = new ReflectionClass($prefix.$controller); 

      if ($class->isAbstract()) 
      { 
       throw new Kohana_Exception('Cannot create instances of abstract :controller', 
        array(':controller' => $prefix.$controller)); 
      } 

      // Create a new instance of the controller 
      $controller = $class->newInstance($request, $request->response() ? $request->response() : $request->create_response()); 

      $class->getMethod('before')->invoke($controller); 

      // Determine the action to use 
      /* ADDED */ if (strpos($request->action(), '_') !== false) throw new HTTP_Exception_404('The requested URL :uri was not found on this server.', array(':uri' => $request->uri())); 
      /* MODIFIED */ $action = str_replace('-', '_', $request->action()); /* ORIGINAL: $action = $request->action(); */ 

      $params = $request->param(); 

      // If the action doesn't exist, it's a 404 
      if (! $class->hasMethod('action_'.$action)) 
      { 
       throw new HTTP_Exception_404('The requested URL :uri was not found on this server.', 
                array(':uri' => $request->uri())); 
      } 

      $method = $class->getMethod('action_'.$action); 

      $method->invoke($controller); 

      // Execute the "after action" method 
      $class->getMethod('after')->invoke($controller); 
     } 
     catch (Exception $e) 
     { 
      // Restore the previous request 
      if ($previous instanceof Request) 
      { 
       Request::$current = $previous; 
      } 

      if (isset($benchmark)) 
      { 
       // Delete the benchmark, it is invalid 
       Profiler::delete($benchmark); 
      } 

      // Re-throw the exception 
      throw $e; 
     } 

     // Restore the previous request 
     Request::$current = $previous; 

     if (isset($benchmark)) 
     { 
      // Stop the benchmark 
      Profiler::stop($benchmark); 
     } 

     // Return the response 
     return $request->response(); 
    } 
} // End Kohana_Request_Client_Internal 

이렇게하려면 "요청 \ 클라이언트 \의 internal.php 응용 프로그램의 \ 클래스 \ kohana \"에 application 폴더에 파일을 추가 한 다음에 그 내용을 설정 , "controller/my-action"은 "my_action()"이라는 액션을 생성합니다.

사용자가 "controller/my_action"에 액세스하려고 시도하면 오류가 발생합니다 (중복 콘텐츠를 방지하기 위해).

일부 개발자는이 방법이 마음에 들지 않지만 장점은 작업의 이름을 바꾸지 않기 때문에 현재 작업을 확인하면 모든 곳에서 일관되게 "내 조치"라고합니다. Route 또는 lambda 함수 메소드를 사용하면 action은 "my_action", 언젠가는 "my-action"이라고 할 수 있습니다 (두 메소드가 모두 액션의 이름을 변경하기 때문에).

관련 문제