vardumper/dom-orm

此包最新版本(v1.2.2)没有可用的许可证信息。

DOMDocument 对象关系映射(ORM)

v1.2.2 2024-09-15 21:04 UTC

README

这是一个小型Web项目的存储适配器。像任何其他ORM一样,它将实体(对象)存储到灵活的XML文件中。这是为想要开始一个无需启动数据库的小型项目的开发者准备的。

特性

  • 一种非常轻量级的将数据持久化到单个XML文件的方法。
  • 支持通过Flysystem(S3、Azure、Google Cloud、(S)FTP等)进行本地和外部文件存储。
  • 支持多对一、一对多和多对多关系。

完整文档

阅读文档

入门

composer require vardumper/dom-orm

默认情况下,XML文件存储在您的本地文件系统中的项目根目录下的storage/data.xml中。您可以通过更改Flysystem适配器并配置dom-orm使用它来更改存储位置,如下所示

// config/dom-orm.php
<?php return [
  'dom-orm' => [
    'flysystem' => new LocalAdapter(__DIR__ . '/storage'),
    'filename' => 'data.xml',
  ],
];

基本用法

实体

通过向实体类添加PHP8属性,DOM ORM知道如何持久化它。

// src/Entity/Tag.php
use DOM\ORM\Entity\AbstractEntity;
use DOM\ORM\Mapping as ORM;

#[ORM\Item(entityType: 'tag')]
class Tag extends AbstractEntity
{
    public function __construct(
        #[ORM\Fragment]
        private readonly string $name,
    ) {
        parent::__construct();
    }
}

持久化

可以在控制器或服务中使用EntityManagerTrait将实体持久化到XML文件。

// src/Service/SomeService.php
class SomeService {
    use DOM\ORM\Traits\EntityManagerTrait;
    ...
    public function addTag(string $name) {
      $tag = new Tag($name);
      $this->persist($tag);
    }
}

当您想更新现有的实体时,也可以使用persist方法。

// src/Service/SomeService.php
class SomeService {
    use DOM\ORM\Traits\EntityManagerTrait;
    ...
    public function updateTag(string $id, string $name) {
      $tag = (new EntityRepository(Tag::class))->find($id);
      $tag->setName($name);
      $this->persist($tag);
    }
}

当您想删除现有的实体时,可以使用remove方法。

// src/Service/SomeService.php
class SomeService {
    use DOM\ORM\Traits\EntityManagerTrait;
    ...
    public function removeTag(string $id) {
      (new EntityRepository(Tag::class))->remove($id);
    }
}

序列化

在持久化实体时,DOM ORM自动生成一个UID并为实体添加创建日期。内置的正常化器和编码器将对象转换成标准化的XML格式并保存。

<!-- storage/data.xml -->
<data>
  <item type="tag" id="e34cbf80edaf490aa39113254b6cdfa9">
    <fragment name="name"><![CDATA[Tagname]]></fragment>
    <fragment name="createdAt"><![CDATA[2024-06-17T06:30:37+00:00]]></fragment>
  </item>
  ...
</data>

查询数据

就像将PHP对象持久化到XML格式一样,查询数据同样简单。当您查询数据时,内部使用XPath来查找元素,然后将结果DOMNodeList映射回其实体类对象。

使用实体仓库查询数据

通过使用EntityRepository类,您可以以面向对象的方式查询数据,始终检索实体对象实例。

$tagRepository = new EntityRepository(Tag::class);
$tag = $tagRepository->findOneBy(['name' => 'Tagname']); // returns a single Tag object
$tag = $tagRepository->find('fec69a494c3145f89af03ae3b3702e19'); // return a single Tag object
$tags = $tagRepository->findAll(); // returns a Collection of Tag objects
$tags = $tagRepository->findBy(['name' => 'Tagname']); // returns a Collection of Tag objects

使用DOMXPath查询数据

$xml = (new DOM\ORM\Storage\StorageService())->read();
$dom = (new DOMDocument())->loadXML($xml);
$xpath = new DOMXPath($dom);
$tags = $xpath->query('//item[@type="tag"]'); // eg: retrieve all tags at any depth
$tag = $xpath->query('//item[@type="tag" and @id="fec69a494c3145f89af03ae3b3702e19"]'); // eg: retrieve a single tag with a specific ID

使用DOMDocument查询数据

$xml = (new DOM\ORM\Storage\StorageService())->read();
$dom = (new DOMDocument())->loadXML($xml);
$entities = $dom->getElementsByTagName('item'); // returns a DOMNodeList of all entities

模板

Twig

最简单的方法是查询实体并将它们传递给您的Twig模板

$twig->render('index.twig', [
    'title' => 'Hello there!',
    'tag' => (new EntityRepository(Tag::class))->find('fec69a494c3145f89af03ae3b3702e19'),
]);

或者,您可以直接解码一些DOM元素并将数组传递给Twig模板(不实例化对象)

use EntityManagerTrait;
$serializer = $this->getSerializer();
$item = $serializer->decode($dom->getELementsByTagName('item')->item(0)); // example: decode the first item into an array

echo $twig->render('index.twig', [
    'title' => 'Hello there!',
    'item' => $item,
]);

XSLT

您可以使用XML数据通过XSLT将其转换为HTML。

$xml = (new DOM\ORM\Storage\StorageService())->read();
$dom = (new DOMDocument())->loadXML($xml);
$xslt = (new XSLTProcessor())->importStylesheet(DOMDocument::load('path/to/stylesheet.xsl'));

echo $xslt->transformToXML($dom);

路线图

  • 通过哈希表添加多对多关系的支持。
  • 向实体仓库模式添加排序/排序功能。
  • 通过提供一个GraphQL端点,您可以以更灵活、无头的方式与DOM-ORM数据库交互。
  • 添加对迁移(或更准确的说是清理)的支持,以便从XML文件中删除已删除的片段。
  • 添加对加密XML文件部分或整个文件的支持,以提高安全性。