JamesMoss/flywheel

轻量级、扁平文件、文档数据库

0.6.0 2020-01-13 11:39 UTC

This package is not auto-updated.

Last update: 2024-09-14 15:06:06 UTC


README

Build Status Scrutinizer Quality Score Code Coverage

Flywheel是一个PHP的扁平文件、无服务器文档数据库,可以存储JSON、YAML或Markdown格式的数据。

通常MySQL对于小型网站或博客安装来说可能是多余的。尽管它在很多托管套餐中作为标准存在,但它仍然需要几个手动步骤,包括配置、用户和数据库的创建等。

此外,存储在MySQL数据库中的内容无法(或者至少非常困难)使用版本控制软件跟踪。这使得在团队之间共享网站或应用程序变得困难,需要每个人都能够访问主数据库或自己的副本。当应用程序在预发布服务器上设置并且用户的更改必须反映在开发人员的本地副本中时,也会出现复杂情况。你可能在过去遇到过这个问题,而且情况一团糟。

Flywheel希望通过为开发者提供类似NoSQL数据库的数据存储方式,但没有任何外部依赖,从而启用新一代PHP应用程序和库。文档(本质上关联数组)可以保存和检索,排序和限制。

目前Flywheel处于开发阶段,尚未准备好投入生产。你可能发现从Flywheel的一个版本创建的文档现在无法由另一个版本加载。随着我们越来越接近v1版本,这种情况发生的可能性越来越小。

Flywheel是具有观点的软件。以下是一些假设:

  • 简单数据结构最好。
  • 你不会存储成千上万的文档。

需求

  • PHP 5.3+
  • Composer

可选

  • APC / APCu - 在内存中缓存文档和查询,以实现巨大的性能提升。

安装

使用Composer安装flywheel包。包详情可在Packagist.org上找到。

在项目目录中运行composer require jamesmoss/flywheel以安装Flywheel包。

使用

$config = new \JamesMoss\Flywheel\Config('path/to/writable/directory');

// The repository is responsible for storing, updating and deleting documents.
$repo = new \JamesMoss\Flywheel\Repository('posts', $config);

// Storing a new document
$post = new \JamesMoss\Flywheel\Document(array(
    'title'     => 'An introduction to Flywheel',
    'dateAdded' => new \DateTime('2013-10-10'),
    'body'      => 'A lightweight, flat-file, document database for PHP...',
    'wordCount' => 7,
    'author'    => 'James',
    'published' => true,
    'translations' => array(
    	'de' => 'Eine Einführung in Flywheel',
    	'it' => 'Una introduzione a Flywheel',
    ),
));

echo $post->title; // An introduction to Flywheel
echo $post->wordCount; // 7

$id = $repo->store($post);

// A unique ID is automatically generated for you if you don't specify your own when storing.
// The generated ID consists of upper/lowercase letters and numbers so is URL safe.
echo $id; // Czk6SPu4X
echo $post->getId(); // Czk6SPu4X

// If you set your own then it cannot contain the following characters: / ? * : ; { } \ or newline
$post->setId('a-review-of-2013');

// Retrieving documents
$posts = $repo->query()
    ->where('dateAdded', '>', new \DateTime('2013-11-18'))
    ->andWhere('published', '==', true)
    ->orderBy('wordCount DESC')
    ->limit(10, 5)
    ->execute();

echo count($posts); // 5 the number of documents returned in this result
echo $posts->total() // 33 the number of documents if no limit was applied. Useful for pagination.

foreach($posts as $post) {
    echo $post->title;
}

// Pull one document out of the repo by ID
$post = $repo->findById('a-quick-guide-to-flywheel');

// Updating documents
$post->title = 'How to update documents';

// Updates the document (only if it already exists)
$repo->update($post);


// Deleting documents - you can pass a document or it's ID.
$repo->delete($post);
// or you can do the following
$repo->delete('Czk6SPu4X');

查询

您可以使用查询上的whereandWhereorWhere方法来过滤返回的文档数量。

// Find posts with more than 100 words written by James
$posts = $repo->query()
    ->where('wordCount', '>', 100)
    ->andWhere('author', '==', 'James')
    ->execute();

// The special __id field name can be used to query by the document's ID.
// Find all posts where the ID is either 1 or 7 or 8.
$posts = $repo->query()
    ->where('__id', '==', 1)
    ->orWhere('__id', '==', 7)
    ->orWhere('__id', '==', 8)
    ->execute();

// A neater, alternative way of doing the above query
$posts = $repo->query()
    ->where('__id', 'IN', array(1, 7, 8))
    ->execute();

// You can query by sub keys within a document too. The following finds all
// documents which have a German translation
$posts = $repo->query()
    ->where('translations.de', '!=', false)
    ->execute();

