cakephp url modification: remove action and add sl

2019-06-03 08:56发布

问题:

I'm trying to remove the action in the cakephp url and add a slug inflector, to be more clear this is my expected output:
from this: example.com/posts/view/81/This is a test post
to this: example.com/posts/This-is-a-test-post

This is my current code:
That gives me this output: example.com/posts/view/This is a test post

Controller:

public function view($title = null) {
        if (!$title) {
            throw new NotFoundException(__('Invalid post'));
        }
        $post = $this->Post->findByTitle($title);
        if (!$post) {
            throw new NotFoundException(__('Invalid post'));
        }
        $this->set('post', $post);
    }

view.ctp:

$this->Html->link($post['Post']['title'], array('action' => 'view', $post['Post']['title']));

I also tried this one,this link being my reference CakePHP: Use post title as the slug for view method :
Output: example.com/posts/view/21/This-is-a-test-post

Controller:

function view($id) {
        $this->Post->id = $id;
        $this->set('post', $this->Post->read());
    }

view.ctp

$this->Html->link($post['Post']['title'], array('action' => 'view', $post['Post']['id'], Inflector::slug($post['Post']['title'],'-')));

below are the other links that I tried but failed, I also tried the modifying the routes.php but can't make the proper code to make it work

want to remove action name from url CakePHP
How to remove action name from url in cakephp?
Remove action name from Url in cakephp?

any help/suggestions is appreciated thanks.

回答1:

Use Id and Named parameter...

On routes.php

define new routes as-

Router::connect('/posts/:id-:title',
    array('controller' => 'posts',
        'action' => 'view')
);

This new defined routes will match and parse all url containing id and title named parameter..

Important Note:: Do not define new routes after the end of routes.php. Try to define on the middle of the file..

On view

echo $this->Html->link('Hi',array(
    'controller' => 'posts',
    'action' => 'view',
    'id' => 4,
    'title' => Inflector::slug('the quick brown fox')
));


回答2:

Well the solution provided above will fulfill your needs, but still after reading your question one thing comes into my mind... in your controller you are trying to read posts using title I mean this will slow down your system not recommended in programming so use id and increase one more column in your db table for slug(SEO title) which will be used for creating your post urls.

For example: 
Post title: This is a test post 
Create seo title for this as: this-is-a-test-post-123
Stor seo title in DB as <this-is-a-test-post>

See 123 is your posts ID now change your controller function to get data based on id ie.123, I hope you cn extract 123 from the sting easily...

Note: remember you have to think about this-is-a-123 string also because they also land in post having id 123.

Use below route for the above solution:

Router::connect('/posts/*', array('controller' => 'posts', 'action' => 'view'),array('pass' => array('title')));

Now in your controller:

You will get string "this-is-a-test-post-123" in $post_title

function view($post_title=null){   

           $temp = explode('-',$post_title);
           $posts_id= end($temp); 
           $lastKey = end(array_keys($temp));
           unset($temp[$lastKey]);
           $seoTitle = implode("-",$temp);
           //Now compare the above seoTitle with DB seo title for unique urls


}