PHP の命名制限を克服して MongoDB オペレーターをモデル化する方法

DDD
リリース: 2023-10-18 10:58:01
転載
773 人が閲覧しました

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 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:Jérôme TAMARELLE
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!