spatie/sheets

将静态内容存储和检索在纯文本文件中

1.12.0 2024-03-02 05:56 UTC

README

Latest Version on Packagist Total Downloads

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,以及一个slugmy-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实例调用getall来查询默认集合。

// 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)。有关更多信息,请参阅许可文件