Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk mengatasi had penamaan PHP untuk memodelkan pengendali MongoDB

Bagaimana untuk mengatasi had penamaan PHP untuk memodelkan pengendali MongoDB

DDD
DDDke hadapan
2023-10-18 10:56:00797semak imbas

MongoDB menyediakan pemacu untuk pelbagai bahasa termasuk PHP. Untuk memudahkan proses mencipta saluran paip pengagregatan dalam PHP, kita perlu memodelkan semua peringkat dan pengendali sebagai fungsi yang boleh digubah.

Saluran paip pengagregatan ialah senarai dokumen "peringkat". Kami akan memberikan contoh pertanyaan $match dan menyertai menggunakan $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"
        }
    }
])

Setiap kunci dengan awalan dolar ialah operator yang kami mahu sediakan kaedah kilang.

Fungsi ruang nama

Penyelesaian yang paling jelas ialah mencipta fungsi ruang nama, contohnya: operator 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,
    ]];
}

Menggunakan fungsi dengan parameter bernama, paip akan ditulis dalam 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'),
);

Walau bagaimanapun, sesetengah nama operator bercanggah dengan kata kunci simpanan dalam PHP. Kami tidak boleh mencipta fungsi (global atau ruang nama) dengan nama berikut:

dan,

atau,

padanan,

nyahset,

set,

Tambah akhiran pada nama fungsi

Untuk mengelakkan masalah pengekalan nama, kita boleh menambah awalan atau akhiran pada nama fungsi.

Diakhiri dengan jenis operator:

function andQuery(...) { /* ... */ }
function matchStage(...) { /* ... */ }

Bergaris bawah:

function _and(...) { /* ... */ }
function _match(...) { /* ... */ }

Atau gunakan emotikon. Cantik, tetapi tidak praktikal:

function ?and(...) { /* ... */ }
function ?match(...) { /* ... */ }

Kaedah kelas statik

Apabila berlaku, senarai kata kunci yang dikhaskan untuk nama kaedah adalah lebih pendek. Kita boleh mencipta kaedah statik pada kelas.

final class Stage {
    public static function lookup(...) { /* ... */ }
    public static function match(...) { /* ... */ }
}
final class Query {
    public static function and(...) { /* ... */ }
    public static function eq(...) { /* ... */ }
}

Tulisannya agak panjang, tetapi masih boleh dibaca.

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'),
);

Untuk menghalang sesiapa daripada mencipta tika kelas ini, kita boleh menjadikan pembina peribadi.

final class Operator {
    // ...
    private function __construct() {} // This constructor cannot be called 
}

Kita juga boleh menggunakan enum tanpa cangkerang. Enum menerima kaedah statik dan tidak boleh digunakan.

enum Query {
    public static function and() { /* ... */ }
    public static function eq() { /* ... */ }
}

Kedua-dua kaedah statik kelas dan penghitungan boleh dipanggil dengan cara yang sama.

Penutupan dalam pembolehubah

Memandangkan kami tidak dapat mencari penyelesaian yang ideal, kami mula bersemangat tentang penyelesaian yang tidak mungkin.

Jika kami mahukan sintaks pendek yang kelihatan sangat serupa dengan sintaks MongoDB tanpa sekatan nama, maka kami akan memikirkan untuk menggunakan pembolehubah untuk menyimpan penutupan. Ambil perhatian bahawa ini (...) ialah sintaks baharu untuk membuat penutupan dalam PHP 8.1.

$eq = Operator::eq(...);
$and = Operator::and(...);

$PHP menggunakan tanda dolar untuk awalan berubah dan MongoDB menggunakan operator yang sama untuk awalan.

pipeline(
    $match(
        $or(
            $query(status: $eq('shipped')),
            $query(date: $gte(new UTCDateTime())),
        ),
    ),
    $lookup(from: 'inventory', localField: 'product_id', foreignField: 'product_id', as: 'inventory_docs'),
);

Pustaka boleh menyediakan penutupan ini sebagai tatasusunan.

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(...),
        ];
    }
}

Sintaks untuk mendapatkan semua pembolehubah agak bertele-tele, tetapi masih boleh dibaca.

['and' => $and, 'eq' => $eq, 'query' => $query] = Query::functions();

ekstrak Kami boleh mengimport semua pembolehubah ke dalam skop semasa menggunakan ciri ajaib dalam Laravel yang sering digunakan tetapi dibenci oleh PHPStorm dan alat analisis statik.

extract(Query::functions());
var_dump($and(
    $query(foo: $eq(5)),
    $query(bar: $eq(10))
));
// INFO: MixedFunctionCall - Cannot call function on mixed

Kesimpulan

Seperti yang anda lihat, penamaan fungsi dalam PHP tidak semudah itu apabila menggunakan kata kunci simpanan.

Atas ialah kandungan terperinci Bagaimana untuk mengatasi had penamaan PHP untuk memodelkan pengendali MongoDB. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:Jérôme TAMARELLE. Jika ada pelanggaran, sila hubungi admin@php.cn Padam