Introduktion
Jeg tror, at evaluering af MongoDB-lignende JSON-forespørgsler i PHP har givet al den information, du har brug for. alt hvad du behøver er at være kreativ med løsningen, og du opnår det du ønsker
Arrayet
Lad os antage, at vi har følgende json
konverteret til array
$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);
Eksempel 1
tjek om key
- Different
ville være så simpelt som
echo new ArrayCollection($array, array("key" => "Diffrent"));
Output
{"3":{"key":"Diffrent","value":"cool","children":{"tech":"json","lang":"php","year":2013}}}
Eksempel 2 Tjek om release year
er 2013
echo new ArrayCollection($array, array("release.year" => 2013));
Output
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Eksempel 3
Tæl hvor Year
er 2012
$c = new ArrayCollection($array, array("release.year" => 2012));
echo count($c); // output 2
Eksempel 4
Lad os tage fra dit eksempel, hvor du vil kontrollere version
er grater than 22
$c = new ArrayCollection($array, array("release.version" => array('$gt'=>22)));
echo $c;
Output
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Eksempel 5
Tjek om release.arch
værdien er IN
et sæt såsom [x86,x100]
(Eksempel)
$c = new ArrayCollection($array, array("release.arch" => array('$in'=>array("x86","x100"))));
foreach($c as $var)
{
print_r($var);
}
Output
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
)
)
Eksempel 6
Bruger 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);
}
Output
Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x86
[version] => 23
[year] => 2013
)
)
Eksempel 7
Registrer dit eget udtryksnavn
$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;
Output
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Klasse brugt
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);
}
}
Oversigt
Det dækker muligvis ikke alle de avancerede funktioner og bør have en udvidelsesbar arkitektur
Ovenstående klasse viser et typisk eksempel på, hvad du ønsker .. du kan nemt decouple
it , udvide det til at understøtte sammensatte udtryk som $and
og $or
MongoDB-lignende forespørgselsudtryksobjekter er nemme at forstå og bruge, hvilket giver mulighed for at skrive ren, selvforklarende kode, fordi både forespørgsler og objekter at søge i er associative arrays.
Hvorfor ikke bare skrive arrayet til en MongoDB
database snarere end at arbejde med det arrays ?? Det er mere effektivt, og det ville spare dig for mange problemer
Jeg må også nævne, at brug det bedste værktøj til det bedste job ... Det du ønsker er dybest set en funktion af en database
Dybest set taler det om en praktisk funktion til at udtrække information fra php-arrays. Ved at kende array-strukturen (arrayPath), vil det gøre det muligt at udføre operationer på multidimensionelle array-data uden behov for flere indlejrede sløjfer.
Eksemplet viser, hvordan du bruger en sti til at søge efter værdi, men du er stadig afhængig af at indlæse arrayet til hukommelsen, og at din klasse udfører flere rekursion og loops, hvilket ikke er så effektivt som en database.
Jeg sætter pris på arkitekturtips, relateret eller lignende kode, som kan være et eksempel på god praksis til at bygge php "hvis..else"-udtryk i farten.
Mener du virkelig, at du vil have alle dem herinde ???