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,
또는
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 자주 사용되지만 PHPStorm 및 정적 분석 도구에서는 싫어하는 Laravel의 마법 같은 기능을 사용하여 모든 변수를 현재 범위로 가져올 수 있습니다.
extract(Query::functions()); var_dump($and( $query(foo: $eq(5)), $query(bar: $eq(10)) )); // INFO: MixedFunctionCall - Cannot call function on mixed
결론
보시다시피 PHP에서 예약어를 사용하면 함수 이름 지정이 그리 간단하지 않습니다.
위 내용은 MongoDB 연산자를 모델링하기 위해 PHP의 명명 제한을 극복하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!