mrcnpdlk / pixie
轻量级、快速查询构建器,基于Laravel Eloquent,但开销更小。
Requires
- php: >=7.2
- ext-pdo: *
Requires (Dev)
- ext-pdo_sqlite: *
- friendsofphp/php-cs-fixer: ^2
- jangregor/phpstan-prophecy: ^0
- mockery/mockery: ^1
- phpstan/phpstan: ^0
- phpunit/phpunit: ^6.0
Suggests
- ext-pdo_sqlite: Add extension for SQLite support
This package is auto-updated.
Last update: 2024-09-19 21:54:44 UTC
README
A lightweight, expressive, framework agnostic query builder for PHP it can also be referred as a Database Abstraction Layer. Pixie supports MySQL, SQLite and PostgreSQL will handle all your query sanitization, table alias, unions among many other things, with a unified API.
The syntax is similar to Laravel's query builder "Eloquent", but with less overhead.
This library is stable, maintained and are used by sites around the world (check the credits).
要求
- PHP版本7.1或更高版本需要用于pixie版本4.x及以上(4.x之前的版本可在此处找到)。
- PDO扩展已启用。
功能
- 改进的子查询。
- 为表定义自定义前缀/别名(prefix.
table
)。 - 支持不定义表或删除已定义的表。
- 在
where
语句中更好地处理Raw
对象。 - 联合查询。
- 更好的连接处理。
- 性能优化。
- 大量错误修复。
- 更多...
包括所有原始功能,如
- 查询事件
- 嵌套标准
- 子查询
- 嵌套查询
- 多个数据库连接。
最重要的是,此项目在许多实时网站上使用且得到维护。
示例
// Make sure you have Composer's autoload file included require 'vendor/autoload.php'; // Create a connection, once only. $config = [ // Name of database driver or IConnectionAdapter class 'driver' => 'mysql', 'host' => 'localhost', 'database' => 'your-database', 'username' => 'root', 'password' => 'your-password', // Optional 'charset' => 'utf8', // Optional 'collation' => 'utf8_unicode_ci', // Table prefix, optional 'prefix' => 'cb_', // PDO constructor options, optional 'options' => [ PDO::ATTR_TIMEOUT => 5, PDO::ATTR_EMULATE_PREPARES => false, ], ]; $queryBuilder = (new \Pecee\Pixie\Connection('mysql', $config))->getQueryBuilder();
简单查询
获取id为3
的用户。如果没有匹配项,则返回null
。
$user = $queryBuilder ->table('users') ->find(3);
完整查询
获取所有有蓝色或红色头发的用户。
$users = $queryBuilder ->table('users') ->where('hair_color', '=', 'blue') ->orWhere('hair_color', '=', 'red') ->get();
目录
- 安装
- 反馈和开发
- 连接到数据库
- 选择
- Where
- 分组-排序
- Having
- Limit和Offset
- 连接
- 联合
- 原始查询
- 插入
- 更新
- 删除
- 事务
- 获取原始查询
- 子查询和嵌套查询
- 获取PDO实例
- 将结果作为指定类的对象获取
- 高级
- 查询事件
- 异常
- 鸣谢
安装
Pixie使用Composer简化操作。
学习如何使用Composer并将其添加到require部分(在您的composer.json中)
composer install pecee/pixie
反馈和开发
如果您缺少某个功能、遇到问题或者有想法或反馈希望我们听到,请随时创建一个问题。
问题指南
-
在创建新问题时,请尽可能详细地描述。这有助于他人更容易理解和解决您的问题。例如:如果您遇到问题,应在描述中提供重现错误的必要步骤。
-
我们乐于听取对库的任何想法或反馈。
贡献和开发指南
-
请尽量遵循PSR-2编码风格指南。
-
请将您的拉取请求创建到与您想要更改的版本号匹配的开发基础库中。例如,当推送更改到版本3时,拉取请求应使用
v3-development
基础/分支。 -
为您的提交创建详细的描述,因为它们将被用于新版本的变更日志中。
-
在更改现有功能时,请确保单元测试运行正常。
-
在添加新内容时,请记得为该功能添加新的单元测试。
连接到数据库
Pixie支持三种数据库驱动程序:MySQL、SQLite和PostgreSQL。您可以在创建新连接时指定驱动程序及其相关配置。您还可以创建多个连接,但一次只能使用一个别名。
// Make sure you have Composer's autoload file included require 'vendor/autoload.php'; $config = [ 'driver' => 'mysql', 'host' => 'localhost', 'database' => 'your-database', 'username' => 'root', 'password' => 'your-password', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', ]; // Creates new connection $connection = new \Pecee\Pixie\Connection('mysql', $config); // Get the query-builder object which will initialize the database connection $queryBuilder = $connection->getQueryBuilder(); // Run query $person = $queryBuilder ->table('persons') ->where('name', '=', 'Bobby') ->first();
这里的$connection
是可选的,如果没有提供,它将始终与第一个连接关联,但在您有多个数据库连接时可能很有用。
注意:调用getQueryBuilder
方法将自动建立数据库连接(如果尚未建立),如果您想直接从Connection
类中访问Pdo
实例,请确保调用$connection->connect();
以建立数据库连接。
SQLite和PostgreSQL配置示例
以下示例用于sqlite数据库。
$queryBuilder = new \Pecee\Pixie\Connection('sqlite', [ 'driver' => 'sqlite', 'database' => 'your-file.sqlite', 'prefix' => 'cb_', ]);
以下示例用于pgsql数据库。
$queryBuilder = new \Pecee\Pixie\Connection('pgsql', [ 'driver' => 'pgsql', 'host' => 'localhost', 'database' => 'your-database', 'username' => 'postgres', 'password' => 'your-password', 'charset' => 'utf8', 'prefix' => 'cb_', 'schema' => 'public', ]);
选择
建议在每次查询之前使用table()
方法,除非是原始query()
查询。要从多个表中选择,只需传递一个数组即可。
但这不是必需的。
$queryBuilder->table(array('mytable1', 'mytable2'));
表别名
您可以通过使用以下方式轻松设置表别名:
$queryBuilder ->table(['table1' => 'foo1']) ->join('table2', 'table2.person_id', '=', 'foo1.id');
您可以通过使用以下方式随时更改别名:
$queryBuilder->alias('foo1', 'table1'); // Simplified way... $queryBuilder->table('table1')->alias('foo1');
输出
SELECT * FROM `table1` AS `foo1` INNER JOIN `cb_table2` ON `cb_table2`.`person_id` = `cb_foo1`.`id`
注意:您可以通过调用没有参数的table
方法(如$queryBuilder->table()
)始终从查询中删除一个表。
轻松获取
以下查询返回id = 3的(第一)行,如果没有行则返回null。
$row = $queryBuilder ->table('my_table') ->find(3);
访问您的行,如echo $row->name
。如果您的字段名不是id
,则将字段名作为第二个参数传递,如$queryBuilder->table('my_table')->find(3, 'person_id');
。
以下查询返回所有name = 'Sana'的行,如果没有行则返回null。
$result = $queryBuilder ->table('my_table') ->findAll('name', 'Sana');
多个选择
$queryBuilder ->select( [ 'mytable.myfield1', 'mytable.myfield2', 'another_table.myfield3' ] );
多次使用select方法(如select('a')>select('b')
)也会选择a
和b
。如果要在PHP if
中进行条件选择,这可能会很有用。
选择不同的
$queryBuilder->selectDistinct(array('mytable.myfield1', 'mytable.myfield2'));
从查询中选择
您可以通过使用以下方式轻松地从另一个查询中选择项:
$subQuery = $queryBuilder->table('person'); $builder = $queryBuilder->table($queryBuilder->subQuery($subQuery))->where('id', '=', 2);
将产生以下输出
SELECT * FROM (SELECT * FROM `person`) WHERE `id` = 2
选择单个字段
$queryBuilder->table('my_table')->select('*');
选择多个字段
$queryBuilder->table('my_table')->select(array('field1', 'field2'));
获取所有
返回一个数组。
$results = $queryBuilder ->table('my_table') ->where('name', '=', 'Sana') ->get();
您可以通过以下方式遍历它:
foreach ($results as $row) { echo $row->name; }
获取第一行
$row = $queryBuilder ->table('my_table') ->where('name', '=', 'Sana') ->first();
返回第一行,如果没有记录则返回null。使用此方法,您还可以确保记录是否存在。访问这些记录,如echo $row->name
。
聚合方法
获取行数
这将返回结果中所有行的总数。
默认行为将计算*
(所有)字段。您可以通过更改field
参数来指定自定义字段。
$queryBuilder ->table('my_table') ->where('name', '=', 'Sana') ->count();
获取总和
这将返回结果中所有行的字段总和。
$queryBuilder ->table('my_table') ->where('name', '=', 'Sana') ->sum('views');
获取平均值
这将返回结果中所有行的字段平均值。
$queryBuilder ->table('my_table') ->where('name', '=', 'Sana') ->average('views');
获取最小值
这将返回结果中所有行的字段最小值。
$queryBuilder ->table('my_table') ->where('name', '=', 'Sana') ->min('views');
获取最大值
这将返回结果中所有行的字段平均值。
$queryBuilder ->table('my_table') ->where('name', '=', 'Sana') ->max('views');
使用子查询选择
// Creates the first sub-query $subQuery1 = $queryBuilder ->table('mail') ->select( $queryBuilder->raw('COUNT(*)') ); // Create the second sub-query $subQuery2 = $queryBuilder ->table('event_message') ->select( $queryBuilder->raw('COUNT(*)') ); // Executes the query which uses the subqueries as fields $count = $queryBuilder ->select( $queryBuilder->subQuery($subQuery1, 'row1'), $queryBuilder->subQuery($subQuery2, 'row2') ) ->first();
上述示例将输出如下SQL查询:
SELECT (SELECT COUNT(*) FROM `cb_mail`) AS row1, (SELECT COUNT(*) FROM `cb_event_message`) AS row2 LIMIT 1
您也可以轻松地在where
语句中创建子查询。
$queryBuilder->where($queryBuilder->subQuery($subQuery), '!=', 'value');
Where
基本语法是 (字段名, 操作符, 值)
,如果提供两个参数,则默认使用 =
操作符。因此,where('name', 'usman')
和 where('name', '=', 'usman')
是一样的。
$queryBuilder ->table('my_table') ->where('name', '=', 'usman') ->whereNot('age', '>', 25) ->orWhere('type', '=', 'admin') ->orWhereNot('description', 'LIKE', '%query%');
Where in
$queryBuilder ->table('my_table') ->whereIn('name', array('usman', 'sana')) ->orWhereIn('name', array('heera', 'dalim')); $queryBuilder ->table('my_table') ->whereNotIn('name', array('heera', 'dalim')) ->orWhereNotIn('name', array('usman', 'sana'));
Where between
$queryBuilder ->table('my_table') ->whereBetween('id', 10, 100) ->orWhereBetween('status', 5, 8);
Where null
$queryBuilder ->table('my_table') ->whereNull('modified') ->orWhereNull('field2') ->whereNotNull('field3') ->orWhereNotNull('field4');
分组Where
有时查询会变得复杂,需要分组条件,例如 WHERE age = 10 and (name like '%usman%' or description LIKE '%usman%')
。
Pixie 允许您这样做,您可以嵌套任意多个闭包,如下所示。
$queryBuilder ->table('my_table') ->where('my_table.age', 10) ->where(function(QueryBuilderHandler $qb) { $qb->where('name', 'LIKE', '%pecee%'); // You can provide a closure on these wheres too, to nest further. $qb->orWhere('description', 'LIKE', '%usman%'); });
分组-排序
$query = $queryBuilder ->table('my_table') ->groupBy('age') ->orderBy('created_at', 'ASC');
多重分组
$queryBuilder ->groupBy(array('mytable.myfield1', 'mytable.myfield2', 'another_table.myfield3')); ->orderBy(array('mytable.myfield1', 'mytable.myfield2', 'another_table.myfield3'));
多次使用 groupBy()
或 orderBy()
方法,如 groupBy('a')->groupBy('b')
,也会先按 a
分组,然后按 b
分组。如果您想在 PHP if
中进行条件分组,这可能会很有用。同样适用于 orderBy()
。
Having
$queryBuilder ->having('total_count', '>', 2) ->orHaving('type', '=', 'admin');
Limit和Offset
$queryBuilder ->limit(30); ->offset(10);
连接
$queryBuilder ->table('my_table') ->join('another_table', 'another_table.person_id', '=', 'my_table.id')
可用方法:
- join() 或 innerJoin
- leftJoin()
- rightJoin()
如果您需要 FULL OUTER
连接或其他连接,只需将它们作为 join
方法的第五个参数传递。
$queryBuilder ->join('another_table', 'another_table.person_id', '=', 'my_table.id', 'FULL OUTER')
Join USING语法
JOIN USING
语法允许您轻松地将两个相同的标识符映射到同一个,这在大型查询中可能很有帮助。
示例
$queryBuilder ->table('user') ->join('user_data', 'user_data.user_id', '=', 'user.user_id');
可以简化为
$queryBuilder ->table('user') ->joinUsing('user_data', 'user_id');
多个连接标准
如果您需要多个条件来连接表,则将闭包作为第二个参数传递。
$queryBuilder ->join('another_table', function($table) { $table ->on('another_table.person_id', '=', 'my_table.id') ->on('another_table.person_id2', '=', 'my_table.id2') ->orOn('another_table.age', '>', $queryBuilder->raw(1)); })
联合
您可以通过在 QueryBuilderHandler
上调用 union
方法轻松创建联合。
示例
$firstQuery = $queryBuilder ->table('people') ->whereNull('email'); $secondQuery = $queryBuilder ->table('people') ->where('hair_color', '=', 'green') ->union($firstQuery); $thirdQuery = $queryBuilder ->table('people') ->where('gender', '=', 'male') ->union($secondQuery); $items = $thirdQuery->get();
上面的示例将创建一个类似于以下 SQL 语句
( SELECT * FROM `cb_people` WHERE `gender` = 'male' ) UNION ( SELECT * FROM `cb_people` WHERE `email` IS NULL ) UNION ( SELECT * FROM `cb_people` WHERE `hair_color` = 'green' )
原始查询
如果您需要执行原始查询,则始终可以这样做。
$query = $queryBuilder->query('SELECT * FROM persons WHERE age = 12'); $kids = $query->get();
您还可以传递自定义绑定
$queryBuilder ->query('SELECT * FROM persons WHERE age = ? AND name = ?', array(10, 'usman'));
原始表达式
当您使用 raw()
方法包装表达式时,Pixie 不会尝试对其进行清理。
$queryBuilder ->table('my_table') ->select($queryBuilder->raw('count(cb_my_table.id) as tot')) ->where('value', '=', 'Ifrah') ->where($queryBuilder->raw('DATE(?)', 'now'))
注意:通过 query()
方法运行的查询在您通过绑定传递所有值之前都不会进行清理。通过 raw()
方法运行的查询也不会进行清理,您必须自己进行。当然,这些也不会添加表前缀,但您可以使用 addTablePrefix()
方法。
插入
$data = [ 'name' => 'Sana', 'description' => 'Blah' ]; $insertId = $queryBuilder ->table('my_table') ->insert($data);
insert()
方法返回插入 ID。
批量插入
$data = [ array( 'name' => 'Sana', 'description' => 'Blah' ), array( 'name' => 'Usman', 'description' => 'Blah' ), ]; $insertIds = $queryBuilder ->table('my_table') ->insert($data);
在批量插入的情况下,它将返回一个包含插入 ID 的数组。
带有ON DUPLICATE KEY语句的插入
$data = [ 'name' => 'Sana', 'counter' => 1 ]; $dataUpdate = [ 'name' => 'Sana', 'counter' => 2 ]; $insertId = $queryBuilder ->table('my_table') ->onDuplicateKeyUpdate($dataUpdate) ->insert($data);
更新
$data = [ 'name' => 'Sana', 'description' => 'Blah' ]; $queryBuilder ->table('my_table') ->where('id', 5) ->update($data);
将名称字段更新为 Sana,描述字段更新为 Blah,其中 id = 5。
删除
$queryBuilder ->table('my_table') ->where('id', '>', 5) ->delete();
将删除所有 id 大于 5 的行。
事务
Pixie 具有运行数据库 "事务" 的能力,在这种情况下,所有数据库更改在提交之前都不会保存。这样,如果发生错误或与预期不同,数据库更改就不会保存,也不会进行任何更改。
这是一个基本的事务示例
$queryBuilder ->transaction(function (Transaction $transaction) { $transaction ->table('my_table') ->insert(array( 'name' => 'Test', 'url' => 'example.com' ); $transaction ->table('my_table') ->insert(array( 'name' => 'Test2', 'url' => 'example.com' )); });
如果这会导致任何错误(例如重复名称或其他此类错误),则数据库中都不会显示任何数据集。如果没有错误,则更改将成功保存。
如果您希望手动提交或回滚更改,则可以使用相应的 commit()
和 rollback()
方法。
$queryBuilder ->transaction(function (Transaction $transaction) { $transaction ->table('my_table') ->insert($data); // Commit changes (data will be saved) $transaction->commit(); // Rollback changes (data would be rejected) $transaction->rollback(); } );
在插入多个记录时,会自动使用事务。例如
$queryBuilder->table('people')->insert([ [ 'name' => 'Simon', 'age' => 12, 'awesome' => true, 'nickname' => 'ponylover94', ], [ 'name' => 'Peter', 'age' => 40, 'awesome' => false, 'nickname' => null, ], [ 'name' => 'Bobby', 'age' => 20, 'awesome' => true, 'nickname' => 'peter', ], ]);
获取原始查询
有时您可能需要获取查询字符串,这是可能的。
$queryHandler = $queryBuilder ->table('my_table') ->where('id', '=', 3) ->getQuery();
getQuery()
将返回一个 QueryBuilderHandler
对象。
您可以使用它来获取 SQL、绑定或原始 SQL。
$queryHandler->getSql();
调用 getSql()
将返回未经处理的 SQL 查询。
SELECT * FROM my_table where `id` = ?
您可以通过调用 getBindings()
方法轻松获取查询上的任何绑定。
示例
$queryHandler->getBindings();
您还可以通过调用 getRawSql()
方法直接获取原始 SQL 查询。
示例
$queryHandler->getRawSql();
调用 getRawSql()
方法将返回一个包含绑定如这样的查询。
SELECT * FROM my_table where `id` = 3
从最后执行的查询中获取QueryObject
您还可以从最后一个执行的查询中检索查询对象。
示例
$queryString = $queryBuilder->getLastQuery()->getRawSql();
子查询和嵌套查询
很少但您可能需要进行子查询或嵌套查询。Pixie 足够强大,可以为您这样做。您可以创建不同的查询对象并使用 $queryBuilder->subQuery()
方法。
$subQuery = $queryBuilder ->table('person_details') ->select('details') ->where('person_id', '=', 3); $query = $queryBuilder ->table('my_table') ->select('my_table.*') ->select( $queryBuilder->subQuery($subQuery, 'table_alias1') ); $nestedQuery = $queryBuilder ->table( $queryBuilder->subQuery($query, 'table_alias2') ) ->select('*'); // Execute query $result = $nestedQuery->get();
这将生成如下查询
SELECT * FROM (SELECT `cb_my_table`.*, (SELECT `details` FROM `cb_person_details` WHERE `person_id` = 3) AS table_alias1 FROM `cb_my_table`) AS table_alias2
注意
Pixie 不为子查询和嵌套查询使用绑定。它使用 PDO 的 quote()
方法引用值。
获取PDO实例
如果您需要获取 \PDO
实例,可以通过调用以下方法轻松获取:
$queryBuilder->pdo();
如果您想获取 Connection
对象,可以这样做:
$connection = $queryBuilder->getConnection();
将结果作为指定类的对象获取
简单调用查询的 asObject
方法。
$queryBuilder ->table('my_table') ->asObject('SomeClass', array('ctor', 'args')) ->first();
此外,您还可以通过调用 setFetchMode
方法来微调获取模式。
$queryBuilder ->table('my_table') ->setFetchMode(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE) ->get();
高级
启用查询覆盖
如果启用,从 select 等调用将覆盖查询中之前调用存在的任何值。
您可以通过在 QueryBuilderHandler
对象上调用 setOverwriteEnabled
方法来启用或禁用查询覆盖。
该功能默认是禁用的。
示例
$queryBuilder ->setOverwriteEnabled(true);
如果您希望此功能默认在所有 QueryBuilderHandler
对象上启用,可以将以下设置添加到连接配置中:
$adapterConfig = [ 'query_overwriting' => false, ];
查询事件
Pixie 随附强大的查询事件,以增强您的应用程序。这些事件类似于数据库触发器,您可以在事件发生时执行某些操作,例如,您可以挂钩表的 after-delete
事件,并从另一个表中删除相关数据。
可用事件
注册事件
您可以通过使用 QueryBuilderHandler
、Connection
或 EventHandler
类上的 registerEvent
方法轻松注册新事件。
事件需要一个带有 EventArguments
对象作为参数的自定义回调函数。
示例
$queryBuilder->registerEvent(EventHandler::EVENT_BEFORE_SELECT, 'users', function(EventArguments $arguments) { $arguments ->getQueryBuilder() ->where('status', '!=', 'banned'); });
现在每次在 users
表上发生 select 查询时,都会添加此 where 条件,因此禁止的用户无法访问。
语法是 registerEvent('事件类型', '表名',闭包中的操作)
。
如果要将事件设置为在查询任何表时执行,提供 ':any'
作为表名。
其他示例
在向 my_table
插入数据后,将详细信息插入到另一个表中
$queryBuilder->registerEvent(EventHandler::EVENT_AFTER_INSERT, 'my_table', function(EventArguments $arguments) { $arguments ->getQueryBuilder() ->table('person_details')->insert(array( 'person_id' => $insertId, 'details' => 'Meh', 'age' => 5 )); });
每当向 person_details
表插入数据时,设置时间戳字段 created_at
,因此我们不必在所有地方指定它
$queryBuilder->registerEvent(EventHandler::EVENT_AFTER_INSERT, 'person_details', function(EventArguments $arguments) { $arguments ->getQueryBuilder() ->table('person_details') ->where('id', $insertId) ->update([ 'created_at' => date('Y-m-d H:i:s') ]); });
在从 my_table
中删除后删除关联数据
$queryBuilder->registerEvent(EventHandler::EVENT_AFTER_DELETE, 'my_table', function(EventArguments $arguments) { $bindings = $arguments->getQuery()->getBindings(); $arguments ->getQueryBuilder() ->table('person_details') ->where('person_id', $binding[0]) ->delete(); });
Pixie 将查询构建器的当前实例作为闭包的第一个参数传递,因此您可以使用此对象构建查询,您可以像通常的查询构建器(QB
)那样做任何事情。
如果 before-*
查询处理程序返回的不是 null
,则该值将是执行结果,数据库实际上不会被查询(因此,相应的 after-*
处理程序也不会被调用)。
只有在使用 after-*
事件时,您会得到三个参数:第一个 是查询构建器,第三个 是执行时间作为浮点数,第二个 因事件而异。
- 在执行原始查询之后,将触发
after-query
。 - 在
after-select
中,您将得到select
获取的results
。 - 在
after-insert
中,您将得到插入 id(或批量插入的 id 数组)。 - 在
after-delete
中,您将得到 查询对象(与从getQuery()
获取的相同),您可以从其中获取 SQL 和绑定。 - 在
after-update
中,您将得到与after-delete
相同的 查询对象。
删除事件
$queryBuilder->removeEvent($event, $table = null);
用例
以下是查询事件可能非常有用的几个场景
- 限制被禁止的用户。
- 仅获取
deleted = 0
记录。 - 实现所有查询的缓存。
- 在每次条目后触发用户通知。
- 在删除查询后删除关联数据。
- 在插入查询后插入关联数据。
- 在每个更新查询后记录修改。
- 在每个条目后添加/编辑
created_at
和updated_at
数据。
注意
- 查询事件按连接设置,因此多个数据库连接不会引起任何问题,创建新的查询构建器实例将保留您的事件。
- 查询事件递归执行,例如,在向
table_a
插入后,您的事件插入到table_b
,现在您可以注册另一个事件与table_b
关联,该事件插入到table_c
。 - 当然,查询事件不与原始查询一起使用。
异常
以下是 pecee-pixie 抛出的异常列表。
所有异常都继承自基类 Exception
。
从异常获取sql查询
如果发生错误并且您想调试您的查询 - 您可以轻松做到,因为 Pixie 抛出的所有异常都将包含最后一个执行的查询。
您可以通过调用以下方式检索 QueryObject
:
$sql = $exception->getQueryObject()->getRawSql();
鸣谢
本项目基于由才华横溢的 usmanhalalit 开发的原始 Pixie 项目。
感谢所有贡献者和享受我们库的用户。
以下是一些我们的参考资料
许可证
本软件及其相关文档文件(以下简称“软件”)采用 MIT 许可证授权。
MIT 许可证 (MIT)
版权所有(c)2020 Marcin Pudełek / pixie
特此授予任何获得本软件及其相关文档文件副本(以下简称“软件”)的人免费使用本软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许软件的接收人进行此类操作,但必须遵守以下条件
上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。
本软件按“原样”提供,没有任何形式的保证,明示或暗示,包括但不限于适销性、特定用途的适用性和非侵权性。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论该索赔、损害或其他责任是基于合同、侵权或其他方式,无论是否与软件或其使用或其他方式有关。