CakePHP友好的SEO URL

4
我希望使我的url更加符合seo优化要求。将www.example.com/posts/view/1改为www.example.pl/:slug-:id。一切工作正常,但可能我的路由设置有误,因为当在paginator中点击urls后,url是正确的,看起来像www.example.pl/:slug-:id,但是却出现了错误:

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

我不知道问题出在哪里。这是我的代码:

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

在分页器视图中:

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

我解决了这个问题。
5个回答

4

这太简单了,我将给你举一个我项目中的例子... 在你的routes.php文件中。

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

你在 视图 中的链接应该像这样。
$this->Html->link(__('link desu'),array('controller'=>'posts','action'=>'view','id'=>$post['Post']['id'],'slug'=>$post['Post']['slug']));

以及你的PostsController.php

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

快速提示:尝试在您的PostModel中创建一个数组,以避免每次在视图中都创建它。示例:
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;
    }
}

因此,您可以在视图中简单地调用它

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

1
+1,尽管“快速提示”会分散注意力,但并不影响实际答案。 - AD7six
为什么呢,只是为了避免每次想要获取您的URL时创建那些大数组(有时)。 - Abdou Tahiri
1
请记住你正在回答一个问题:超过一半的答案与问题无关 - 现在知道了问题(参见作者的回答),实际解决问题的唯一行(单数,1)是这个:public function view($slug,$id){. - AD7six
1
我明白了。只是想通过这个有用的提示给我的答案加上一个奖励,无论如何还是谢谢 :) - Abdou Tahiri

2

可能是路由中的正则表达式出了问题。您的slug包含连字符-,这也是您用于在slug和id之间分隔的符号。例如:

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

正则表达式不够智能,无法知道“最后一个”连字符将slug与id分开。 为了测试是否是这个问题,请尝试使用如下路由 '/:slug__:id',只是为了看看它是否起作用。

1
这是一个合理的猜测,但贪婪正则表达式并不是这样工作的——如果没有限制,slug 将只是字符串“my-slug-has-hyphens”。我建议在回答之前先尝试您所建议的内容。 - AD7six

1

我解决了这个问题。在帖子控制器中,我的视图函数是错误的。这是正确的:

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

+1 是为了回答自己的问题。注意,代码并没有错,只是与路由定义不匹配。 - AD7six

0

Pass是有顺序的

在这个问题中,路由如下:

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

这意味着post函数将会接收到:

public function view($slug, $id)

根据修改后的问题,代码期望id是第一个参数。最简单的解决方案就是按照期望的顺序指定传递的参数:

...
        'pass' => array('id', 'slug'), # <-

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

以上代码将创建正确的链接,如 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']));

-1 因为这会改变问题以匹配答案,而不是回答问题。 - AD7six

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接