Search code examples
phpcakephpcakephp-3.0view-helperstrailing-slash

Add a trailing slash while building URLs from Helpers in CakePHP 3


I'm working on a blog-like website in CakePHP 3 and made the canonical URL structure with a trailing slash for SEO purposes. To accomplish this, in the routes file I built the requests to match a trailing slash, and in the webroot .htaccess made the proper redirects to handle requests without a trailing slash. Also, in the AppController I override the redirect function to manage redirects from Controllers:

function redirect($url, $status = null, $exit = true)
{
    $routerUrl = Router::url($url, true);
    if(!preg_match('/\.[a-z0-9]{1,5}$/', strtolower($routerUrl)) && substr($routerUrl, -1) != '/') {
        $routerUrl .= '/';
    }
    parent::redirect($routerUrl, $status, $exit);
}

So far, so good.

Now, I would like to build URLs with a trailing slash every time I build them with a Helper, like FormHelper or HtmlHelper. For example:

$this->Form->create(null, [
    'url' => ['controller' => 'Messages', 'action' => 'send']
]);

The URL output in this case would be:

/messages/send

And I need it to be:

/messages/send/

At the moment I'm hard-coding the URL in the Helper's options for it to work (not in production yet). If I use the example's option, when the Form is submitted it redirects /messages/send to /messages/send/ because of the .htaccess redirect rules and the POST data is lost.

Thanks in advance, and I apologize for my poor English, I hope I made myself clear.


Solution

  • I’d recommend to create an alias for your Helper and tweak the URL building.

    src/View/AppView.php

    class AppView extends View
    {
        public function initialize()
        {
            $this->loadHelper('Url', [
                'className' => 'MyUrl'
            ]);
        }
    }
    

    src/View/Helper/MyUrlHelper.php

    namespace App\View\Helper;
    
    use Cake\View\Helper\UrlHelper;
    
    class MyUrlHelper extends HtmlHelper
    {
        public function build($url = null, $options = false)
        {
            // Add your code to override the core UrlHelper build() function
    
            return $url;
        }
    }
    

    Find the original source of UrlHelper here.