Présentation
Je pense que l'évaluation des requêtes JSON de type MongoDB en PHP a fourni toutes les informations dont vous avez besoin. tout ce dont vous avez besoin est d'être créatif avec la solution et vous obtenez ce que vous voulez
Le tableau
Supposons que nous ayons le suivant json
converti en tableau
$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);
Exemple 1
vérifier si key
- Different
serait aussi simple que
echo new ArrayCollection($array, array("key" => "Diffrent"));
Sortie
{"3":{"key":"Diffrent","value":"cool","children":{"tech":"json","lang":"php","year":2013}}}
Exemple 2 Vérifiez si release year
est 2013
echo new ArrayCollection($array, array("release.year" => 2013));
Sortie
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Exemple 3
Compter où Year
est 2012
$c = new ArrayCollection($array, array("release.year" => 2012));
echo count($c); // output 2
Exemple 4
Prenons de votre exemple où vous voulez vérifier version
est grater than 22
$c = new ArrayCollection($array, array("release.version" => array('$gt'=>22)));
echo $c;
Sortie
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Exemple 5
Vérifiez si release.arch
la valeur est IN
un ensemble tel que [x86,x100]
(Exemple)
$c = new ArrayCollection($array, array("release.arch" => array('$in'=>array("x86","x100"))));
foreach($c as $var)
{
print_r($var);
}
Sortie
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
)
)
Exemple 6
Utilisation de Callable
$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);
}
Sortie
Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x86
[version] => 23
[year] => 2013
)
)
Exemple 7
Enregistrez votre propre nom d'expression
$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;
Sortie
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Classe utilisée
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);
}
}
Résumé
Il peut ne pas couvrir toutes les fonctionnalités avancées et doit avoir une architecture extensible
La classe ci-dessus montre un exemple typique de ce que vous voulez .. vous pouvez facilement decouple
it , étendez-le pour prendre en charge les expressions composées telles que $and
et $or
Les objets d'expression de requête de type MongoDB sont faciles à comprendre et à utiliser, offrant la possibilité d'écrire du code propre et explicite, car la requête et les objets dans lesquels rechercher sont des tableaux associatifs.
Pourquoi ne pas simplement écrire le tableau dans un MongoDB
base de données plutôt que de travailler avec des tableaux ?? C'est plus efficace et cela vous éviterait bien des soucis
Je dois également mentionner qu'utiliser le meilleur outil pour le meilleur travail... Ce que vous voulez est essentiellement une fonction d'une base de données
Fondamentalement, c'est une fonction pratique pour extraire des informations à partir de tableaux php. Connaissant la structure du tableau (le arrayPath), cela permettra d'effectuer des opérations sur des données de tableaux multidimensionnels, sans avoir besoin de plusieurs boucles imbriquées.
L'exemple montre comment utiliser un chemin pour rechercher une valeur, mais vous dépendez toujours du chargement du tableau en mémoire et de votre classe effectuant plusieurs boucles de récursivité, ce qui n'est pas aussi efficace qu'une base de données.
J'apprécie les conseils d'architecture, le code connexe ou similaire, qui peut être un exemple de bonne pratique pour créer des expressions php "if..else" à la volée.
Voulez-vous vraiment dire que vous voulez tous ceux qui sont juste ici ???