CakePHP - How to do reverse routing with slug?

前端 未结 4 1089
囚心锁ツ
囚心锁ツ 2021-01-13 12:12

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

相关标签:
4条回答
  • 2021-01-13 12:46

    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

    0 讨论(0)
  • 2021-01-13 12:46

    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 讨论(0)
  • 2021-01-13 12:47

    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.

    0 讨论(0)
  • 2021-01-13 13:08

    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

    0 讨论(0)
提交回复
热议问题