您可以将匿名函数传递给whereandWhereorWhere方法以分组谓词。匿名函数接受一个参数,该参数是JamesMoss\Flywheel\Predicate的实例,并具有相同的方法。您可以嵌套尽可能多次。

$posts = $repo->query()
    ->where('wordCount', '>', 100)
    ->andWhere(function($query) {
    	$query->where('author', '==', 'Hugo')
    	$query->orWhere('dateAdded', '>', new \DateTime('2014-05-04'))
    })
    ->execute();

重要尚未实现传统的逻辑运算符优先级。如果您混合了ANDOR,则可能不会看到预期的行为。目前,无论定义的顺序如何,都会先处理AND谓词。如果混合了ANDOR,则始终显式使用匿名函数将您的谓词分组在一起。

可用的比较运算符列表如下:

  • == 等于
  • === 严格等于
  • != 不等于
  • !== 严格不等于
  • > 大于
  • >= 大于等于
  • < 小于
  • <= 小于等于
  • IN 检查值是否在集合中。等式检查不是严格的。

您可以使用orderBy对返回的结果进行排序。

// A simple example
$posts = $repo->query()
    ->orderBy('wordCount ASC')
    ->execute();

// You can use sub keys too
$posts = $repo->query()
    ->orderBy('translations.de DESC')
    ->execute();
    
// It's possible to sort on multiple fields by passing in an array to orderBy
$posts = $repo->query()
    ->orderBy(['name ASC', 'age DESC'])
    ->execute();

// Use the special __id field name to sort by the document's ID
$posts = $repo->query()
    ->orderBy('__id')
    ->execute();

您可以使用limit来限制从仓库返回的文档数量。与传统的数据库类似,也支持偏移量。

// Get the last 5 blog posts
$posts = $repo->query()
	->where('published', '==', 'true')
    ->orderBy('dateAdded DESC')
    ->limit(5)
    ->execute();

 // Get 25 blog posts offset by 100 from the start.
 $posts = $repo->query()
 	->where('published', '==', 'true')
    ->orderBy('dateAdded DESC')
    ->limit(25, 100)
    ->execute();

配置选项

  • formatter。请参阅本说明文件中的格式部分。默认为JamesMoss\Flywheel\Formatter\JSON实例。
  • query_class。从Repository::query()返回的类的名称。默认情况下,Flywheel会检测您是否安装了APC或APCu,如果适用,则使用CachedQuery类,否则只使用Query
  • document_class。当从文件系统中填充文档时要使用的类的名称。必须实现JamesMoss\Flywheel\DocumentInterface。默认为JamesMoss\Flywheel\Document

格式

默认情况下,文档以JSON格式保存和解析,因为它速度快,并且编码/解码已内置到PHP中。您还可以选择其他两种序列化格式:YAML和Markdown(带有YAML元数据)。

您可以在初始化时通过传递到Config中来选择格式。

$config = new Config('/path/to/writable/directory', array(
    'formatter' => new \JamesMoss\Flywheel\Formatter\YAML,
))

以下是一些可用的格式化类。

  • JamesMoss\Flywheel\Formatter\JSON - 如果使用PHP 5.4+,将尝试美化输出。文件扩展名为json
  • JamesMoss\Flywheel\Formatter\YAML - 使用yaml文件扩展名,而不是yml
  • JamesMoss\Flywheel\Formatter\Markdown - 构造函数中可选的参数指定了结果Document中的主字段名称(默认为body)。文件扩展名为md。Markdown不会转换为HTML,这取决于您。

重要 如果您在Composer中使用--no-dev标志时使用YAMLMarkdown格式化程序,则需要手动将mustangostang\spyc添加到您的composer.json中。Flywheel试图将其依赖项保持在最低限度。

如果您编写自己的格式化程序,它必须实现JamesMoss\Flywheel\Formatter\Format

待办事项

  • Repository::findAll周围更多缓存。
  • 索引。
  • HHVM支持。
  • 抽象文件系统,类似于Gaufrette或Symfony的文件系统组件?
  • 事件系统。
  • 将日期重新水化为日期时间对象的功能?
  • 更多的序列化格式?PHP序列化,PHP原始格式?
  • 单元测试中的更多模拟。
  • 简单的单对单和多对一连接。
  • 在查询中实现正确的逻辑运算符优先级。
  • 添加注册自己的比较运算符的能力。

运行测试

目前有很好的测试覆盖率。如果您想自己运行测试,请使用以下命令

$ composer install
$ phpunit

贡献

如果您发现了我遗漏的地方,请将此仓库进行分叉,创建一个新的分支并提交一个pull request。请确保您添加的功能都有单元测试覆盖,并且不要破坏其他测试。