expstudio/friendly-url

使用PHP5.3.x和非拉丁字符支持,在Laravel 4中轻松创建Eloquent模型的路由别名或友好URL。

2.0.1 2014-05-13 18:10 UTC

This package is not auto-updated.

Last update: 2024-09-28 16:25:49 UTC


README

在Laravel 4中轻松为Eloquent模型创建路由别名。

背景:什么是路由别名?

路由别名是字符串的简化版本,通常是URL友好的。将字符串“路由别名化”通常涉及将其转换为单一大小写,并删除任何非URL友好的字符(空格、重音字母、和号等)。生成的字符串可以用来标识特定的资源。

例如,我有一个包含帖子内容的博客。我可以通过ID引用每个帖子

http://example.com/post/1
http://example.com/post/2

...但这并不特别友好(特别是对于SEO)。你可能更喜欢使用帖子的标题作为URL,但如果帖子的标题是“我与安德烈和弗朗索瓦共进晚餐”,那么这也会很丑陋

http://example.com/post/My+Dinner+With+Andr%C3%A9+%26+Fran%C3%A7ois

解决方案是为标题创建一个路由别名并使用它。你可能想使用Laravel内置的Str::slug()方法将标题转换为更友好的形式

http://example.com/post/my-dinner-with-andre-francois

这样的URL会让用户更满意(可读性更强,更容易输入等)。

更多信息,你可能想阅读维基百科上的这篇描述

路由别名通常也是唯一的。所以如果我再写一篇标题相同的帖子,我需要以某种方式区分它们,通常是在路由别名末尾添加一个递增计数器

http://example.com/post/my-dinner-with-andre-francois
http://example.com/post/my-dinner-with-andre-francois-1
http://example.com/post/my-dinner-with-andre-francois-2

这保持了URL的唯一性。

Laravel 4的包会自动处理所有这些,初始配置最小。

安装和需求

首先,您需要将包添加到composer.json文件的require属性中

{
    "require": {
        "expstudio/friendlyurl": "dev-master"
    },
}

注意:Eloquent-Sluggable现在使用特性,因此您需要运行PHP 5.4或更高版本。如果您仍在使用5.3,请使用“1.*”版本,并遵循该版本README.md文件中的说明。

然后,从命令行运行composer update

然后,通过添加服务提供者的条目来更新app/config/app.php

	'providers' => array(

		// ...

		'Expstudio\FriendlyUrl\SluggableServiceProvider',

	);

最后,再次从命令行运行php artisan config:publish expstudio/friendlyurl以发布默认配置文件。

更新你的Eloquent模型

