如何克服PHP的命名限制来建模MongoDB运算符
MongoDB 提供了包括 PHP 在内的各种语言的驱动程序。为了简化在 PHP 中创建聚合管道的过程,我们需要将所有阶段和运算符建模为可以组合的函数。
聚合管道是“阶段”文档的列表。我们将举一个使用 进行查询$match和连接的示例$lookup:
db.orders.aggregate([ { $match: { $or: [ { status: "shipped" }, { created_at: { $gte: ISODate("2023-01-01T00:00:00Z") } } ] } }, { $lookup: { from: "inventory", localField: "product_id", foreignField: "product_id", as: "inventory_docs" } } ])
每个带有美元前缀的键都是我们要为其提供工厂方法的运算符。
命名空间函数
最明显的解决方案是创建命名空间函数,例如:MongoDBOperatoreqof$eq运算符。
namespace MongoDB\Operator; function eq(mixed $value): array { return ['$eq' => $value]; } function lookup(string $from, string $localField, string $foreignField, string $as): array { return ['$lookup' => [ 'from' => $from, 'localField' => $localField, 'foreignField' => $foreignField, 'as' => $as, ]]; }
使用带有命名参数的函数,管道将用 PHP 编写:
pipeline( match( or( query(status: eq('shipped')), query(date: gte(new UTCDateTime())), ), ), lookup(from: 'inventory', localField: 'product_id', foreignField: 'product_id', as: 'inventory_docs'), );
但是,某些运算符名称与PHP 中的保留关键字冲突。我们不能创建具有以下名称的函数(全局或命名空间):
and,
or,
match,
unset,
set,
为函数名添加后缀
为了避免保留名称的问题,我们可以在函数名称中添加前缀或后缀。
以运算符类型作为后缀:
function andQuery(...) { /* ... */ } function matchStage(...) { /* ... */ }
带下划线:
function _and(...) { /* ... */ } function _match(...) { /* ... */ }
或者使用表情符号。漂亮,但不实用:
function ?and(...) { /* ... */ } function ?match(...) { /* ... */ }
静态类方法
碰巧的是,方法名称的保留关键字列表较短。我们可以在类上创建静态方法。
final class Stage { public static function lookup(...) { /* ... */ } public static function match(...) { /* ... */ } } final class Query { public static function and(...) { /* ... */ } public static function eq(...) { /* ... */ } }
字写得有点长了,不过还是可读的。
new Pipeline( Stage::match( Query::or( Query::query(status: Query::eq('shipped')), Query::query(date: Query::gte(new UTCDateTime())), ), ), Stage::lookup(from: 'inventory', localField: 'product_id', foreignField: 'product_id', as: 'inventory_docs'), );
为了防止任何人创建此类的实例,我们可以将构造函数设为私有。
final class Operator { // ... private function __construct() {} // This constructor cannot be called }
我们也可以使用enum不带外壳的。Enum 接受静态方法并且不能实例化。
enum Query { public static function and() { /* ... */ } public static function eq() { /* ... */ } }
类和枚举静态方法都可以以相同的方式调用。
变量中的闭包
由于找不到理想的解决方案,我们开始热衷于不太可能的解决方案。
如果我们想要一个看起来与 MongoDB 语法非常相似且没有名称限制的简短语法,那么我们就会想到使用变量来存储闭包。请注意,这(...)是PHP 8.1 中创建闭包的新语法。
$eq = Operator::eq(...); $and = Operator::and(...);
$PHP 使用美元符号作为变量前缀,MongoDB 使用相同的运算符作为前缀。
pipeline( $match( $or( $query(status: $eq('shipped')), $query(date: $gte(new UTCDateTime())), ), ), $lookup(from: 'inventory', localField: 'product_id', foreignField: 'product_id', as: 'inventory_docs'), );
库可以将这些闭包作为数组提供。
enum Query { public static function and(array ...$queries) { /* ... */ } public static function eq(mixed $value) { /* ... */ } public static function query(mixed ...$query) { /* ... */ } /** @return array{and:callable,eq:callable,query:callable} */ public static function functions(): array { return [ 'and' => self::and(...), 'eq' => self::eq(...), 'query' => self::query(...), ]; } }
获取所有变量的语法有点冗长,但仍然可读。
['and' => $and, 'eq' => $eq, 'query' => $query] = Query::functions();
extract我们可以使用 Laravel 中经常使用但 PHPStorm 和静态分析工具非常讨厌的神奇功能将所有变量导入到当前作用域中。
extract(Query::functions()); var_dump($and( $query(foo: $eq(5)), $query(bar: $eq(10)) )); // INFO: MixedFunctionCall - Cannot call function on mixed
结论
正如您所看到的,在使用保留关键字时,PHP 中的函数命名并不那么简单。
以上是如何克服PHP的命名限制来建模MongoDB运算符的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

在PHP8 中,match表达式是一种新的控制结构,用于根据表达式的值返回不同的结果。1)它类似于switch语句,但返回值而非执行语句块。2)match表达式使用严格比较(===),提升了安全性。3)它避免了switch语句中可能的break遗漏问题,增强了代码的简洁性和可读性。

在PHP中可以通过使用不可预测的令牌来有效防范CSRF攻击。具体方法包括:1.生成并在表单中嵌入CSRF令牌;2.在处理请求时验证令牌的有效性。

在PHP中,final关键字用于防止类被继承和方法被重写。1)标记类为final时,该类不能被继承。2)标记方法为final时,该方法不能被子类重写。使用final关键字可以确保代码的稳定性和安全性。

PHP中的...(splat)操作符用于函数参数和数组解包,提升代码简洁性和效率。1)函数参数解包:将数组元素作为参数传递给函数。2)数组解包:将一个数组解包到另一个数组中或作为函数参数。

PHP中的严格类型通过在文件顶部添加declare(strict_types=1);来启用。1)它强制对函数参数和返回值进行类型检查,防止隐式类型转换。2)使用严格类型可以提高代码的可靠性和可预测性,减少bug,提升可维护性和可读性。

Composer是PHP的依赖管理工具。使用Composer的核心步骤包括:1)在composer.json中声明依赖,如"stripe/stripe-php":"^7.0";2)运行composerinstall下载并配置依赖;3)通过composer.lock和autoload.php管理版本和自动加载。Composer简化了依赖管理,提升了项目效率和可维护性。

PHP的未来将通过适应新技术趋势和引入创新特性来实现:1)适应云计算、容器化和微服务架构,支持Docker和Kubernetes;2)引入JIT编译器和枚举类型,提升性能和数据处理效率;3)持续优化性能和推广最佳实践。
