jeremyharris / slugger
Slugger 是一个 CakePHP 插件,可以自动生成 slugs。
Requires
This package is not auto-updated.
Last update: 2023-05-08 19:47:38 UTC
README
Slugger
重大更改 原版 Slugger 专门使用命名参数。现在它默认使用传递的参数。配置数组也发生了变化。请阅读 README 以获取有关新配置的信息。要使用原始版本,请检出 1.0 标签。
Slugger 是一个插件,基本上自动将 cake urls(使用路由)重写为 slugged urls。
'/posts/view/12'
自动变为
'/posts/view/my-post-title'
这避免了在数据库中存储 slug、管理它、检查重复项等需求。它还避免了很多人使用的 Model::findBySlug()
解决方案。使用主键搜索你的帖子!(初始开发受到 Mark Story 的博客 的启发)。
然后 slug 会被透明地转换回适当的格式,用于你的控制器操作。
要求
- CakePHP 2.0.x(检查标签以获取 CakePHP 的旧版本)
安装
手动
- 下载此: http://github.com/jeremyharris/slugger/zipball/master
- 解压下载。
- 将生成的文件夹复制到 app/Plugin/Slugger/
GIT 子模块
在您的应用目录中键入
git submodule add git://github.com/jeremyharris/slugger.git Plugin/Slugger
git submodule update --init
Composer
确保在 composer.json
中存在 require
。这将安装插件到 Plugin/Slugger
{
"require": {
"jeremyharris/slugger": "dev-master"
}
}
如果您需要 slugger 的旧版本,请确保用 "1.0" 替换 "dev-master"。
用法
App::uses('SluggableRoute', 'Slugger.Routing/Route');
Router::connect(/posts/:action/:Post,
array(),
array(
'routeClass' => 'Slugger.SluggableRoute',
'models' => array('Post')
)
);
这是最小默认配置。我们在这个路由中使用 SluggableRoute 类,并检查 Post 模型以生成 slugs。`:Post` 键是我们传递的键(操作中的 `$id`)。
选项
Router::connect(/posts/:action/:Post,
array(),
array(
'routeClass' => 'Slugger.SluggableRoute',
'models' => array(
'<MODEL_NAME>' => array(
'slugField' => '<FIELD_TO_SLUG>',
'param' => '<SLUG_PARAM>'
)
),
'slugFunction' => '<SLUG_FUNCTION>'
)
);
<MODEL_NAME>
必需 至少需要一个模型名称。这些模型将在拉取和生成 slug 时被搜索。<FIELD_TO_SLUG>
默认情况下,Slugger 将$displayField
设置在模型上作为 slug。如果您希望使用不同的字段作为 slug,请在此处定义它。<SLUG_PARAM>
默认情况下,从路由中获取:<MODEL_NAME>
并用 slug 替换。如果它未定义,则假设为第一个传递的参数。您还可以配置它使用命名参数。<SLUG_FUNCTION>
一个可调用的函数。默认使用Inflector::slug
。
定义 slug 参数
Slug参数是Slugger从路由URL中提取并替换成你的slug的参数。默认情况下,它会检查传递的:<MODEL_NAME>
键。
:Post
对:Post
路由元素进行Slug处理
/post/view/5 --> /post/view/my-post-title
Post
对Post
命名的参数进行Slug处理
/post/view/Post:5 --> /post/view/my-post-title
自定义slug函数
你可以通过在路由选项中设置'slugFunction'键来自定义在slug你的URL时使用的函数。此键接受一个PHP 回调,并传递一个参数,即要slug的字符串。它期望返回一个字符串。
例如,要使用自定义函数
function my_custom_iconv_slugger($str) {
$str = preg_replace('/[^a-z0-9 ]/i', '', iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $str));
$quotedReplacement = preg_quote($replacement, '/');
$merge = array(
'/[^\s\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]/mu' => ' ',
'/\\s+/' => $replacement,
sprintf('/^[%s]+|[%s]+$/', $quotedReplacement, $quotedReplacement) => '',
);
return strtolower(preg_replace(array_keys($merge), array_values($merge), $str));
}
Router::connect('/posts/:action/*',
array(),
array(
'routeClass' => 'SluggableRoute',
'models' => array('Post'),
'slugFunction' => 'my_custom_iconv_slugger'
)
);
iconv 是一个PHP模块,它使用不同的字符集编码字符串,从而删除无效字符。它更快,但取决于你的系统设置。
在您的应用程序中使用Slugger
使用Cake的辅助工具和Router创建链接,以利用自动生成的slug
array(
'controller' => 'posts',
'action' => 'view',
12
)
变为如/posts/view/my-post-title
这样的URL字符串,然后通过将12
放回传递的参数中,将其变为控制器可以处理的正确请求。在你的控制器中,通过检查
function view($id = null) {
$post = $this->Post->read(null, $id);
// do controller stuff
}
如果你定义了自定义的<SLUG_PARAM>
,Slugger将替换你选择的任何参数类型,并将原始路由数组重新组合。
缓存
Slugger默认情况下会进行缓存。当你更新Sluggable路由使用的记录时,你需要删除缓存。例如,更新用户的用户名
App::uses('SlugCache', 'Slugger.Cache');
$this->User->id = 3;
$this->User->saveField('username', 'newUsername');
// invalidate user slugs
SlugCache::invalidate('User');
要使单个用户无效,你必须自己重新生成slug并将其保存到缓存中
$this->User->id = 3;
$newSlug = 'my-new-slug';
$userSlugs = SlugCache::get('User');
$userSlugs[$this->User->id] = $newSlug;
SlugCache::set('User', $userSlugs);
Slugger使用'Slugger'缓存配置进行缓存,因此自定义该配置以更改缓存引擎。
示例
使用第一个参数的传递参数示例(默认烘焙)
Router::connect(/posts/:action/*,
array(),
array(
'routeClass' => 'Slugger.SluggableRoute',
'models' => array('Post')
)
);
使用上述路由
array(
'controller' => 'posts',
'action' => 'view',
12
)
变为/posts/view/sluggable-is-cool
,并在控制器中这样访问
function view($id) {
$post = $this->Post->read(null, $id);
// do controller stuff
}
使用键传递参数的传递参数示例
Router::connect(/posts/:action/:post_id/*,
array(),
array(
'pass' => array('post_id'),
'routeClass' => 'Slugger.SluggableRoute',
'models' => array(
'Post' => array(
'param' => ':post_id'
)
)
)
);
使用上述路由
array(
'controller' => 'posts',
'action' => 'view',
'anotherArg',
'post_id' => 12
)
变为/posts/view/anotherArg/sluggable-is-cool
,并在控制器中这样访问
function view($id, $anotherArgWillBeHere) {
$post = $this->Post->read(null, $id);
// do controller stuff
}
注意事项
如果你在路由中使用键传递参数,请注意以下几点。
- 你不能使用正则表达式来验证使用此方法的路由元素,因为路由在Slugger重写之前被解析,并且它们会因为URL字符串不匹配预期的整数正则表达式而失败
- 缺少slug(即
/posts/missing-title
,其中missing-title
找不到作为slug)仍然会将:key
参数添加到路由参数中,因为无法进行正则表达式验证
命名参数示例
Router::connect(/posts/:action/*,
array(),
array(
'routeClass' => 'Slugger.SluggableRoute',
'models' => array(
'Post' => array(
'slugField' => 'post_title',
'param' => 'Post'
),
'Author' => array(
'param' => 'Author'
)
)
)
);
使用上述路由
array(
'controller' => 'posts',
'action' => 'view',
'Post' => 12,
'Author' => 1
)
变为/posts/view/jeremy/sluggable-is-cool
,并在控制器中这样访问
function view() {
$post = $this->Post->read(null, $this->request->params['named']['Post']);
$author = $this->Post->Author->read(null, $this->request->params['named']['Author']);
// do controller stuff
}
注释和功能
- 可以通过在路由选项中的
models
参数中传递多个模型。 - 如果模型有(将成为)重复的slug,可slug路由将自动将id添加到slug前面,以避免冲突
- 如果没有找到slug,它将回退到原始URL,因此你不需要更改数据库中的任何内容
- 不要把這些當作永久鏈接!這只是讓您的URL看起來更漂亮而已
限制
- 可能會與具有相同slug的多個模型發生衝突。一個解決方案是不在每條路徑中slug超過一個模型
- 如果有人將slugged URL加入書签,然後您後來添加了一個同名帖子,則已經加入書签的URL將不再有效,因為id將被預先添加到其上。為了避免發生這種情況,將
'prependPk' => true
傳遞給路徑選項,id將始終被添加到slug前面
許可證
根據MIT許可證授權 https://open-source.org.cn/licenses/mit-license.php 文件的重新分發必須保留上述版權聲明。