kiwilan / php-opds
创建电子书 OPDS 馈送的 PHP 包。
Requires
- php: ^8.1
- spatie/array-to-xml: ^3.2.3
Requires (Dev)
- kiwilan/php-xml-reader: ^1.0
- laravel/pint: ^1.2
- opis/json-schema: ^2.3
- pestphp/pest: ^1.20
- phpstan/phpstan: ^1.10
- spatie/ray: ^1.28
- symfony/console: ^6.3
This package is auto-updated.
Last update: 2024-09-08 05:24:45 UTC
README
PHP 包用于创建 OPDS 馈送 (Open Publication Distribution System) 以供电子书使用。
所有旧版本:0.9,1.0 和 1.1 均回退到 OPDS 1.2。
需求
php
v8.1 最低
关于
OPDS 类似于 RSS 馈送,但针对电子书进行了适配,它是一个在图书馆、书店、出版社和读者之间共享电子书的标准。由 Hadrien Gardeur 和 Leonard Richardson 开发。
此包是为了与 bookshelves-project/bookshelves
一起使用而创建的,这是一个开源的电子书 Web 应用程序。
注意
开放出版分发系统 (OPDS) 目录格式是基于 Atom 和 HTTP 的电子出版物聚合、分发、发现和获取的订阅格式。OPDS 目录使用现有的或新兴的开放标准和惯例,并优先考虑简单性。
开放出版分发系统规范由一个非正式的合作伙伴群体准备,该群体结合了互联网档案馆、O'Reilly 媒体、Feedbooks、OLPC 等。
来自 Wikipedia
有关 OPDS 和电子书的一些资源
- opds.io: OPDS 官方网站
- OPDS 馈送示例
- bookshelves.ink: 书架(使用
kiwilan/php-opds
的电子书 Web 应用程序) - gallica.bnf.fr: 加利亚(法国国家图书馆)
- cops-demo.slucas.fr: COPS(OPDS PHP 服务器)
- feedbooks.com: Feedbooks
- bookshelves.ink: 书架(使用
kiwilan/php-ebook
: 处理电子书的 PHP 包koreader/koreader
: Android、iOS、Kindle、Kobo、Linux、macOS、Windows 和更多设备上的电子书阅读器。如果你的电子书阅读器不能使用 OPDS 馈送,你可以在上面安装 KOReaderedrlab/thorium-reader
: 基于 Readium Desktop 工具包的跨平台桌面阅读应用程序。你可以使用它来使用 OPDS 馈送并阅读电子书
功能
- ⚛️ 生成 OPDS XML 和 JSON 馈送(导航馈送和获取馈送)
- 👌 支持 OPDS 1.2 和 2.0
- 🔖 带有分页选项
- 🔍 包含搜索页面,但不是搜索引擎
- 🌐 以 XML 或 JSON 格式处理浏览器响应的选项
路线图
- OPDS 1.2:支持高级获取馈送
- OPDS 2.0:支持
Facets
、Groups
、高级belongsTo
- 添加来自
anansi-project
的 OPDS 页面流扩展
安装
您可以通过Composer安装此软件包。
composer require kiwilan/php-opds
使用方法
您必须使用 Opds::make()
方法来创建OPDS实例,唯一参数是 config
用于设置OPDS配置,完全可选。默认响应为带有OPDS 1.2版本的XML,您可以使用 OpdsConfig::class
方法的 forceJson()
方法强制JSON响应,仅使用OPDS 2.0。使用 get()
方法,您可以使用 OpdsEngine
和 OpdsResponse
获取完整的 Opds
实例。
use Kiwilan\Opds\Opds; use Kiwilan\Opds\OpdsConfig; $opds = Opds::make(new OpdsConfig()) // OpdsConfig::class, optional ->title('My feed') ->feeds([...]) // OpdsEntryNavigation[]|OpdsEntryBook[]|OpdsEntryNavigation|OpdsEntryBook ->get() ;
在 Opds::class
中有不同信息。
关于OPDS实例的一些信息
use Kiwilan\Opds\Opds; $opds = Opds::make() ->title('My feed') ->feeds([...]) ->get() ; $opds->getConfig(); // OpdsConfig - Configuration used to create OPDS feed set into `make()` method $opds->getUrl(); // string|null - Current URL, generated automatically but can be overrided with `url()` method $opds->getTitle(); // string - Title of OPDS feed set with `title()` method $opds->getVersion(); // OpdsVersionEnum - OPDS version used, determined by query parameter `v` or `OpdsConfig::class` method `forceJson()` $opds->getQueryVersion(); // OpdsVersionEnum|null - Name of query parameter used to set OPDS version, default is `v` $opds->getUrlParts(); // array - URL parts, determined from `url` $opds->getQuery(); // array - Query parameters, determined from `url` $opds->getFeeds(); // array - Feeds set with `feeds()` method $opds->checkIfSearch(); // bool, default is false, set to true if `isSearch()` method is used
以及关于引擎和响应
use Kiwilan\Opds\Opds; $opds = Opds::make() ->title('My feed') ->feeds([...]) ->get() ; $opds->getEngine(); // OpdsEngine|null - Engine used to create OPDS feed, determined by OPDS version, can be `OpdsXmlEngine::class` or `OpdsJsonEngine::class` $opds->getOutput(); // OpdsOutputEnum|null - Output of response, useful for debug $opds->getPaginator(); // OpdsPaginator|OpdsPaginate|null - Paginator used to paginate feeds, if you use `paginate()` method $opds->getResponse(); // OpdsResponse|null - Response of OPDS feed, will use `OpdsEngine` to create a response
OPDS版本
您可以使用查询参数 version
动态设置它。您可以将此查询更改为 OpdsConfig::class
。
- 版本
1.2
可以使用?v=1.2
设置 - 版本
2.0
可以使用?v=2.0
设置
警告
如果您使用 OpdsConfig::class
方法的 forceJson()
将查询参数 v
设置为 1.2
,则查询参数将被忽略。
OPDS引擎
根据OPDS版本,引擎将您的源转换为OPDS。
您可以从 Opds::class
的 getEngine()
方法获取使用的引擎。属性 contents
包含源数组,OpdsEngine
允许使用 __toString()
方法转换为XML或JSON,输出取决于OPDS版本。
use Kiwilan\Opds\Opds; $opds = Opds::make() ->title('My feed') ->feeds([...]) ->get() ; $engine = $opds->getEngine(); // OpdsEngine $contents = $engine->getContents(); // array $output = $engine->__toString(); // string
OPDS响应
要构建OPDS源,您必须使用 get()
方法。它将返回一个包含 OpdsEngine
、OpdsResponse
和分页器的 Opds
实例。
use Kiwilan\Opds\Opds; $opds = Opds::make() ->title('My feed') ->feeds([...]) ->get() // `Opds` to fill `OpdsEngine`, `OpdsResponse` and paginator ;
要获取响应,您可以使用 Opds::class
的 getResponse()
方法。
use Kiwilan\Opds\Opds; $opds = Opds::make() ->title('My feed') ->feeds([...]) ->get() ; $response = $opds->getResponse(); // OpdsResponse $response->getStatus(); // int - Status code of response $response->isJson(); // bool - If response is JSON $response->isXml(); // bool - If response is XML $response->getHeaders(); // array - Headers of response $response->getContents(); // string - Contents of response
发送响应
注意
此方法完全可选,您可以直接将响应发送到浏览器。
您可以从 OpdsResponse
直接发送响应到浏览器以获取状态码、头信息和内容,或使用 Opds
和 OpdsResponse
中可用的 send()
方法。
- 您可以从
Opds
或OpdsResponse
使用send()
发送响应到浏览器(完全相同) - 在
send()
方法之前不需要调用get()
方法,send()
将自动调用get()
。
use Kiwilan\Opds\Opds; Opds::make() ->title('My feed') ->feeds([...]) ->send(); // XML or JSON response ;
如果您想获取 OpdsResponse
实例,可以在 send()
方法之前调用 get()
方法。
use Kiwilan\Opds\Opds; $opds = Opds::make() ->title('My feed') ->feeds([...]) ->get() ; // do something with `OpdsResponse` instance $opds->send(); // XML or JSON response
获取响应
use Kiwilan\Opds\Opds; $opds = Opds::make() ->title('My feed') ->feeds([...]) ->get(); $response = $opds->getResponse(); // OpdsResponse $response->send(); // XML or JSON response
注意
您可以使用 send()
方法的 exit
参数在发送响应后停止脚本。
OPDS配置
可以使用 OpdsConfig::class
设置OPDS配置。
<?php use Kiwilan\Opds\OpdsConfig; $config = new OpdsConfig( name: 'My OPDS Catalog', // Name of OPDS feed author: 'John Doe', // Author name authorUrl: 'https://example.com', // Author URL iconUrl: 'https://example.com/icon.png', // Icon URL startUrl: 'https://example.com/opds', // Start URL, will be included in top navigation searchUrl: 'https://example.com/opds/search', // Search URL, will be included in top navigation versionQuery: 'v', // query parameter for version paginationQuery: 'page', // query parameter for pagination updated: new DateTime(), // Last update of OPDS feed maxItemsPerPage: 16, // Max items per page, default is 16 forceJson: false, // To force JSON response as OPDS 2.0, default is false );
注意
您可以使用setter方法覆盖 OpdsConfig
。
OPDS分页
您可以使用 Opds
的 paginate()
方法使用分页,它将根据 OpdsConfig::class
的 maxItemsPerPage
属性生成分页。
- 如果您没有设置任何参数,它将生成分页
- 如果您设置了
OpdsPaginate
对象,它将根据它生成分页
use Kiwilan\Opds\Opds; $opds = Opds::make() ->title('My feed') ->feeds([...]) ->paginate() // will generate pagination ->get(); $opds->getPaginator(); // OpdsPaginator
您可以使用 OpdsPaginate::class
来处理手动分页
use Kiwilan\Opds\Opds; $opds = Opds::make(getConfig()) ->title('My feed') ->url('http://localhost:8080/opds?u=2') ->feeds([...]) ->paginate(new OpdsPaginate( currentPage: $page, totalItems: $total, firstUrl: 'http://localhost:8080/opds?f=1', lastUrl: 'http://localhost:8080/opds?l=42', previousUrl: 'http://localhost:8080/opds?p=1', nextUrl: 'http://localhost:8080/opds?n=3', )) // will generate pagination based on `OpdsPaginate` object ->get(); $opds->getPaginator(); // OpdsPaginate
OPDS条目
导航
您可以使用 OpdsEntryNavigation::class
创建导航条目
use Kiwilan\Opds\Entries\OpdsEntryNavigation; $entry = new OpdsEntryNavigation( id: 'authors', title: 'Authors', route: 'http://mylibrary.com/opds/authors', summary: 'Authors, 1 available', media: 'https://user-images.githubusercontent.com/48261459/201463225-0a5a084e-df15-4b11-b1d2-40fafd3555cf.svg', updated: new DateTime(), properties: [ 'numberOfItems' => 1, ], // to include extra properties (like numberOfItems for facets) relation: 'current', // to specify the relation to use (instead of `current`) );
提示
您可以使用setter方法覆盖 OpdsEntryNavigation
。
您可以使用 feeds()
方法将此条目添加到OPDS源中
use Kiwilan\Opds\Opds; $opds = Opds::make() ->feeds([$entry]) ->get();
书籍
您可以使用 OpdsEntryBook::class
创建书籍条目
警告
某些属性只能在OPDS 2.0中使用,请参阅 OPDS 2.0规范。
use Kiwilan\Opds\Entries\OpdsEntryBook; use Kiwilan\Opds\Entries\OpdsEntryBookAuthor; $entry = new OpdsEntryBook( id: 'the-clan-of-the-cave-bear-epub-en', title: 'The Clan of the Cave Bear', route: 'http://mylibrary.com/opds/books/the-clan-of-the-cave-bear-epub-en', summary: 'The Clan of the Cave Bear is an epic work of prehistoric fiction by Jean M. Auel.', content: 'The Clan of the Cave Bear is an epic work of prehistoric fiction by Jean M. Auel about prehistoric times. It is the first book in the Earth\'s Children book series which speculates on the possibilities of interactions between Neanderthal and modern Cro-Magnon humans.', media: 'https://user-images.githubusercontent.com/48261459/201463225-0a5a084e-df15-4b11-b1d2-40fafd3555cf.svg', updated: new DateTime(), download: 'http://mylibrary.com/api/download/books/the-clan-of-the-cave-bear-epub-en', mediaThumbnail: 'https://user-images.githubusercontent.com/48261459/201463225-0a5a084e-df15-4b11-b1d2-40fafd3555cf.svg', categories: ['category'], authors: [ new OpdsEntryBookAuthor( name: 'Jean M. Auel', uri: 'http://mylibrary.com/opds/authors/jean-m-auel', ), ], published: new DateTime(), volume: 1, serie: 'Earth\'s Children', language: 'English', identifier: 'urn:isbn:9780553381672', // to specify the actual identifier to use (instead of `urn:isbn:...`) translator: 'translator', publisher: 'publisher', );
提示
您可以使用setter方法覆盖 OpdsEntryBook
。
您可以使用 feeds()
方法将此条目添加到OPDS源中
$opds = Opds::make() ->feeds([$entry]) ->get();
搜索
此软件包不实现任何搜索引擎,您可以使用自己的搜索引擎并使用 Opds::class
创建OPDS源。
用于搜索的查询参数在规范中静态定义:
q
参数由 OPDS 1.2 使用query
参数由 OPDS 2.0 使用
提示
我推荐使用 Meilisearch 作为搜索引擎,它是一个功能强大且易于使用的搜索引擎。
这里有一个示例
use Kiwilan\Opds\Opds; use Kiwilan\Opds\Entries\OpdsEntryBook; $query = // get query from URL, `q` or `query` param $feeds = []; if ($query) { $results = []; // use your search engine here foreach ($results as $result) { $feeds[] = new OpdsEntryBook( title: $result->title, // ... ); } } $opds = Opds::make() ->title("Search for {$query}") ->isSearch() ->feeds($feeds) ->get();
更多用法
测试
composer test
变更日志
有关最近更改的更多信息,请参阅 变更日志。
鸣谢
- OPDS 创始人:为 OPDS 规范做出贡献
ewilan-riviere
:作者- 贡献者
spatie/array-to-xml
:将数组转换为 XMLspatie/package-skeleton-php
:PHP 包的骨架
许可
MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件。