Bagaimana untuk mengatasi had penamaan PHP untuk memodelkan pengendali MongoDB

DDD
Lepaskan: 2023-10-18 10:58:01
ke hadapan
774 orang telah melayarinya

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"
        }
    }
])
Salin selepas log masuk

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,
    ]];
}
Salin selepas log masuk

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'),
);
Salin selepas log masuk

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(...) { /* ... */ }
Salin selepas log masuk

Bergaris bawah:

function _and(...) { /* ... */ }
function _match(...) { /* ... */ }
Salin selepas log masuk

Atau gunakan emotikon. Cantik, tetapi tidak praktikal:

function ?and(...) { /* ... */ }
function ?match(...) { /* ... */ }
Salin selepas log masuk

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(...) { /* ... */ }
}
Salin selepas log masuk

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'),
);
Salin selepas log masuk

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

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

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() { /* ... */ }
}
Salin selepas log masuk

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(...);
Salin selepas log masuk

$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'),
);
Salin selepas log masuk

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(...),
        ];
    }
}
Salin selepas log masuk

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

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

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
Salin selepas log masuk

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!

Label berkaitan:
sumber:Jérôme TAMARELLE
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!