简化版 / postgres
简化版PostgreSQL库
Requires
- php: >=5.3
- ext-pdo: *
README
_ _ _ ___(_)_ __ ___ _ __ | | ___ _ __ _ __ ___ ___| |_ __ _ _ __ ___ ___ / __| | '_ ` _ \| '_ \| |/ _ \| '_ \ | '_ \ / _ \/ __| __/ _` | '__/ _ \/ __| \__ \ | | | | | | |_) | | (_) | | | | | |_) | (_) \__ \ || (_| | | | __/\__ \ |___/_|_| |_| |_| .__/|_|\___/|_| |_| | .__/ \___/|___/\__\__, |_| \___||___/ |_| |_| |___/
简化版/Postgres
- 安装
- 直接与PgSqlManager的比较
- 设置连接
- 用法:直接访问
4.1. 查询
4.2. 插入
4.3. 更新
4.4. 替换
4.5. 删除
4.6. 执行 - 用法:PgSqlManager
5.1. 查询
5.2. 插入
5.3. 更新
5.4. 替换
5.5. 删除
5.6. 执行 - IN()子句处理
6.1. 问题
6.2. 解决方案 - CRUD助手
7.1. 简介
7.2. 要求
7.3. 灵活性/限制
7.4. 结论
7.5. 示例
7.6. 自定义Vo示例 - 异常
依赖
- PHP >= 5.3
- PDO
1. 安装
通过composer轻松安装。还不知道composer是什么?请在此处了解 信息。
{ "require": { "simplon/postgres": "*" } }
2. 直接与PgSqlManager的比较
我实现了两种与Postgres交互的方式。第一种选项是直接与数据库交互的常规方式。以下是一个直接示例,以展示我的意思
$dbConn->fetchRow('SELECT * FROM names WHERE name = :name', array('name' => 'Peter'));
与先前的方法相比,PgSqlManager使用建造者模式来处理数据库。这有什么优势?好吧,如果我们想在发送查询之前对查询做更多的事情,我们可以将其封装为Builder Pattern
。从那时起,我们可以将其传递到我们的应用程序中,在最终将查询发送到数据库之前添加更多数据或类似内容。再次,以下是如何重写上面的直接查询
的快速示例
$sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setQuery('SELECT * FROM names WHERE name = :name') ->setConditions(array('name' => 'Peter')); $pgSqlManager = new \Simplon\Postgres\Manager\PgSqlManager($dbConn); $pgSqlManager->fetchRow($sqlBuilder);
3. 设置连接
库需要一个配置值对象来实例化与Postgres的连接。看看它是如何做的
$config = array( // required credentials 'host' => 'localhost', 'user' => 'rootuser', 'password' => 'rootuser', 'database' => 'our_database', // optional 'fetchMode' => \PDO::FETCH_ASSOC, 'charset' => 'utf8', 'port' => 3306, 'unixSocket' => null, ); // standard setupPostgres $dbConn = new \Simplon\Postgres\Postgres( $config['host'], $config['user'], $config['password'], $config['database'] );
以下代码显示了设置连接的所有可能参数
\Simplon\Postgres\Postgres::__construct( $host, $user, $password, $database, $fetchMode = \PDO::FETCH_ASSOC, $charset = 'utf8', array $options = array('port' => 3306, 'unixSocket' => '') );
如果您想使用PgSqlManager
,则缺少一个部分
$pgSqlManager = new \Simplon\Postgres\Manager\PgSqlManager($dbConn);
4. 用法:直接访问
4.1. 查询
FetchColumn
返回第一个匹配项所选的列。以下示例返回id
或如果没有找到任何内容,则返回false
。
$result = $dbConn->fetchColumn('SELECT id FROM names WHERE name = :name', array('name' => 'Peter')); // result var_dump($result); // '1' || false
FetchColumnMany
返回包含所有匹配数据集所选列的数组。以下示例返回包含所有ids
的数组或如果没有找到任何内容,则返回false
。
$result = $dbConn->fetchColumnMany('SELECT id FROM names WHERE name = :name', array('name' => 'Peter')); // result var_dump($result); // ['1', '15', '30', ...] || false
FetchColumnManyCursor
一次返回一个匹配数据集。它资源效率高,因此在结果数据很多时很方便。以下示例中,如果您有匹配项,则通过foreach循环迭代,如果没有匹配项,则不执行任何操作。
$cursor = $dbConn->fetchColumnMany('SELECT id FROM names WHERE name = :name', array('name' => 'Peter')); foreach ($cursor as $result) { var_dump($result); // '1' }
FetchRow
返回匹配数据集的所有所选列。以下示例返回匹配数据集的id
和age
。如果没有找到匹配项,则返回false
。
$result = $dbConn->fetchRow('SELECT id, age FROM names WHERE name = :name', array('name' => 'Peter')); var_dump($result); // ['id' => '1', 'age' => '22'] || false
FetchRowMany
返回所有匹配数据集的所有所选列。以下示例为每个匹配数据集返回id
和age
。如果没有找到匹配项,则返回false
。
$result = $dbConn->fetchRowMany('SELECT id, age FROM names WHERE name = :name', array('name' => 'Peter')); var_dump($result); // [ ['id' => '1', 'age' => '22'], ['id' => '15', 'age' => '40'], ... ] || false
FetchRowManyCursor
与FetchColumnManyCursor
相同,但我们接收所有所选列。
$result = $dbConn->fetchRowMany('SELECT id, age FROM names WHERE name = :name', array('name' => 'Peter')); foreach ($cursor as $result) { var_dump($result); // ['id' => '1', 'age' => '22'] }
4.2. 插入
单条数据
将数据插入数据库非常直接。请参考以下示例
$data = array( 'id' => false, 'name' => 'Peter', 'age' => 45, ); $id = $dbConn->insert('names', $data); var_dump($id); // 50 || bool
结果取决于表。如果表有一个自动增长ID
列,您将收到插入数据的ID计数。如果表没有这样的字段,您将收到成功插入的true
。如果出了问题,您将收到false
。
多个数据集
遵循示例以一次性插入多个数据集
$data = array( array( 'id' => false, 'name' => 'Peter', 'age' => 45, ), array( 'id' => false, 'name' => 'Peter', 'age' => 16, ), ); $id = $dbConn->insertMany('names', $data); var_dump($id); // 50 || bool
结果取决于表。如果表有一个自动增长ID
列,您将收到插入数据的ID计数。如果表没有这样的字段,您将收到成功插入的true
。如果出了问题,您将收到false
。
4.3. 更新
简单更新语句
与插入语句相同,考虑到更新。这很容易理解。如果更新成功,响应将是 true
。如果出现问题,您将收到 false
。
$conds = array( 'id' => 50, ); $data = array( 'name' => 'Peter', 'age' => 50, ); $result = $dbConn->update('names', $conds, $data); var_dump($result); // true || false
自定义更新条件查询
与插入语句相同,考虑到更新。这很容易理解。如果更新成功,响应将是 true
。如果出现问题,您将收到 false
。
$conds = array( 'id' => 50, 'name' => 'Peter', ); // custom conditions query $condsQuery = 'id = :id OR name =: name'; $data = array( 'name' => 'Peter', 'age' => 50, ); $result = $dbConn->update('names', $conds, $data, $condsQuery); var_dump($result); // true || false
4.4. 替换
正如Postgres所述: REPLACE
与 INSERT
完全相同,除了如果表中旧行的新行对于 PRIMARY KEY
或 UNIQUE index
具有相同的值,则在插入新行之前将删除旧行。
替换单个数据集
结果您将收到 INSERT ID
或在出现错误的情况下 false
。
$data = array( 'id' => 5, 'name' => 'Peter', 'age' => 16, ); $result = $dbConn->replace('names', $data); var_dump($result); // 1 || false
替换多个数据集
结果您将收到一个 INSERT IDs
数组或出现错误的情况下的 false
。
$data = array( array( 'id' => 5, 'name' => 'Peter', 'age' => 16, ), array( 'id' => 10, 'name' => 'John', 'age' => 22, ), ); $result = $dbConn->replaceMany('names', $data); var_dump($result); // [5, 10] || false
4.5. 删除
简单的删除条件
以下示例演示了如何删除数据。如果查询成功,我们将收到 true
否则 false
。
$result = $dbConn->delete('names', array('id' => 50)); var_dump($result); // true || false
自定义删除条件查询
以下示例演示了如何使用自定义条件查询删除数据。如果查询成功,我们将收到 true
否则 false
。
$conds = array( 'id' => 50, 'name' => 'John', ); // custom conditions query $condsQuery = 'id = :id OR name =: name'; $result = $dbConn->delete('names', $conds, $condsQuery); var_dump($result); // true || false
4.6. 执行
此方法适用于不需要任何参数的调用,例如 TRUNCATE
。如果调用成功,您将收到 true
。如果失败,将抛出 PostgresException
。
$result = $dbConn->executeSql('TRUNCATE names'); var_dump($result); // true
5. 使用:PgSqlManager
以下查询示例将是上述 直接访问
示例的改写。请注意:我们需要一个 PgSqlManager
的实例。第 3. 设置连接
段落说明了如何获取它。
5.1. 查询
FetchColumn
返回第一个匹配项的选定列。在下面的示例中,将返回 id
或未找到任何内容时返回 false
。
$sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setQuery('SELECT id FROM names WHERE name = :name') ->setConditions(array('name' => 'Peter')); $result = $pgSqlManager->fetchColumn($sqlBuilder); // result var_dump($result); // '1' || false
FetchColumnMany
返回包含所有匹配数据集所选列的数组。以下示例返回包含所有ids
的数组或如果没有找到任何内容,则返回false
。
$sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setQuery('SELECT id FROM names WHERE name = :name') ->setConditions(array('name' => 'Peter')); $result = $pgSqlManager->fetchColumnMany($sqlBuilder); // result var_dump($result); // ['1', '15', '30', ...] || false
FetchColumnManyCursor
一次返回一个匹配数据集。它资源效率高,因此在结果数据很多时很方便。以下示例中,如果您有匹配项,则通过foreach循环迭代,如果没有匹配项,则不执行任何操作。
$sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setQuery('SELECT id FROM names WHERE name = :name') ->setConditions(array('name' => 'Peter')); foreach ($pgSqlManager->fetchColumnMany($sqlBuilder) as $result) { var_dump($result); // '1' }
FetchRow
返回匹配数据集的所有所选列。以下示例返回匹配数据集的id
和age
。如果没有找到匹配项,则返回false
。
$sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setQuery('SELECT id, age FROM names WHERE name = :name') ->setConditions(array('name' => 'Peter')); $result = $pgSqlManager->fetchRow($sqlBuilder); var_dump($result); // ['id' => '1', 'age' => '22'] || false
FetchRowMany
返回所有匹配数据集的所有所选列。以下示例为每个匹配数据集返回id
和age
。如果没有找到匹配项,则返回false
。
$sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setQuery('SELECT id, age FROM names WHERE name = :name') ->setConditions(array('name' => 'Peter')); $result = $pgSqlManager->fetchRowMany($sqlBuilder); var_dump($result); // [ ['id' => '1', 'age' => '22'], ['id' => '15', 'age' => '40'], ... ] || false
FetchRowManyCursor
与FetchColumnManyCursor
相同,但我们接收所有所选列。
$sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setQuery('SELECT id, age FROM names WHERE name = :name') ->setConditions(array('name' => 'Peter')); foreach ($pgSqlManager->fetchRowManyCursor($sqlBuilder) as $result) { var_dump($result); // ['id' => '1', 'age' => '22'] }
5.2. 插入
单条数据
将数据插入数据库非常直接。请参考以下示例
$data = array( 'id' => false, 'name' => 'Peter', 'age' => 45, ); $sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setTableName('names') ->setData($data); $id = $pgSqlManager->insert($sqlBuilder); var_dump($id); // 50 || false
结果取决于表。如果表有一个自动增长ID
列,您将收到插入数据的ID计数。如果表没有这样的字段,您将收到成功插入的true
。如果出了问题,您将收到false
。
多个数据集
遵循示例以一次性插入多个数据集
$data = array( array( 'id' => false, 'name' => 'Peter', 'age' => 45, ), array( 'id' => false, 'name' => 'Peter', 'age' => 16, ), ); $sqlBuilder = (new \Simplon\Postgres\Manager\PgSqlQueryBuilder()) ->setTableName('names') ->setData($data); $result = $pgSqlManager->insert($sqlBuilder); var_dump($id); // [50, 51, ...] || false
结果取决于表。如果表有一个自动增长ID
列,您将收到插入数据的ID计数。如果表没有这样的字段,您将收到成功插入的true
。如果出了问题,您将收到false
。
5.3. 更新
简单更新语句
与插入语句相同,考虑到更新。这很容易理解。如果更新成功,响应将是 true
。如果出现问题,您将收到 false
。
$data = array( 'name' => 'Peter', 'age' => 50, ); $sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setTableName('names') ->setConditions(array('id' => 50)) ->setData($data); $result = $pgSqlManager->update($sqlBuilder); var_dump($result); // true || false
自定义更新条件查询
与插入语句相同,考虑到更新。这很容易理解。如果更新成功,响应将是 true
。如果出现问题,您将收到 false
。
$data = array( 'name' => 'Peter', 'age' => 50, ); $sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setTableName('names') ->setConditions(array('id' => 50)) ->setConditionsQuery('id = :id OR name =: name') ->setData($data) $result = $pgSqlManager->update($sqlBuilder); var_dump($result); // true || false
5.4. 替换
正如Postgres所述: REPLACE
与 INSERT
完全相同,除了如果表中旧行的新行对于 PRIMARY KEY
或 UNIQUE index
具有相同的值,则在插入新行之前将删除旧行。
替换单个数据集
结果您将收到 INSERT ID
或在出现错误的情况下 false
。
$data = array( 'id' => 5, 'name' => 'Peter', 'age' => 16, ); $sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setTableName('names') ->setData($data); $result = $pgSqlManager->replace($sqlBuilder); var_dump($result); // 1 || false
替换多个数据集
结果您将收到一个 INSERT IDs
数组或出现错误的情况下的 false
。
$data = array( array( 'id' => 5, 'name' => 'Peter', 'age' => 16, ), array( 'id' => 10, 'name' => 'John', 'age' => 22, ), ); $sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setTableName('names') ->setData($data); $result = $pgSqlManager->replaceMany($sqlBuilder); var_dump($result); // [5, 10] || false
5.5. 删除
简单的删除条件
以下示例演示了如何删除数据。如果查询成功,我们将收到 true
否则 false
。
$sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setTableName('names') ->setConditions(array('id' => 50)); $result = $pgSqlManager->delete($sqlBuilder); var_dump($result); // true || false
自定义删除条件查询
以下示例演示了如何使用自定义条件查询删除数据。如果查询成功,我们将收到 true
否则 false
。
$sqlBuilder = new \Simplon\Postgres\Manager\PgSqlQueryBuilder(); $sqlBuilder ->setTableName('names') ->setConditions(array('id' => 50, 'name' => 'Peter')) ->setConditionsQuery('id = :id OR name =: name'); $result = $pgSqlManager->delete($sqlBuilder); var_dump($result); // true || false
6. IN() 子句处理
6.1. 问题
无法通过 PDO 使用 IN()
子句。这种功能根本不存在。然而,您可以做一些类似以下的事情
$ids = array(1,2,3,4,5); $query = "SELECT * FROM users WHERE id IN (" . join(',', $ids) . ")";
乍一看看起来不错 - 不性感但可能能完成任务,对吧?错了。这种方法仅适用于 INTEGERS
并且它不会 ESCAPE
用户的输入 - 这正是我们最初使用 PDO
的原因。
仅为了记录,以下是一个无法工作的字符串示例
$emails = array('johnny@me.com', 'peter@ibm.com'); $query = "SELECT * FROM users WHERE email IN (" . join(',', $emails) . ")";
唯一能让它工作的方式是将每个值像以下这样包装: '"email"'
。这太费事了。
6.2. 解决方案
为了利用内置的具有转义和类型处理的 IN() Clause
,请执行以下操作
// integers $conds = array('ids' => array(1,2,3,4,5)); $query = "SELECT * FROM users WHERE id IN (:ids)"; // strings $conds = array('emails' => array('johnny@me.com', 'peter@ibm.com')); $query = "SELECT * FROM users WHERE email IN (:emails)";
7. CRUD 辅助器
7.1. 简介
CRUD
代表 Create Read Update Delete
,反映了持久存储的基本功能。
我发现自己在为所有与对象/数据库交互的对象编写越来越多的 CRUD,仅仅是因为我需要在与这些对象进行上述功能交互时有一个 SINGLE POINT OF ACCESS
。最终,它有点像数据库模型的感觉,但具有更大的灵活性。此外,我们继续编写 VALUE OBJECTS
,并通过这种方式保持所有代码库的红线。
注意: 实际上 VALUE OBJECTS
是 MODELS
,而模型不是值对象。这样做的原因是值对象是各种数据的载体,而模型只是数据库数据的载体。至少,它应该是这样的。
7.2. 要求/限制
实际上 没有多少 要求/限制
- 需要
PgSqlCrudManager
的实例 - 需要一个Simplon\Postgres
的实例。 - 值对象需要从
PgSqlCrudVo
扩展 - 表名应该是复数形式,或者通过值对象中的
PgSqlCrudVo::$crudSource
设置。 - 值对象的实例变量必须与表中的列名匹配,使用驼峰命名法(请参见下例)。
- 每个值对象仅反映一个对象——《Postgres::fetchRow()》用于获取您的数据。
变量 = 列
请不要在您的值对象中设置任何不反映您的数据库表的属性。如果您必须这样做,则可以使用PgSqlCrudVo::crudColumns()
或PgSqlCrudVo::crudIgnore()
。请参阅《灵活性》部分的描述。- 在
主键
的情况下:如果您的字段名称与id
不同,您需要通过PgSqlCrudVo::crudPkName
来设置它。这对于自动递增PK字段以及获取lastInsertId
是必要的。
7.3. 灵活性
-
设置源:如果您有一个无法轻易复数的表名(例如person/people),您可以在值对象中通过
PgSqlCrudVo::$crudSource
自行设置源。 -
设置自定义读取查询:如果您需要一个自定义查询来获取对象,您可以在实例化对象时设置它
new PgSqlCrudVo($query)
,或者简单地在其__construct() { parent::construct($query); }
中设置。 -
回调函数:您可以实现两个方法,这些方法将在保存对象之前/之后被调用:
PgSqlCrudVo::crudBeforeSave($isCreateEvent)
和PgSqlCrudVo::crudAfterSave($isCreateEvent)
。管理器将传递一个布尔值以让您知道正在发生/已发生的保存过程类型。例如,您可以使用此功能自动设置created_at
和updated_at
字段。 -
设置列:如果您需要匹配属性名和列名,或者只想选择您的属性的一部分,请使用值对象中的
PgSqlCrudVo::crudColumns()
。它应该返回一个数组,其中数组键
反映值对象的变量名
,而数组值
反映列名
。示例:array('createdAt' => 'created_at')
-
忽略属性:考虑到前面的点,您可以简单地
忽略变量
。为此,实现PgSqlCrudVo::crudIgnore()
,它应该返回一个您想要忽略的属性的数组。 -
无假设:没有关于主键或其他类似事物的假设。您为读取、更新和/或删除对象设置所有条件。
-
类型转换的值:感谢您的值对象始终在您和数据库之间,您可以转换所有值——再见
仅字符串类型转换
值。
7.4. 结论
这就是目前所需的所有内容。它是简单
、明确
和灵活
的,不会限制您的要求或您的创造力
。
7.5. 示例
别说了,行动起来吧!好吧,需要什么?假设我们有一个名为users
的数据库表和一个名为UserVo
的值对象。注意:值对象名称必须是表的复数名称的单数形式。
以下是表模式
CREATE TABLE users ( id serial NOT NULL, name varying(50) NOT NULL DEFAULT '', email varying(254) NOT NULL DEFAULT '', created_at int(10) unsigned NOT NULL, updated_at int(10) unsigned NOT NULL, CONSTRAINT users_user_pkey PRIMARY KEY (id) );
...以及给定表的值对象
class UserVo extends \Simplon\Postgres\Crud\PgSqlCrudVo { protected $id; protected $name; protected $email; protected $createdAt; protected $updatedAt; // ... here goes getter/setter for the above variables }
现在,让我们做一些CRUD操作,宝贝!对于所有过程,我们需要一个PgSqlCrudManager
的实例。
/** * construct it with an instance of your simplon/Postgres */ $PgSqlCrudManager = new \Simplon\Postgres\Crud\PgSqlCrudManager($postgresInstance);
创建一个用户
$userVo = new UserVo(); $userVo ->setName('Johnny Foobar') ->setEmail('foo@bar.com'); /** @var UserVo $userVo */ $userVo = $PgSqlCrudManager->create($userVo); // print insert id echo $userVo->getId(); // 1
读取一个用户
// conditions: where id = 1 $conds = array('id' => 1); /** @var UserVo $userVo */ $userVo = $PgSqlCrudManager->read(new UserVo(), $conds); // print name echo $userVo->getName(); // Johnny Foobar
更新一个用户
// conditions: where id = 1 $conds = array('id' => 1); /** @var UserVo $userVo */ $userVo = $PgSqlCrudManager->read(new UserVo(), $conds); // set new name $userVo->setName('Hansi Hinterseher'); // update /** @var UserVo $userVo */ $userVo = $PgSqlCrudManager->update($userVo, $conds); // print name echo $userVo->getName(); // Hansi Hinterseher
删除一个用户
// conditions: where id = 1 $conds = array('id' => 1); /** * UserVo::crudGetSource() is the name of the table * based on the value object's name */ $PgSqlCrudManager->update(UserVo::crudGetSource(), $conds);
7.6. 自定义Vo示例
设置一个自定义表名
,因为person的复数不是persons
class PersonVo extends \Simplon\Postgres\Crud\PgSqlCrudVo { /** * @return string */ public static function crudGetSource() { return 'people'; } // ... here goes the rest }
如果您的列名
完全不同,仍然有方法将它们与您的属性
匹配
class UserVo extends \Simplon\Postgres\Crud\PgSqlCrudVo { protected $id; protected $name; protected $email; protected $createdAt; protected $updatedAt; /** * @return array */ public function crudColumns() { return array( 'id' => 'xx_id', 'name' => 'xx_name', 'email' => 'xx_email', 'createdAt' => 'xx_created_at', 'updatedAt' => 'xx_updated_at', ); } // ... here goes the rest }
有时有一些辅助属性
不是您数据库条目的一部分。这里有忽略它们的方法
class UserVo extends \Simplon\Postgres\Crud\PgSqlCrudVo { protected $id; protected $name; protected $email; protected $createdAt; protected $updatedAt; // helper property: not part of the people table protected $isOffline; /** * @return array */ public function crudIgnore() { return array( 'isOffline', ); } // ... here goes the rest }
8. 异常
对于两种访问方法(直接,PgSqlManager)发生的异常将被包装在PostgresException
中。所有关键异常信息都将总结为JSON
在异常消息中。
下面是一个例子,看看它可能是什么样子
{"query":"SELECT pro_id FROM names WHERE connector_type = :connectorType","params":{"connectorType":"FB"},"errorInfo":{"sqlStateCode":"42S22","code":1054,"message":"Unknown column 'pro_id' in 'field list'"}}
许可证
Simplon/Postgres可以在MIT许可证的条款下自由分发。
版权(c)2015 Tino Ehrich(tino@bigpun.me)
在此特此授权,免费提供给任何获得本软件及其相关文档文件(以下简称“软件”)副本的个人,在不加限制的情况下处理软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本的权利,并允许将软件提供给他人,使其能够这样做,前提是遵守以下条件
上述版权声明和本许可声明应包含在软件的所有副本或实质性部分中。
软件按“原样”提供,不提供任何形式的保证,无论是明示的还是暗示的,包括但不限于适销性、特定用途适用性和非侵权性保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任承担责任,无论该责任是在合同行为、侵权或其他行为中产生,还是与软件或软件的使用或其他方式有关。