简凌/mysql

简凌 MySQL 库

3.1.0 2024-09-02 10:06 UTC

README

     _                 _                                         _ 
 ___(_)_ __ ___  _ __ | | ___  _ __    _ __ ___  _   _ ___  __ _| |
/ __| | '_ ` _ \| '_ \| |/ _ \| '_ \  | '_ ` _ \| | | / __|/ _` | |
\__ \ | | | | | | |_) | | (_) | | | | | | | | | | |_| \__ \ (_| | |
|___/_|_| |_| |_| .__/|_|\___/|_| |_| |_| |_| |_|\__, |___/\__, |_|
                |_|                              |___/        |_|  

简凌/Mysql

  1. 安装
  2. 直接访问与 CRUD
  3. 设置连接
  4. 使用:直接访问
    4.1. 查询
    4.2. 插入
    4.3. 更新
    4.4. 替换
    4.5. 删除
    4.6. 执行
  5. 使用:CRUD
    5.1. 设置存储库
    5.2. 设置模型
    5.3. 连接到存储库
    5.4. 查询
    5.5. 插入
    5.6. 更新
    5.7. 删除
    5.8. 自定义查询
  6. IN() 子句处理
    6.1. 问题
    6.2. 解决方案
  7. 异常

依赖项

  • PHP >= 7.1
  • PDO

1. 安装

通过 composer 简单安装。还不知道 composer 是什么?请在此处了解 此处

{
  "require": {
    "simplon/mysql": "*"
  }
}

2. 直接访问与 CRUD

我实现了两种与 MySQL 交互的方式。第一种是直接与数据库交互的常用方法。以下是一个直接示例,说明我的意思

$data = $dbConn->fetchRow('SELECT * FROM names WHERE name = :name', ['name' => 'Peter']);

//
// $data is an array with our result
//

与先前方法相比,CRUD 更有结构,具有 storemodel。此外,它使用 构建者模式 来与数据库交互。以下是一个重写上述 直接查询 的快速示例

$store = new NamesStore($dbConn);

$model = $store->read(
    ReadQueryBuilder::create()->addCondition(NameModel::COLUMN_NAME, 'Peter')
);

//
// $model is a class with our result data abstracted
//

3. 设置连接

该库需要配置值对象来创建与 MySQL 的连接实例。看看是如何做的

$pdo = new PDOConnector(
	'localhost', // server
	'root',      // user
	'root',      // password
	'database'   // database
);

$pdoConn = $pdo->connect('utf8', []); // charset, options

//
// you could now interact with PDO for instance setting attributes etc:
// $pdoConn->setAttribute($attribute, $value);
//

$dbConn = new Mysql($pdoConn);

4. 使用:直接访问

4.1. 查询

FetchColumn

从第一个匹配项返回所选列。以下示例返回 idnull 如果未找到任何内容。

$result = $dbConn->fetchColumn('SELECT id FROM names WHERE name = :name', ['name' => 'Peter']);

// result
var_dump($result); // '1' || null

FetchColumnMany

返回一个包含所有匹配数据集所选列的数组。以下示例将返回包含所有 ids 的数组或 null 如果未找到任何内容。

$result = $dbConn->fetchColumnMany('SELECT id FROM names WHERE name = :name', ['name' => 'Peter']);

// result
var_dump($result); // ['1', '15', '30', ...] || null

FetchColumnManyCursor

每次返回一个匹配数据集。它资源效率高,因此当您的结果有许多数据时很方便。以下示例中,您将遍历 foreach 循环以查找匹配项,如果没有匹配项则不会发生任何事情。

$cursor = $dbConn->fetchColumnMany('SELECT id FROM names WHERE name = :name', ['name' => 'Peter']);

foreach ($cursor as $result)
{
    var_dump($result); // '1'
}

FetchRow

从匹配的数据集返回所有所选列。以下示例返回匹配数据集的 idage。如果没有匹配项,将返回 null

$result = $dbConn->fetchRow('SELECT id, age FROM names WHERE name = :name', ['name' => 'Peter']);

var_dump($result); // ['id' => '1', 'age' => '22'] || null

FetchRowMany

返回所有匹配数据集的所有所选列。以下示例为每个匹配数据集返回 idage。如果没有匹配项,将返回 null

$result = $dbConn->fetchRowMany('SELECT id, age FROM names WHERE name = :name', ['name' => 'Peter']);

var_dump($result); // [ ['id' => '1', 'age' => '22'],  ['id' => '15', 'age' => '40'], ... ] || null

FetchRowManyCursor

FetchColumnManyCursor 相同的解释,但我们将接收到所有所选列。

$result = $dbConn->fetchRowMany('SELECT id, age FROM names WHERE name = :name', ['name' => 'Peter']);

foreach ($cursor as $result)
{
    var_dump($result); // ['id' => '1', 'age' => '22']
}

4.2. 插入

单数据

将数据插入数据库非常直接。请参考以下示例

$data = [
    'id'   => false,
    'name' => 'Peter',
    'age'  => 45,
];

$id = $dbConn->insert('names', $data);

var_dump($id); // 50 || bool

结果取决于表。如果表包含 自动递增 ID 列,您将收到插入数据的 ID 计数。如果表不包含此类字段,您将收到成功的插入 true。如果任何事情出了问题,您将收到 false

多个数据集

按照以下示例一次性插入多个数据集

$data = [
    [
        'id'   => false,
        'name' => 'Peter',
        'age'  => 45,
    ],
    [
        'id'   => false,
        'name' => 'Peter',
        'age'  => 16,
    ],
];

$id = $dbConn->insertMany('names', $data);

var_dump($id); // 50 || bool

结果取决于表。如果表包含 自动递增 ID 列,您将收到插入数据的 ID 计数。如果表不包含此类字段,您将收到成功的插入 true。如果任何事情出了问题,您将收到 false

4.3. 更新

简单更新语句

与插入语句类似,更新语句也易于理解。如果更新成功,则响应将为 true。如果没有更新任何内容,您将收到 null

$conds = [
    'id' => 50,
];

$data = [
    'name' => 'Peter',
    'age'  => 50,
];

$result = $dbConn->update('names', $conds, $data);

var_dump($result); // true || null

自定义更新条件查询

与插入语句类似,更新语句也易于理解。如果更新成功,则响应将为 true。如果没有更新任何内容,您将收到 null

$conds = [
    'id'   => 50,
    'name' => 'Peter',
];

// custom conditions query
$condsQuery = 'id = :id OR name =: name';

$data = [
    'name' => 'Peter',
    'age'  => 50,
];

$result = $dbConn->update('names', $conds, $data, $condsQuery);

var_dump($result); // true || null

4.4. 替换

正如MySQL所述:REPLACE的工作方式与INSERT完全相同,不同之处在于如果表中某行的值与新的行的PRIMARY KEYUNIQUE index相同,则在插入新行之前,将删除旧行。

替换单个数据集

结果您将获得INSERT ID或如果出现问题,将返回false

$data = [
    'id'   => 5,
    'name' => 'Peter',
    'age'  => 16,
];

$result = $dbConn->replace('names', $data);

var_dump($result); // 1 || false

替换多个数据集

结果您将获得一个INSERT IDs数组或如果出现问题,将返回false

$data = [
    [
        'id'   => 5,
        'name' => 'Peter',
        'age'  => 16,
    ],
    [
        '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', ['id' => 50]);

var_dump($result); // true || false

自定义删除条件查询

以下示例演示了如何使用自定义条件查询删除数据。如果查询成功,我们将收到true,否则收到false

$conds = [
    '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。如果失败,将抛出MysqlException

$result = $dbConn->executeSql('TRUNCATE names');

var_dump($result); // true

5. 使用:CRUD

以下查询示例将是上述直接访问示例的重写。为此,我们需要一个Store及其相关的Model

5.1. 设置存储库

namespace Test\Crud;

use Simplon\Mysql\CreateQueryBuilder;use Simplon\Mysql\CrudModelInterface;use Simplon\Mysql\CrudStore;use Simplon\Mysql\DeleteQueryBuilder;use Simplon\Mysql\MysqlException;use Simplon\Mysql\ReadQueryBuilder;use Simplon\Mysql\UpdateQueryBuilder;

/**
 * @package Test\Crud
 */
class NamesStore extends CrudStore
{
    /**
     * @return string
     */
    public function getTableName(): string
    {
        return 'names';
    }

    /**
     * @return CrudModelInterface
     */
    public function getModel(): CrudModelInterface
    {
        return new NameModel();
    }

    /**
     * @param CreateQueryBuilder $builder
     *
     * @return NameModel
     * @throws MysqlException
     */
    public function create(CreateQueryBuilder $builder): NameModel
    {
        /** @var NameModel $model */
        $model = $this->crudCreate($builder);

        return $model;
    }

    /**
     * @param ReadQueryBuilder|null $builder
     *
     * @return NameModel[]|null
     * @throws MysqlException
     */
    public function read(?ReadQueryBuilder $builder = null): ?array
    {
        /** @var NameModel[]|null $response */
        $response = $this->crudRead($builder);

        return $response;
    }

    /**
     * @param ReadQueryBuilder $builder
     *
     * @return null|NameModel
     * @throws MysqlException
     */
    public function readOne(ReadQueryBuilder $builder): ?NameModel
    {
        /** @var NameModel|null $response */
        $response = $this->crudReadOne($builder);

        return $response;
    }

    /**
     * @param UpdateQueryBuilder $builder
     *
     * @return NameModel
     * @throws MysqlException
     */
    public function update(UpdateQueryBuilder $builder): NameModel
    {
        /** @var NameModel|null $model */
        $model = $this->crudUpdate($builder);

        return $model;
    }

    /**
     * @param DeleteQueryBuilder $builder
     *
     * @return bool
     * @throws MysqlException
     */
    public function delete(DeleteQueryBuilder $builder): bool
    {
        return $this->crudDelete($builder);
    }   
    
    /**
     * @param int $id
     *
     * @return null|NameModel
     * @throws MysqlException
     */
    public function customMethod(int $id): ?NameModel
    {
        $query = 'SELECT * FROM ' . $this->getTableName() . ' WHERE id=:id';

        if ($result = $this->getCrudManager()->getMysql()->fetchRow($query, ['id' => $id]))
        {
            return (new NameModel())->fromArray($result);
        }

        return null;
    }
}

5.2. 设置模型

<?php

namespace Test\Crud;

use Simplon\Mysql\CrudModel;

/**
 * @package Test\Crud
 */
class NameModel extends CrudModel
{
    const COLUMN_ID = 'id';
    const COLUMN_NAME = 'name';
    const COLUMN_AGE = 'age';

    /**
     * @var int
     */
    protected $id;
    /**
     * @var string
     */
    protected $name;
    /**
     * @var int
     */
    protected $age;

    /**
     * @return int
     */
    public function getId(): int
    {
        return (int)$this->id;
    }

    /**
     * @param int $id
     *
     * @return NameModel
     */
    public function setId(int $id): NameModel
    {
        $this->id = $id;

        return $this;
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @param string $name
     *
     * @return NameModel
     */
    public function setName(string $name): NameModel
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return int
     */
    public function getAge(): int
    {
        return (int)$this->age;
    }

    /**
     * @param int $age
     *
     * @return NameModel
     */
    public function setAge(int $age): NameModel
    {
        $this->age = $age;

        return $this;
    }
}

5.3. 连接到存储库

为了与我们的商店交互,我们需要创建一个实例。以下各点我们将使用此实例。

$store = new NamesStore($pdoConn);

5.4. 查询

获取一个项目

返回一个name model或如果没有匹配到任何内容,则返回NULL

$model = $store->readOne(
    ReadQueryBuilder::create()->addCondition(NameModel::COLUMN_NAME, 'Peter')
);

echo $model->getId(); // prints user id

您可以使用addCondition中的运算符。

$model = $store->readOne(
    ReadQueryBuilder::create()->addCondition(NameModel::COLUMN_AGE, 20, '>')
);

echo $model->getId(); // prints user id

获取多个项目

返回一个name models数组或如果没有匹配到任何内容,则返回NULL

$models = $store->read(
    ReadQueryBuilder::create()->addCondition(NameModel::COLUMN_NAME, 'Peter')
);

echo $models[0]->getId(); // prints user id from first matched model

5.5. 插入

以下示例展示了如何创建新的商店条目。

$model = $store->create(
    CreateQueryBuilder::create()->setModel(
        (new NameModel())
            ->setName('Johnny')
            ->setAge(22)
    )
);

5.6. 更新

以下示例展示了如何更新现有的商店条目。

//
// fetch a model
//

$model = $store->readOne(
    ReadQueryBuilder::create()->addCondition(NameModel::COLUMN_NAME, 'Peter')
);

//
// update age
//

$model->setAge(36);

//
// persist change
//

$model = $store->update(
    UpdateQueryBuilder::create()
        ->setModel($model)
        ->addCondition(NameModel::COLUMN_ID, $model->getId())
);

5.7. 删除

以下示例展示了如何删除现有的商店条目。

//
// fetch a model
//

$model = $store->readOne(
    ReadQueryBuilder::create()->addCondition(NameModel::COLUMN_NAME, 'Peter')
);

//
// delete model from store
//

$store->delete(
    DeleteQueryBuilder::create()
        ->addCondition(NameModel::COLUMN_ID, $model->getId())
)

5.8. 自定义查询

您还可以为您的商店编写自定义查询/处理。我向商店添加了一个方法,展示了如何实现自定义处理。

/**
 * @param int $id
 *
 * @return null|NameModel
 * @throws MysqlException
 */
public function customMethod(int $id): ?NameModel
{
    $query = 'SELECT * FROM ' . $this->getTableName() . ' WHERE id=:id';

    if ($result = $this->getCrudManager()->getMysql()->fetchRow($query, ['id' => $id]))
    {
        return (new NameModel())->fromArray($result);
    }

    return null;
}

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,请对直接访问执行以下操作。CRUD将自动为您构建查询。

// 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. 异常

对于两种访问方法(直接,sqlmanager),发生的异常将被MysqlException包装。所有基本异常信息都将在Exception Message中以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/Mysql可以在MIT许可证的条款下自由分发。

版权(c)2017 Tino Ehrich (tino@bigpun.me)

特此授予任何获得此软件及其相关文档副本(“软件”)的人,免费处理该软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本,并允许向提供软件的人这样做,前提是遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或实质性部分中。

本软件按“原样”提供,不提供任何形式的保证,无论是明示的还是暗示的,包括但不限于对适销性、特定用途的适用性和非侵权的保证。在任何情况下,作者或版权所有者不应对任何索赔、损害或其他责任负责,无论源于、因之或与软件或软件的使用或其他相关事宜有关,无论基于合同、侵权或其他法律行为。