spatie / sheets
将静态内容存储和检索在纯文本文件中
Requires
- php: ^8.0
- ext-json: *
- illuminate/contracts: ^8.71|^9.0|^10.0|^11.0
- illuminate/filesystem: ^8.71|^9.0|^10.0|^11.0
- illuminate/support: ^8.71|^9.0|^10.0|^11.0
- league/commonmark: ^1.0|^2.0
- spatie/yaml-front-matter: ^2.0
- symfony/yaml: ^4.0|^5.0|^6.0|^7.0
Requires (Dev)
- league/flysystem: ^1.0.8|^3.0
- orchestra/testbench: ^6.23|^7.0|^8.0|^9.0
- phpunit/phpunit: ^9.4|^10.5
README
Sheets是一个用于存储、检索和索引以文本文件形式存储的内容的Laravel包。默认支持Markdown文件和front matter,但你也可以从任何你偏好的格式解析和提取数据。
Sheets可以添加到任何现有的Laravel应用程序中,非常适合文档网站和个人博客。
--- title: Home --- # Hello, world! Welcome to Sheets!
class SheetController { public function index(Sheets $sheets) { return view('sheet', [ 'sheet' => $sheets->get('home'), ]); } public function show(string $id, Sheets $sheets) { return view('sheet', [ 'sheet' => $sheets->get($id), ]); } }
@extends('layouts.app', [ 'title' => $sheet->title, ]) @section('main') {{ $sheet->contents }} @endsection
特性
- 允许任何文档格式(默认为带有front matter的Markdown文件)
- 将您的内容存储在任何您想要的地方(使用Laravel的文件系统组件)
- 保持多个内容集合(例如帖子、页面等)
- 将文档内容转换为Eloquent-like类,具有访问器
- 约定优于配置,如果您使用默认设置,则接近零设置
支持我们
我们投入了大量资源来创建一流的开放源代码包。您可以通过购买我们的付费产品之一来支持我们。
我们非常感谢您从您的家乡寄给我们一张明信片,说明您正在使用我们的哪个包。您可以在我们的联系页面上找到我们的地址。我们在我们的虚拟明信片墙上发布所有收到的明信片。
安装
您可以通过composer安装此包
composer require spatie/sheets
Laravel将自动发现并注册SheetsServiceProvider
,因此不需要进一步设置。
安装后,您必须发布sheets.php
配置文件
php artisan vendor:publish --provider="Spatie\Sheets\SheetsServiceProvider" --tag="config"
最后,您必须创建您的第一个集合。
使用
Sheets
实例通过外观、辅助函数或依赖注入提供。
use Sheets; Sheets::all();
sheets()->all();
use Spatie\Sheets\Sheets; class SheetsController { public function index(Sheets $sheets) { return view('sheets', [ 'sheets' => $sheets->all(), ]); } }
创建您的第一个集合
集合映射到您选择的文件系统中的一个文件夹。Sheets将在配置文件config/filesystems.php
中查找与集合同名的磁盘——或者您可以自行配置磁盘名称。
// config/filesystems.php return [ 'disks' => [ // ... 'posts' => [ 'driver' => 'local', 'root' => base_path('posts'), ], ], ]; // config/sheets.php return [ 'collections' => ['posts'], ];
Sheets将为您的应用程序中的posts
文件夹创建一个仓库。
app/
config/
posts/
hello-world.md
---
title: Hello, world!
---
# Hello, world!
Welcome to Sheets!
仓库有两个公共方法:all()
和get($slug)
。您可以通过Sheets
上的collection
方法获取仓库实例。
Repository::all()
将返回一个包含Spatie\Sheets\Sheet
实例的Illuminate\Support\Collection
。
$repository = Sheets::collection('posts'); $repository->all();
Repository::get($slug)
返回单个Sheet
实例或null
(如果没有找到任何内容)。一个sheet的slug
字段包含其文件名,不带扩展名。
Sheets::collection('posts')->get('hello-world');
Sheet
实例非常类似于Eloquent模型。它包含一个属性数组,这些属性作为属性公开。默认情况下,它将包含路径作为slug
字段,所有front matter数据,以及一个包含包含Markdown的HTML表示的contents
字段。
$sheet = Sheets::collection('posts')->get('hello-world'); echo $sheet->slug; // 'hello-world' echo $sheet->title; // 'Hello, world!' echo $sheet->contents; // '<h1>Hello, world!</h1><p>Welcome to Sheets!</p>'
您可以使用与Eloquent相同的访问器创建自己的Sheet
实现,但我们将稍后深入探讨。
配置集合
Sheets功能高度可配置。您可以通过在config/sheets.php
中使用关联数组,分别配置每个集合。
// config/sheets.php return [ 'collections' => [ 'pages' => [ 'disk' => null, // Defaults to collection name 'sheet_class' => Spatie\Sheets\Sheet::class, 'path_parser' => Spatie\Sheets\PathParsers\SlugParser::class, 'content_parser' => Spatie\Sheets\ContentParsers\MarkdownWithFrontMatterParser::class, 'extension' => 'md', ], ], ];
以上是集合的默认配置样子(我们一直以来的配置)。在配置集合时,每个键都是可选的,如果不存在,Sheets将使用这些值之一。
磁盘
存储您内容的磁盘名称。磁盘在config/filesystems.php
中配置。默认情况下,Sheets将查找与集合同名的磁盘。
// config/sheets.php return [ 'collections' => [ 'pages' => [ 'disk' => null, // Uses the 'pages' disk ], ], ];
// config/sheets.php return [ 'collections' => [ 'pages' => [ 'disk' => 'sheets', // Uses the 'sheets' disk ], ], ];
Sheet类
您的将内容转换为Sheet
实例。Sheet
类类似于一个精简版的Eloquent模型:它包含一组属性,这些属性可以作为属性使用。
$sheet = Sheets::collection('page')->get('hello-world'); echo $sheet->slug; // 'hello-world'
您可以扩展Sheet
类来添加访问器(就像在Eloquent中一样)和自定义行为。
namespace App; use Spatie\Sheets\Sheet; class Page extends Sheet { public function getUrlAttribute(): string { return url($this->slug); } }
// config/sheets.php return [ 'collections' => [ 'pages' => [ 'sheet_class' => App\Page::class, ], ], ];
$sheet = Sheets::collection('pages')->get('hello-world'); echo $sheet->url; // 'https://example.app/hello-world'
路径解析器
Sheets使用文件路径来确定Sheet
属性的一部分。路径解析器能够解析路径到一组属性。
默认路径解析器是SlugParser
,它简单地将一个slug
属性添加到文件名。
namespace Spatie\Sheets\PathParsers; use Spatie\Sheets\PathParser; class SlugParser implements PathParser { public function parse(string $path): array { return ['slug' => explode('.', $path)[0]]; } }
您可以使用path_parser
选项自定义集合的路径解析器。
// config/sheets.php return [ 'collections' => [ 'posts' => [ 'path_parser' => Spatie\Sheets\PathParsers\SlugWithDateParser::class, ], ], ];
以上,我们为posts
配置了路径解析器为SlugWithDateParser
,这允许您在文件名前添加日期。这对于时间敏感的内容(如博客)很有用。
posts/
2018-05-05.my-first-post.md
以上sheet将有两个属性:一个包含Illuminate\Support\Carbon
实例的date
,以及一个slug
my-first-post
。
您可以通过实现Spatie\Sheets\PathParser
接口来编写自己的路径解析器。路径解析器通过Laravel的容器实例化,因此如果需要,您可以通过__construct
方法注入其依赖。
内容解析器
内容解析器与路径解析器类似,但负责解析文件的正文。
默认内容解析器是MarkdownWithFrontMatterParser
,它提取front matter并将Markdown转换为HTML。
class MarkdownWithFrontMatterParser implements ContentParser { /** @var \League\CommonMark\CommonMarkConverter */ protected $commonMarkConverter; public function __construct(CommonMarkConverter $commonMarkConverter) { $this->commonMarkConverter = $commonMarkConverter; } public function parse(string $contents): array { $document = YamlFrontMatter::parse($contents); return array_merge( $document->matter(), ['contents' => $this->commonMarkConverter->convert($document->body())] ); } }
您可以使用content_parser
选项自定义集合的内容解析器。
// config/sheets.php return [ 'collections' => [ 'pages' => [ 'content_parser' => Spatie\Sheets\ContentParsers\MarkdownParser::class, ], ], ];
以上,我们为pages
配置了内容解析器为MarkdownParser
,它解析不带front matter的Markdown文件。
您可以通过实现Spatie\Sheets\ContentParser
接口来编写自己的内容解析器。内容解析器通过Laravel的容器实例化,因此如果需要,您可以通过__construct
方法注入其依赖。
扩展
集合中使用的文件扩展名。默认为md
。
默认集合
您可以在不指定集合的情况下直接对Sheets
实例调用get
或all
来查询默认集合。
// Return all sheets in the default collection Sheets::all();
您可以在sheets.config
中指定默认集合。如果没有指定默认集合,默认集合将是注册在collections
数组中的第一个集合。
这里默认集合将隐式设置为pages
return [ 'default_collection' => null, 'collections' => [ 'pages', ], ];
以下将默认集合设置为pages
return [ 'default_collection' => 'pages', 'collections' => [ 'posts', 'pages', ], ];
路由模型绑定
您可以为自定义路由解析逻辑注册,以便在控制器操作中立即注入Sheet
实例。
// app/Providers/RouteServiceProvider.php public function boot() { parent::boot(); Route::bind('sheet', function ($path) { return $this->app->make(Spatie\Sheets\Sheets::class) ->get($path) ?? abort(404); }); }
现在路由将解析任何sheet
参数为一个Sheet
对象。
Route::get('/{sheet}', 'SheetsController@show'); class SheetsController { public function show(Sheet $sheet) { return view('sheet', ['sheet' => $sheet]); } }
注册特定绑定以针对其他集合可能很有用。
use Spatie\Sheets\Sheets; Route::bind('post', function ($path) { return $this->app->make(Sheets::class) ->collection('posts') ->get($path) ?? abort(404); });
Laravel文档有一个关于路由模型绑定的整个部分。
使用子目录组织您的sheets
当您想使用(子)目录来组织sheets时,需要定义路由参数以接受所有字符。这样,sheets的完整相对路径将被发送到控制器。
Route::get('/', 'SheetsController@index')->where('sheet', '(.*)'); Route::get('{sheet}', 'SheetsController@show')->where('sheet', '(.*)');
测试
composer test
变更日志
有关最近更改的更多信息,请参阅变更日志。
贡献
有关详细信息,请参阅贡献指南。
安全
如果您发现与安全相关的错误,请通过security@spatie.be发送邮件,而不是使用问题跟踪器。
鸣谢
许可协议
MIT许可协议(MIT)。有关更多信息,请参阅许可文件。