Php 科哈纳3.2如何在URI中使用连字符

Php 科哈纳3.2如何在URI中使用连字符,php,kohana,uri,kohana-3,routes,Php,Kohana,Uri,Kohana 3,Routes,最近,我一直在研究SEO,以及如何区别对待使用连字符或下划线的URI,特别是被谷歌视为分隔符的URI 无论如何,为了使我当前的项目符合这个标准,我发现由于Kohana使用函数名定义页面,我收到了意外的“-”警告 我想知道是否有任何方法可以在Kohana中使用URI,如: http://www.mysite.com/controller/function-name 显然,我可以为这个设置一个路由管理器。。。但如果我要有用户生成的内容,即新闻。然后我必须从数据库中获取所有文章,生成URI,然后为每

最近,我一直在研究SEO,以及如何区别对待使用连字符或下划线的URI,特别是被谷歌视为分隔符的URI

无论如何,为了使我当前的项目符合这个标准,我发现由于Kohana使用函数名定义页面,我收到了意外的“-”警告

我想知道是否有任何方法可以在Kohana中使用URI,如:

http://www.mysite.com/controller/function-name
显然,我可以为这个设置一个路由管理器。。。但如果我要有用户生成的内容,即新闻。然后我必须从数据库中获取所有文章,生成URI,然后为每个文章进行路由


有其他解决方案吗?

没有办法直接将连字符字符串映射到PHP函数,因此您必须执行路由


对于用户生成的内容,您可以像Stack Exchange那样进行操作。每次将用户内容保存到数据库时,都会为其生成一个slug(
kohana-3-2-how-can-i-use-hyphens-in-uris
),并将其与其他信息一起保存。然后,当您需要链接到它时,使用唯一id并将slug附加到末尾(例如:
http://stackoverflow.com/questions/7404646/kohana-3-2-how-can-i-use-hyphens-in-uris
)的可读性。

您可以执行以下操作

Route::set('route', '<controller>/<identifier>', array(
    'identifier' => '[a-zA-Z\-]*'
))
->defaults(array(
    'controller' => 'Controller',
    'action'     => 'show',
));
Route::set('Route','/',数组(
“标识符”=>“[a-zA-Z\-]*”
))
->默认值(数组)(
“控制器”=>“控制器”,
“操作”=>“显示”,
));

然后使用
Request::current()->param('identifier')
在函数中接收您的内容标识符,并手动解析它以查找相关数据。

您可以使用lambda函数执行此操作:

尝试各种解决方案后,我发现最简单、最可靠的方法是覆盖
Kohana\u请求\u客户端\u内部::执行\u请求
。为此,请在“application\classes\kohana\request\client\internal.php”中的
应用程序
文件夹中添加一个文件,然后将其内容设置为:

<?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
注意:这与中的方法相同,只是在面向对象方面稍有改进。Kohana允许我们非常容易地重载任何系统类,因此我们可以使用它来节省一些输入,并允许将来进行更干净的更新

我们可以在Kohana中插入请求流,并修复URL的操作部分中的破折号。为此,我们将重写Request\u Client\u内部系统类及其execute\u Request()方法。在那里,我们将检查request->action是否有破折号,如果有,我们将把它们切换为下划线,以允许php正确调用我们的方法

步骤1。打开应用程序/bootstrap.php并添加以下行:

define('URL_WITH_DASHES_ONLY', TRUE);
如果url中需要下划线,可以使用此常量在某些请求上快速禁用此功能

步骤2。在:application/classes/request/client/internal.php中创建一个新的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

好的,例如,如果我只是创建了一些函数,例如,一个法律页面mysite.com/legal/terms-and-conditions。我必须为我这样做的任何事情生成单独的路由?对于不符合
/
结构的任何事情,是的,您会这样做。所以在你的例子中,如果你想要连字符的URL部分,你必须这样做。我不能创建带下划线的动作函数吗。。。然后简单地用字符串替换将连字符改为下划线?是的,当然,为什么不呢。科哈纳路由是灵活的,因为你希望它是!但是要注意,当在url中直接使用函数名时,这可能是危险的,但通过以下操作很容易修复:<代码>$func_in_url=str_replace('-','''.'我的func');如果(!是可调用的(数组($this,'u protected_func_.'$func_in_url)))die()
因此url中的“my func”映射到
函数_protected_func_my_func(){}
请注意,这只对操作而不是控制器起作用。“非官方的Kohana 3.0 Wiki”有一个类似的解决方案,只是扩展了Konaha_Request(),它对操作和控制器都有效,但不处理重复的内容。