使用 Stringable 属性简化 Laravel 模型
Laravel 的 AsStringable
cast是一个强大的工具,可以显著增强在 Eloquent 模型中使用字符串属性的方式。通过将字符串属性转换为 Stringable 对象,你可以访问各种字符串操作方法,从而生成更清晰、更具表现力的代码。
在模型中实现 AsStringable
要使用 AsStringable
cast,只需在模型的 $casts
属性中指定它:
use Illuminate\Database\Eloquent\Casts\AsStringable;
class Post extends Model
{
protected $casts = [
'title' => AsStringable::class,
'content' => AsStringable::class,
];
}
真实案例:博客帖子(Post)管理
让我们假定有一个博客应用,出于各种目的,我们需要操纵帖子标题和内容。以下是我们如何利用 Stringable
属性:
class Post extends Model
{
protected $casts = [
'title' => AsStringable::class,
'content' => AsStringable::class,
];
public function getSnippetAttribute()
{
return $this->content->words(20)->append('...');
}
public function getSlugAttribute()
{
return $this->title->slug();
}
public function getFormattedContentAttribute()
{
return $this->content
->replaceMatches('/\*\*(.*?)\*\*/', '<strong>$1</strong>')
->replaceMatches('/\*(.*?)\*/', '<em>$1</em>')
->replaceMatches('/\n/', '<br>');
}
}
本例中:
• 我们将 title
和 content
都强制转换为 Stringable。
• getSnippetAttribute()
创建了帖子内容的 20 字预览。
• getSlugAttribute()
从帖子标题中生成一个对 URL 友好的 slug。
• getFormattedContentAttribute()
将一些基础 Markdown 式格式应用到内容中。
控制器中的用例:
class PostController extends Controller
{
public function show(Post $post)
{
return view('posts.show', [
'post' => $post,
'snippet' => $post->snippet,
'formattedContent' => $post->formatted_content,
]);
}
public function index()
{
$posts = Post::all()->map(function ($post) {
return [
'id' => $post->id,
'title' => $post->title->title(),
'snippet' => $post->snippet,
'slug' => $post->slug,
];
});
return view('posts.index', compact('posts'));
}
}
在 Blade 模板中:
<!-- posts/show.blade.php -->
<h1>{{ $post->title->title() }}</h1>
<p class="snippet">{{ $snippet }}</p>
<div class="content">{!! $formattedContent !!}</div>
<!-- posts/index.blade.php -->
@foreach ($posts as $post)
<article>
<h2><a href="{{ route('posts.show', $post['slug']) }}">{{ $post['title'] }}</a></h2>
<p>{{ $post['snippet'] }}</p>
</article>
@endforeach
这种方法尤其对于博客、维基或文档系统等内容密集型应用特别有用。它允许在模型中封装常见的字符串操作,保持控制器和视图的整洁,并专注于它们的主要职责。