Giới thiệu
Tôi nghĩ rằng Đánh giá các truy vấn JSON giống MongoDB trong PHP đã cung cấp tất cả Thông tin bạn cần. tất cả những gì bạn cần là sáng tạo với giải pháp và bạn đạt được điều mình muốn
Mảng
Giả sử chúng ta có json
sau được chuyển đổi thành mảng
$json = '[{
"name":"Mongo",
"type":"db",
"release":{
"arch":"x86",
"version":22,
"year":2012
}
},
{
"name":"Mongo",
"type":"db",
"release":{
"arch":"x64",
"version":21,
"year":2012
}
},
{
"name":"Mongo",
"type":"db",
"release":{
"arch":"x86",
"version":23,
"year":2013
}
},
{
"key":"Diffrent",
"value":"cool",
"children":{
"tech":"json",
"lang":"php",
"year":2013
}
}
]';
$array = json_decode($json, true);
Ví dụ 1
kiểm tra xem key
- Different
sẽ đơn giản như
echo new ArrayCollection($array, array("key" => "Diffrent"));
Đầu ra
{"3":{"key":"Diffrent","value":"cool","children":{"tech":"json","lang":"php","year":2013}}}
Ví dụ 2 Kiểm tra xem release year
là 2013
echo new ArrayCollection($array, array("release.year" => 2013));
Đầu ra
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Ví dụ 3
Đếm nơi Year
là 2012
$c = new ArrayCollection($array, array("release.year" => 2012));
echo count($c); // output 2
Ví dụ 4
Hãy lấy ví dụ của bạn nơi bạn muốn kiểm tra version
grater than 22
$c = new ArrayCollection($array, array("release.version" => array('$gt'=>22)));
echo $c;
Đầu ra
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Ví dụ 5
Kiểm tra xem release.arch
giá trị là IN
một tập hợp chẳng hạn như [x86,x100]
(Ví dụ)
$c = new ArrayCollection($array, array("release.arch" => array('$in'=>array("x86","x100"))));
foreach($c as $var)
{
print_r($var);
}
Đầu ra
Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x86
[version] => 22
[year] => 2012
)
)
Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x86
[version] => 23
[year] => 2013
)
)
Ví dụ 6
Sử dụng có thể gọi được
$year = 2013;
$expression = array("release.year" => array('$func' => function ($value) use($year) {
return $value === 2013;
}));
$c = new ArrayCollection($array, $expression);
foreach ( $c as $var ) {
print_r($var);
}
Đầu ra
Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x86
[version] => 23
[year] => 2013
)
)
Ví dụ 7
Đăng ký tên biểu thức của riêng bạn
$c = new ArrayCollection($array, array("release.year" => array('$baba' => 3)), false);
$c->register('$baba', function ($a, $b) {
return substr($a, - 1) == $b;
});
$c->parse();
echo $c;
Đầu ra
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Lớp được sử dụng
class ArrayCollection implements IteratorAggregate, Countable, JsonSerializable {
private $array;
private $found = array();
private $log;
private $expression;
private $register;
function __construct(array $array, array $expression, $parse = true) {
$this->array = $array;
$this->expression = $expression;
$this->registerDefault();
$parse === true and $this->parse();
}
public function __toString() {
return $this->jsonSerialize();
}
public function jsonSerialize() {
return json_encode($this->found);
}
public function getIterator() {
return new ArrayIterator($this->found);
}
public function count() {
return count($this->found);
}
public function getLog() {
return $this->log;
}
public function register($offset, $value) {
if (strpos($offset, '$') !== 0)
throw new InvalidArgumentException('Expresiion name must always start with "$" sign');
if (isset($this->register[$offset]))
throw new InvalidArgumentException(sprintf('Expression %s already registred .. Please unregister It first'));
if (! is_callable($value)) {
throw new InvalidArgumentException(sprintf('Only callable value can be registred'));
}
$this->register[$offset] = $value;
}
public function unRegister($offset) {
unset($this->register[$offset]);
}
public function parse() {
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($this->array));
foreach ( $it as $k => $items ) {
if ($this->evaluate($this->getPath($it), $items)) {
$this->found[$it->getSubIterator(0)->key()] = $this->array[$it->getSubIterator(0)->key()];
}
}
}
private function registerDefault() {
$this->register['$eq'] = array($this,"evaluateEqal");
$this->register['$not'] = array($this,"evaluateNotEqual");
$this->register['$gte'] = array($this,"evaluateGreater");
$this->register['$gt'] = array($this,"evaluateGreater");
$this->register['$lte'] = array($this,"evaluateLess");
$this->register['$lt'] = array($this,"evaluateLess");
$this->register['$in'] = array($this,"evalueateInset");
$this->register['$func'] = array($this,"evalueateFunction");
$this->register['$fn'] = array($this,"evalueateFunction");
$this->register['$f'] = array($this,"evalueateFunction");
}
private function log($log) {
$this->log[] = $log;
}
private function getPath(RecursiveIteratorIterator $it) {
$keyPath = array();
foreach ( range(1, $it->getDepth()) as $depth ) {
$keyPath[] = $it->getSubIterator($depth)->key();
}
return implode(".", $keyPath);
}
private function checkType($a, $b) {
if (gettype($a) != gettype($b)) {
$this->log(sprintf("%s - %s is not same type of %s - %s", json_encode($a), gettype($a), json_encode($b), gettype($b)));
return false;
}
return true;
}
private function evaluate($key, $value) {
$o = $r = 0; // Obigation & Requirement
foreach ( $this->expression as $k => $options ) {
if ($k !== $key)
continue;
if (is_array($options)) {
foreach ( $options as $eK => $eValue ) {
if (strpos($eK, '$') === 0) {
$r ++;
$callable = $this->register[$eK];
$callable($value, $eValue) and $o ++;
} else {
throw new InvalidArgumentException('Missing "$" in expession key');
}
}
} else {
$r ++;
$this->evaluateEqal($value, $options) and $o ++;
}
}
return $r > 0 && $o === $r;
}
private function evaluateEqal($a, $b) {
return $a == $b;
}
private function evaluateNotEqual($a, $b) {
return $a != $b;
}
private function evaluateLess($a, $b) {
return $this->checkType($a, $b) and $a < $b;
}
private function evaluateGreater($a, $b) {
return $this->checkType($a, $b) and $a > $b;
}
private function evalueateInset($a, array $b) {
return in_array($a, $b);
}
private function evalueateFunction($a, callable $b) {
return $b($a);
}
}
Tóm tắt
Nó có thể không bao gồm tất cả các tính năng nâng cao và phải có kiến trúc có thể mở rộng
Lớp trên cho thấy một ví dụ điển hình về những gì bạn muốn .. bạn có thể dễ dàng decouple
nó, mở rộng nó để hỗ trợ các biểu thức ghép như $and
và $or
Các đối tượng biểu thức truy vấn giống MongoDB dễ hiểu và dễ sử dụng, cung cấp khả năng viết mã rõ ràng, tự giải thích vì cả truy vấn và đối tượng cần tìm kiếm đều là các mảng liên kết.
Tại sao không chỉ ghi mảng vào MongoDB
cơ sở dữ liệu hơn là làm việc nó mảng ?? Nó hiệu quả hơn và nó sẽ giúp bạn tiết kiệm rất nhiều rắc rối
Tôi cũng phải đề cập đến việc sử dụng công cụ tốt nhất cho công việc tốt nhất ... Điều bạn muốn về cơ bản là một chức năng của Cơ sở dữ liệu
Về cơ bản, nó là một chức năng thuận tiện để trích xuất thông tin từ các mảng php. Biết cấu trúc mảng (arrayPath), nó sẽ cho phép thực hiện các thao tác trên dữ liệu mảng nhiều chiều mà không cần nhiều vòng lặp lồng nhau.
Ví dụ cho thấy cách sử dụng đường dẫn để tìm kiếm giá trị nhưng bạn vẫn phụ thuộc vào việc tải mảng vào bộ nhớ và lớp của bạn thực hiện nhiều vòng lặp ans đệ quy không hiệu quả như cơ sở dữ liệu.
Tôi đánh giá cao các mẹo về kiến trúc, mã liên quan hoặc tương tự, đây có thể là một ví dụ thực tiễn tốt để xây dựng nhanh các biểu thức php "if..else".
Ý bạn thực sự là bạn muốn tất cả những thứ đó chỉ ở đây ???