bowlofsoup / couchbase-access-layer
简单的 Couchbase 查询构建器。
v2.0.1
2024-07-09 13:46 UTC
Requires
- php: ^8.3
- ext-couchbase: *
- ext-json: *
- couchbase/couchbase: ^4.2
Requires (Dev)
- php-coveralls/php-coveralls: ^2.7
- phpunit/phpunit: ^11
This package is auto-updated.
Last update: 2024-09-09 14:09:12 UTC
README
安装
composer require bowlofsoup/couchbase-access-layer
Couchbase Access Layer
在 PHP Couchbase SDK 之上提供了一个简单的层。基本上,你得到一个 bucket 仓库类,它充当你的代码和 Couchbase 之间的层。
仓库可以帮助你
- 快速设置 Couchbase 连接。
- 一个方便使用的 BucketRepository,可以快速查询一个 单个 bucket。
- 使用所谓的 '查询构建器' 创建查询,这有助于你构建可维护且易于阅读的 N1ql 查询。
- 处理从 Couchbase 返回的查询语法差异,将其转换为一致的查询结果。
- 下面有更多示例!
使用
请使用参数
重要:在构建查询时,始终尝试使用参数。
错误
$queryBuilder
->where('data.creationDate >= ' . $creationDate);
正确
$queryBuilder
->where('data.creationDate >= $creationDate')
->setParameter('creationDate', '2019-01-10');
这将防止注入。
查询构建器支持以下 N1QL 子句
SELECT
可选DISTINCT
和RAW
FROM
可选别名,子查询也实现了(=强制别名)USE
表示:USE KEYS
和USE INDEX
WHERE
GROUP BY
ORDER BY
LIMIT
OFFSET
子句的文档可以在Couchbase 网站上找到。
示例
<?php
declare(strict_types=1);
namespace Some\Name\Space;
use BowlOfSoup\CouchbaseAccessLayer\Exception\CouchbaseQueryException;
use BowlOfSoup\CouchbaseAccessLayer\Factory\ClusterFactory;
use BowlOfSoup\CouchbaseAccessLayer\Model\Result;
use BowlOfSoup\CouchbaseAccessLayer\Repository\BucketRepository;
class Foo
{
public function exampleUsingTheQueryBuilder()
{
$result = $this->querySomeBucket();
foreach ($result as $item) {
// each $item contains a Couchbase document which matched the query.
}
// $result implements the \JsonSerializableInterface.
$jsonEncoded = json_encode($result);
// These (can) only differ when query with limit/offset is done.
$resultCount = $result->getCount();
$resultTotalCount = $result->getTotalCount();
// Return just the data you queried
$justTheData = $result->get();
// Get only one (or the first) result
$singleResult = $result->getFirstResult();
}
public function exampleUsingDirectCalls()
{
$clusterFactory = new ClusterFactory('couchbaseHost', 'couchbaseUsername', 'couchbasePassword');
$bucketRepository = new BucketRepository('someBucketName', $clusterFactory);
$bucketRepository->upsert('some document id', 'the content of the document');
$bucketRepository->remove('some document id);
$documentContent = $bucketRepository->getByKey('some document id');
}
public function exampleExecutingManualQuery()
{
$clusterFactory = new ClusterFactory('couchbaseHost', 'couchbaseUsername', 'couchbasePassword');
$bucketRepository = new BucketRepository('someBucketName', $clusterFactory);
// Creating an index for a bucket
$bucketRepository->executeQuery(
CREATE INDEX i_foo_field_name
ON `' . $bucketRepository->getBucketName() . '`(`field`, `data.name`)
WHERE (`documentType` = "foo")
);
$result = $bucketRepository->executeQuery(
'SELECT someField FROM `bucket name` WHERE someOtherField = $someOtherField',
['someOtherField' => 'some value']
);
// This will only return one result.
$result = $bucketRepository->executeQueryWithOneResult();
}
/**
* @return \BowlOfSoup\CouchbaseAccessLayer\Model\Result
*/
private function querySomeBucket(): Result
{
$clusterFactory = new ClusterFactory('couchbaseHost', 'couchbaseUsername', 'couchbasePassword');
$bucketRepository = new BucketRepository('someBucketName', $clusterFactory);
$queryBuilder = $bucketRepository->createQueryBuilder();
$queryBuilder
->select('data.name')
// See that you can put in your own logic, like COUNT and such:
->select('COUNT(data.name) AS count')
->where('foo = $foo')
->where('someField = $someField')
->where('type = $type');
$queryBuilder->setParameters([
'foo' => 'someFooValue',
'someKey' => 'someKeyValue',
'type' => 'someDocumentType',
]);
$queryBuilder
->where('data.creationDate >= $creationDate')
->setParameter('creationDate', '2019-01-10');
$queryBuilder
->groupBy('data.name')
->limit(10)
->offset(20);
try {
return $bucketRepository->getResult($queryBuilder);
} catch (CouchbaseQueryException $e) {
// Something went wrong.
}
}
}
对于 WHERE
子句,你可以自己添加逻辑
$queryBuilder->where('CONTAINS(SUBSTR(name,0,1),"C")');
对于 GROUP BY
子句,你也可以自己添加逻辑
$queryBuilder->groupBy('city LETTING MinimumThingsToSee = 400 HAVING COUNT(DISTINCT name) > MinimumThingsToSee');
在 FROM 语句中使用子查询
当在 FROM
语句中使用子查询(使用 $queryBuilder->fromSubQuery()
)并使用参数时,请将参数放在 'master' 查询构建器中。更多信息可以在此页上找到。
$queryBuilderForSubSelect = new QueryBuilder('bucket_name');
$queryBuilderForSubSelect->where('type = $foo');
$queryBuilder = new QueryBuilder('bucket_name');
$queryBuilder
->select('q1.someFieldOfTheSubSelect')
->fromSubQuery($queryBuilderForSubSelect, 'q1')
->setParameter('foo', 'value1');
单元测试
在之前的版本中,测试使用了名为 CouchbaseMock.jar 的虚拟 Couchbase 实例。这与最新的 Couchbase 版本不兼容。因此,当前情况有一个 Docker 设置,包含实际的 Couchbase 实例用于测试。假设你已经安装了 Docker,你可以通过运行以下命令来运行测试
docker compose up -d
docker exec -ti couchbase-access-layer-php-1 bash
vendor/bin/phpunit