Question

I want to make my url seo friendly. www.example.com/posts/view/1 change for www.example.pl/:slug-:id. Everything works fine, but probably I'm doing something wrong with routing, because when after clicking the urls in paginator, the url is correct, it looks like www.example.pl/:slug-:id , but it appears an error

"The requested address 'www.example.pl/:slug-:id' was not found on this server."

I don't know what's wrong. Here's my code:

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

in paginator view:

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

I solved the problem.

Était-ce utile?

La solution 3

I solved the problem. In the posts controller my view function was wrong. Here's right correct:

function view($id = null, $slug = null) {
$this->Post->id = $this->params['post'];
$this->set('post', $this->Post->read());

Autres conseils

Its too simple i'll give you an example from my project .. in your routes.php

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

your link in views should be like .

$this->Html->link(__('link desu'),array('controller'=>'posts','action'=>'view','id'=>$post['Post']['id'],'slug'=>$post['Post']['slug']));

and your PostsController.php

public function view($slug,$id){
    $this->Post->id = $id;
    // ....
}

Quick tip : try to create an array in your PostModel to avoid creating it every time in your view . example :

Post.php

class Post extends AppModel{
    // ....
        public function afterFind($results,$primary = false){
        foreach ($results as $key => $value) {
            if(isset($value[$this->alias]['id'])){
                $results[$key][$this->alias]['url'] = array(
                                 'controller'=>'posts',
                                 'action'=>'view',
                                 'id'=>$results[$key][$this->alias]['id'],
                                 'slug'=>$results[$key][$this->alias]['slug']
                            );  
            }
            // ....
        }
        return $results;
    }
}

}

so you can call it in your view simply like that

$this->Html->link(__('link desu'),$post['Post']['url']);

It's probably a problem with the regex on the route. Your slug contain hyphens - which you also use to separate between the slug and the id. i.e.:

example.com/my-slug-has-hyphens-1

The regex is not smart enough to know that the "last" hyphen separates the slug from the id.

To test if this is the problem, try using a route like this '/:slug__:id', just to see if it works.

Pass is order sensitive

In the question the route is as follows:

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

That means the post function will recieve:

public function view($slug, $id)

As indicated by the edited question, the code is expecting the id to be the first parameter. The easiest solution is simply to specify the passed parameters in the order that they are expected:

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

the above code will create correct link as www.example.com/posts/view/title/1

echo $this->Html->link($post['Post']['title'], array('controller' => 'posts', 'action' => 'view', Inflector::slug($post['Post']['title'],'-'),$post['Post']['id']));
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top