您的模型应实现Sluggable的接口并使用其特性。您还应定义一个受保护的属性$sluggable,其中包含任何特定于模型的配置(有关详细信息,请参阅下面的配置

use Expstudio\FriendlyUrl\SluggableInterface;
use Expstudio\FriendlyUrl\SluggableTrait;

class Post extends Eloquent implements SluggableInterface
{

	use SluggableTrait;

	protected $sluggable = array(
		'build_from' => 'title',
		'save_to'    => 'slug',
	);

}

当然,您的数据库需要一个用于存储别名的列。您可以手动操作,或使用内置的Artisan命令为您创建迁移。例如

php artisan sluggable:table posts

运行该命令将在您的帖子表中添加一个名为“slug”的列。如果您想为别名列使用不同的名称,您可以将其作为第二个参数提供

php artisan sluggable:table posts slug_column

确保设置模型的save_to配置以匹配列名。

就是这样...您的模型现在可以“路由别名化”了!

使用类

保存模型很简单

$post = new Post(array(
	'title' => 'My Awesome Blog Post'
));

$post->save();

检索别名也同样简单

echo $post->slug;

// or, if you don't know the name of the slug attribute:
echo $post->getSlug();

请参阅 README-Ardent.md 文件,了解如何在使用 Ardent 时使用 Eloquent-Sluggable。

注意:如果您正在使用 Eloquent 的 replicate() 方法复制模型,那么您需要显式告诉包在之后强制重新生成模型的 slugging,以确保唯一性。

$new_post = $post->replicate()->resluggify();

配置

配置设计得尽可能灵活。您可以设置所有 Eloquent 模型的默认值,然后为单个模型覆盖这些设置。

默认情况下,全局配置可以在 app/config/packages/expstudio/friendlyurl/config.php 文件中设置。如果没有设置配置,则使用 vendor/expstudio/friendlyurl/src/config/config.php 中的包默认值。以下是一个配置示例,显示了所有默认设置:

return array(
	'build_from'      => null,
	'save_to'         => 'slug',
	'max_length'      => null,
	'method'          => null,
	'separator'       => '-',
	'unique'          => true,
	'include_trashed' => false,
	'on_update'       => false,
	'reserved'        => null,
	'use_cache'       => false,
);

build_from

这是构建 slug 字段或字段数组。每个 $model->field 将通过空格分隔连接起来,以构建可 slugging 字符串。这可以是模型属性(即数据库中的字段)或自定义获取器。例如,这可以工作:

class Person extends Eloquent implements SluggableInterface {

	use SluggableTrait;

	public static $sluggable = array(
		'build_from' => 'fullname'
	);

	public function getFullnameAttribute() {
		return $this->firstname . ' ' . $this->lastname;
	}

}

如果 build_from 为空、false 或 null,则使用 $model->__toString() 的值。

save_to

这是模型中存储 slug 的属性字段。默认情况下,这是 "slug"。当定义模式时,您需要在表中创建此列。

Schema::create('posts', function($table)
{
	$table->increments('id');
	$table->string('title');
	$table->string('body');
	$table->string('slug');
	$table->timestamps();
});

max_length

将此设置为正整数将确保生成的 slug 限制在最大长度内(例如,以确保它们适合您的数据库字段)。默认情况下,此值是 null,不强制执行限制。

注意:如果启用 unique(默认启用),并且您预计会有多个模型具有相同的 slug,则应将此值设置为数据库字段长度略短。原因在于,类将为后续模型附加 "-1"、" "-2"、" "-3",等等,以保持唯一性。这些增量扩展不包括在 max_length 计算中。

method

定义将可 slugging 字符串转换为 slug 使用的函数。此配置有三个可能的选项:

  1. method 为 null(默认设置)时,包使用修改后的 Laravel 的 Str::slug() 方法来创建 slug。

  2. method 是可调用的函数或类方法时,则使用该函数或方法。函数/方法应期望两个参数:要处理的字符串和分隔符字符串。例如,要复制默认行为,您可以这样做:

    	'method' => array('Illuminate\\Support\\Str', 'slug'),
  3. 您还可以将 method 定义为闭包(同样,期望两个参数)

    	'method' => function( $string, $separator ) {
    		return strtolower( preg_replace('/[^a-z]+/i', $separator, $string) );
    	},

其他 method 的值将抛出异常。

对于更复杂的 slugging 要求,请参阅下面的 扩展 Sluggable

separator

这定义了构建 slug 时使用的分隔符,并将其传递给上面定义的 method。默认值是连字符。

unique

这是一个布尔值,定义 slugs 是否应在给定类型的所有模型中保持唯一。例如,如果您有两个名为 "My Blog Post" 的博客文章,那么它们都将使用 Sluggable 的默认设置转换为 "my-blog-post"。这可能会成为问题,例如如果您在 URL 中使用 slug。

开启 unique 后,第二个文章模型将转换为 "my-blog-post-1"。如果有第三个具有相同标题的文章,它将转换为 "my-blog-post-2",依此类推。每个后续模型都会在 slug 的末尾附加一个增量值,以确保唯一性。

include_trashed

将此设置为 true 将也会在尝试强制唯一性时检查已删除的模型。这仅影响使用 软删除 功能的 Eloquent 模型。默认值为 false,因此检查唯一性时不会计算软删除的模型。

on_update

一个布尔值。如果它是 false(默认值),那么在模型重新保存时(例如,如果您更改博客文章的标题,则 slug 将保持不变)或 slug 值已被设置时,slugs 不会更新。如果您想覆盖此行为,可以将其设置为 true(或在您的代码中手动更改 $model->slug 值)。

(如果您想使用模型的自定义 Sluggable 设置手动设置 slug 值,可以运行 $model->resluggify() 来强制 Sluggable 更新 slug 字段。)

reserved

一个数组,其中的值永远不会被允许作为 slugs,例如,为了防止与现有路由或控制器方法等冲突。这可以是一个数组,也可以是一个返回数组的闭包。默认值为 null:没有保留的 slug 名称。

use_cache

在检查唯一性时,该包将查询数据库以获取具有相同或类似 slugs 的任何现有模型,然后检查是否需要增量。这意味着更多的数据库使用,如果在同一时间保存大量模型,也可能导致竞争条件。

开启 use_cache 将使用 Laravel 的缓存存储最后生成的增量,以便您的应用程序可以节省这些数据库请求。

默认值是 false:不使用缓存。如果您已经使用支持 Cache::tags() 功能(即除了数据库和文件缓存以外的任何内容)的缓存系统,那么您真的应该启用此设置。将其更改为正整数,表示在缓存中存储 slug 信息的分钟数。

(如果您出于任何原因想清除 Sluggable 的所有缓存条目,只需运行 Cache::tags('sluggable')->flush()。)

扩展Sluggable

有时配置选项不足以满足复杂需求(例如,可能需要考虑其他属性的唯一性测试,或者可能需要为同一模型生成两个 slugs)。

在这种情况下,您的最佳选择是在每个模型的基础上重载一些 SluggableTrait 的方法,或者是在扩展 SluggableTrait 的您自己的特质中。每个步骤都会分解为它自己的方法,并在生成 slug 时依次调用这些方法。

查看 SluggableTrait->sluggify() 以查看操作顺序,但您可以考虑重载以下受保护的任何方法

needsSlugging()

确定模型是否需要 slugging。应返回一个布尔值。

getSlugSource()

返回一个字符串,该字符串形成 slug 的来源(通常基于 build_from 配置值)。

generateSlug($source)

实际的 slugging 代码。通常实现 method 配置中定义的内容,但可能调用其他 slugging 库。接收源字符串(上面)并返回一个字符串。

validateSlug($slug)

验证生成的 slug 是否有效,通常通过将其与 reserved 配置中定义的内容进行比较。应返回一个有效的 slug 字符串。

makeSlugUnique($slug)

检查给定的 slug 是否唯一。应返回一个唯一的 slug 字符串。

setSlug($slug)

将(生成的、有效的和唯一的)slug 写入模型属性。

错误、建议和贡献

请使用 Github 进行错误、评论和建议。

  1. 分叉项目。
  2. 创建您的错误修复/功能分支并编写您的(注释良好的)代码。
  3. 为您的代码创建单元测试。
    • 在根目录中运行 composer install --dev 以安装所需的测试包。
    • 将您的测试方法添加到 eloquent-sluggable/tests/SluggableTest.php
    • 运行 vendor/bin/phpunit 以运行新(以及所有以前)的测试,并确保一切通过。
  4. 提交您的更改(以及您的测试)并推送到您的分支。
  5. 创建一个新的拉取请求,针对eloquent-sluggable的develop分支。

请注意,您必须针对develop分支创建您的拉取请求。

版权和许可证

Laravel4友好URL已被Watee Wichiennit从Eloquent-Sluggable修改并发布在MIT许可证下。有关详细信息,请参阅LICENSE文件。

版权所有 2014 Watee Wichiennit