Wprowadzenie
Myślę, że ocena zapytań JSON podobnych do MongoDB w PHP dała wszystkie potrzebne informacje. wszystko, czego potrzebujesz, to kreatywność z rozwiązaniem i osiągnięcie tego, czego chcesz
Tablica
Załóżmy, że mamy następujący json
konwertowane na tablicę
$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);
Przykład 1
sprawdź, czy key
- Different
byłoby tak proste jak
echo new ArrayCollection($array, array("key" => "Diffrent"));
Wyjście
{"3":{"key":"Diffrent","value":"cool","children":{"tech":"json","lang":"php","year":2013}}}
Przykład 2 Sprawdź, czy release year
jest 2013
echo new ArrayCollection($array, array("release.year" => 2013));
Wyjście
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Przykład 3
Policz gdzie Year
jest 2012
$c = new ArrayCollection($array, array("release.year" => 2012));
echo count($c); // output 2
Przykład 4
Weźmy z twojego przykładu, gdzie chcesz sprawdzić version
jest grater than 22
$c = new ArrayCollection($array, array("release.version" => array('$gt'=>22)));
echo $c;
Wyjście
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Przykład 5
Sprawdź, czy release.arch
wartość to IN
zestaw taki jak [x86,x100]
(Przykład)
$c = new ArrayCollection($array, array("release.arch" => array('$in'=>array("x86","x100"))));
foreach($c as $var)
{
print_r($var);
}
Wyjście
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
)
)
Przykład 6
Korzystanie z opcji wywoływania
$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);
}
Wyjście
Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x86
[version] => 23
[year] => 2013
)
)
Przykład 7
Zarejestruj własną nazwę wyrażenia
$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;
Wyjście
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Używana klasa
Klasaclass 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);
}
}
Podsumowanie
Może nie obejmować wszystkich zaawansowanych funkcji i powinien mieć rozszerzalną architekturę
Powyższa klasa pokazuje typowy przykład tego, czego chcesz .. możesz łatwo decouple
it , rozszerz go o obsługę wyrażeń złożonych, takich jak $and
i $or
Obiekty wyrażeń zapytań podobne do MongoDB są łatwe do zrozumienia i użycia, zapewniając możliwość pisania czystego, zrozumiałego kodu, ponieważ zarówno zapytania, jak i obiekty do przeszukiwania są tablicami asocjacyjnymi.
Dlaczego nie po prostu napisać tablicy do MongoDB
? bazy danych zamiast pracy z tablicami ?? Jest bardziej wydajny i zaoszczędzi ci wielu kłopotów
Muszę również wspomnieć, że używaj najlepszego narzędzia do najlepszej pracy ... To, czego potrzebujesz, to w zasadzie funkcja bazy danych
Mówiąc ogólnie, jest to wygodna funkcja do wyodrębniania informacji z tablic php. Znając strukturę tablicy (arrayPath), pozwoli to na wykonywanie operacji na wielowymiarowych danych tablicowych, bez potrzeby wielu zagnieżdżonych pętli.
Przykład pokazuje, jak używać ścieżki do wyszukiwania wartości, ale nadal jesteś zależny od załadowania tablicy do pamięci i twojej klasy wykonującej wielokrotną rekurencję i pętle, co nie jest tak wydajne jak baza danych.
Doceniam wskazówki dotyczące architektury, pokrewny lub podobny kod, który może być dobrym przykładem praktyki tworzenia wyrażeń php "if..else" w locie.
Czy naprawdę masz na myśli, że chcesz, aby wszystkie te były tutaj ???