开发者

CakePHP - How to do reverse routing with slug?

开发者 https://www.devze.com 2023-02-13 10:56 出处:网络
I am using CakePHP 1.3. I have a Product model. on the DB table among others there are id and slug fields.

I am using CakePHP 1.3. I have a Product model. on the DB table among others there are id and slug fields.

If I have a product that is id:37 and slug:My-Product-Title I want the URL fo开发者_如何学JAVAr the product to be:

products/37/My-Product-Title

Instead of the standard:

products/view/37

I created a route that looks like this:

Router::connect(
    '/products/:id/:slug',
    array('controller' => 'products', 'action' => 'view'),
    array('pass' => array('id'), 'id' => '[0-9]+')
);

Now I can go to http://server/products/37/My-Product-Title and it takes me to the right place.

But How do I get reverse routing to automatically build the correct URL in $HtmlHelper->link?

When I use:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 37)
);

It still outputs the standard products/view/37 url.


I don't believe that it's possible to be done auto-magically. The helper is just an "helper" who builds the link from the given parameters.

So the easiest method is to add another parameter in your link like so:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 37, $slug)
);

where the $slug is the data from the slug field.

Probably it could be done your idea, but you need to break the MVC pattern very badly :)

Edit:

Reading your question again I understood it well. See how should be done:

in your router.php add the following rule:

Router::connect(
    '/product/*',
    array('controller' => 'products', 'action' => 'view')
);

Please note that it's /product/* rather than /products/*

Your link should be done like this:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 37, 'my-product-title')
);

and the link would look like:

http://yourdomain.com/product/37/my-product-title

For me doing your suggestion is bad practice. Also I don't think it's good from SEO point of view redirecting always the user.


For routing:

Router::connect(
    '/products/:id/:slug',
    array('controller' => 'products', 'action' => 'view'),
    array('pass' => array('id'), 'id' => '[0-9]+')
);

Your links should look like this:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 'id' => 37, 'slug' => 'my-product-title')
);

You have to add additional (key => value) to your array for each :param in your routing. Then magic will work


You should look at the following post regarding custom route classes.

The slug data doesn't need to be involved with the database at all - the field is a fake field used to simplify logic and lookups. This solution allows you to reverse route slugs, without needing a slug field in the models table.

http://42pixels.com/blog/slugs-ugly-bugs-pretty-urls


I am not sure how bad this is but with the following code in the ProductsController:

function view($id)
{
    if( isset($_SERVER) && stristr($_SERVER["REQUEST_URI"],'view/') )
    {
        $this->Product->id = $id;
        $slug = $this->Product->field('slug');
        $this->redirect($id.'/'.$slug);
    }
    $data = $this->Product->find('first', array('conditions' => array('Product.id' => $id)));
    $this->set("data", $data);
}

If the page is accesses via /view/id it automatically redirects them to the current page using /id/slug

Now I can just use the default link scheme:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 37)
);

and they will be redirected to the right URL.

Only problem is I am not sure how bad it is to have a redirect happening every time a user visits a product page?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号