Реализация goMongoDB-подобного вычисления объекта выражения Query
Я искал MongoDb-подобную ( http://docs.mongodb.org/manual/applications/read/, docs.mongodb.org/manual/reference/operators/) реализацию функции оценки объекта выражения запроса или класс. Он может охватывать не все расширенные функции и должен иметь расширяемую архитектуру.
MongoDB-подобные объекты выражений запросов просты для понимания и использования, обеспечивая возможность написания чистого, самообъяснимого кода, поскольку и запрос, и объекты для поиска являются ассоциативными массивами.
По сути, это удобная функция для извлечения информации из массивов php. Зная структуру массива (arrayPath), он позволит выполнять операции над многомерными массивами данных, не требуя множественных вложенных циклов.
Если вы не знакомы с MongoDb, взгляните на заданный объект выражения и массив для поиска.
Я написал это как строку JSON для простоты. Содержимое объекта не имеет смысла, просто показывает синтаксис запроса MongoDb.
MongoDb-подобный объект выражения запроса
{
"name": "Mongo",
"type": "db",
"arch": {
"$in": [
"x86",
"x64"
]
},
"version": {
"$gte": 22
},
"released": {
"$or": {
"$lt": 2013,
"$gt": 2012
}
}
}
Массив для поиска
[
{
"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
}
}
]
Найти с использованием монго-подобных выражений запросов
Итак, с помощью функции мы сможем выполнить следующий запрос к целевому массиву.
$found=findLikeMongo($array, $queryExpr); //resulting in a $array[0] value;
//@return found array
Получить путь к массиву с помощью монго-подобных выражений запросов
$arrayPath=getPathFromMongo($array, $queryExpr);// resulting in array("0")
//@return array path, represented as an array where entries are consecutive keys.
Домашнее задание
Я обнаружил, что goessner.net/articles/JsonPath/ может покрыть мои потребности (не точное совпадение, потому что он использует Xpath-подобные выражения), предостережение в том, что он в значительной степени опирается на регулярные выражения и разбор строк, что определенно замедлится он ниже по сравнению с реализацией только для массива (как в JSON).
Также я нашел похожий вопрос здесь, @stackru Оценка MongoDB-подобных запросов JSON в PHP. Полученный ответ состоял в том, чтобы использовать некоторые функции SPL, которых я использовал, чтобы избежать большей части времени.
Интересно, если автор придумал функцию, он пытался развиваться.Возможная реализация arrayPath была найдена по адресу thereisamoduleforthat.com/content/dealing-deep-arrays-php, поэтому недостатком этой реализации является то, что она опирается на указатели.
Я знаю, что это не тривиальный вопрос с ответом oneliner, поэтому я задаю его, прежде чем начать фактическое развитие моего собственного класса.
Я ценю советы по архитектуре, связанный или похожий код, который может быть хорошим примером для построения выражений php "if..else" на лету. выделенный текст
Как написать версию без SPL?
@Baba предоставил отличный класс, который написан с использованием SPL. Интересно, как переписать этот код без SPL.
Есть две причины для этого
- Многократный вызов класса вызовет перегрузку функции, чего можно избежать, переписав ее в сыром PHP.
- он был бы легко переносим на необработанный Javascript, где SPL недоступен, что облегчало бы обслуживание кода на обеих платформах.
Результаты
Созданный класс ArrayQuery опубликован на Github, рассмотрите возможность проверки хранилища на наличие обновлений.
SPL, сырая версия PHP и вывод профилировщика Chequer2 FORP
Вкратце-
- Необработанная версия PHP работает в 10 раз быстрее, чем версия SPL, занимая на 20% меньше памяти.
- Класс Chequer2 работает на 40% медленнее, чем класс PHP SPL, и почти в 20 раз медленнее, чем сырая версия PHP.
- MongoDb является самым быстрым (в 10 раз быстрее, чем сырая реализация PHP и потребляет в 5 раз меньше памяти), не используйте эти классы, если вы не уверены, что хотите избежать взаимодействия с MongoDb.
Версия MongoDb
Версия SPL
Необработанная версия PHP(последняя версия класса ArrayQuery)
Версия Chequer2
Код профилирования эталонного теста MongoDb
$m = new MongoClient(); // connect
$db = $m->testmongo; // select a database
$collection = $db->data;
$loops=100;
for ($i=0; $i<$loops; $i++) {
$d = $collection->find(array("release.year" => 2013));
}
print_r( iterator_to_array($d) );
PHP с профилирующим кодом класса SPL
include('data.php');
include('phpmongo-spl.php');
$s = new ArrayCollection($array, array("release.year" => 2013),false);
$loops=100;
for ($i=0; $i<$loops; $i++) {
$d = $s->parse();
}
print_r( $d );
Функция parse() класса SPL была немного изменена, чтобы возвращать значение после выполнения, ее также можно изменить, чтобы она принимала выражение, но это не важно для целей профилирования, поскольку выражение каждый раз переоценивается.
необработанный код профилирования PHP(последний класс ArrayQuery)
include('data.php');
include('phpmongo-raw.php');
$s = new ArrayStandard($array);
$loops=100;
for ($i=0; $i<$loops; $i++) {
$d = $s->find(array("release.year" => 2013));
}
print_r( $d );
chequer2 PHP профилирующий код
<?php
include('data.php');
include('../chequer2/Chequer.php');
$query=array("release.year" => 2013);
$loops=100;
for ($i=0; $i<$loops; $i++) {
$result=Chequer::shorthand('(.release.year > 2012) ? (.) : NULL')
->walk($array);
}
print_r($result);
?>
использованные данные (такие же, как @baba в ответе)
$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);
слегка измененный пример загрузчика пользовательского интерфейса forp-ui (вызывается с помощью?profile=FILE_TO_PROFILE)
<!doctype html>
<html>
<head>
<style>
body {margin : 0px}
</style>
</head>
<body>
<div class="forp"></div>
<?php
register_shutdown_function(
function() {
// next code can be append to PHP scripts in dev mode
?>
<script src="../forp-ui/js/forp.min.js"></script>
<script>
(function(f) {
f.find(".forp")
.each(
function(el) {
el.css('margin:50px;height:300px;border:1px solid #333');
}
)
.forp({
stack : <?php echo json_encode(forp_dump()); ?>,
//mode : "fixed"
})
})(forp);
</script>
<?php
}
);
// start forp
forp_start();
// our PHP script to profile
include($_GET['profile']);
// stop forp
forp_end();
?>
</body>
</html>
2 ответа
Последнее обновление
@baba предоставила отличную сырую PHP-версию класса, реализующую оценку объекта выражения запроса в виде MongoDB, но структура вывода немного отличается, я имею в виду точечную запись в выходных данных вложенного массива ( [release.arch] => x86), вместо обычных массивов ( [release] => Array([arch] => x86)). Буду признателен за совет, как сделать класс полностью совместимым с mongoDB в этом порядке, так как он, похоже, строго связан с реализацией класса PHP.
================================================== =====================
Ответ:
То, что вы хотите, очень легко, все, что вам нужно, это 2 corrections
в текущем цикле ввода и вывода кода, и вы получите ваш новый формат.
Что я имею в виду?
А. Изменен
foreach ( $array as $part ) {
$this->flatten[] = $this->convert($part);
}
к
foreach ( $array as $k => $part ) {
$this->flatten[$k] = $this->convert($part);
}
Б. изменен
foreach ( $this->flatten as $data ) {
$this->check($find, $data, $type) and $f[] = $data;
}
Для того, чтобы:
foreach ( $this->flatten as $k => $data ) {
$this->check($find, $data, $type) and $f[] = $this->array[$k];
}
Новый массив для отдыха
$json = '[
{
"name": "Mongo",
"release": {
"arch": "x86",
"version": 22,
"year": 2012
},
"type": "db"
},
{
"name": "Mongo",
"release": {
"arch": "x64",
"version": 21,
"year": 2012
},
"type": "db"
},
{
"name": "Mongo",
"release": {
"arch": "x86",
"version": 23,
"year": 2013
},
"type": "db"
},
{
"name": "MongoBuster",
"release": {
"arch": [
"x86",
"x64"
],
"version": 23,
"year": 2013
},
"type": "db"
},
{
"children": {
"dance": [
"one",
"two",
{
"three": {
"a": "apple",
"b": 700000,
"c": 8.8
}
}
],
"lang": "php",
"tech": "json",
"year": 2013
},
"key": "Diffrent",
"value": "cool"
}
]';
$array = json_decode($json, true);
Простой тест
$s = new ArrayStandard($array);
print_r($s->find(array("release.arch"=>"x86")));
Выход
Array
(
[0] => Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x86
[version] => 22
[year] => 2012
)
)
[1] => Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x86
[version] => 23
[year] => 2013
)
)
)
Если вы также хотите сохранить оригинал array key position
вы можете иметь
foreach ( $this->flatten as $k => $data ) {
$this->check($find, $data, $type) and $f[$k] = $this->array[$k];
}
Просто для забавы
А. Поддержка regex
Просто для удовольствия я добавил поддержку $regex
с псевдонимом $preg
или же $match
а это значит, что вы можете иметь
print_r($s->find(array("release.arch" => array('$regex' => "/4$/"))));
Или же
print_r($s->find(array("release.arch" => array('$regex' => "/4$/"))));
Выход
Array
(
[1] => Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x64
[version] => 21
[year] => 2012
)
)
)
Б. Используйте простой массив, как queries
$queryArray = array(
"release" => array(
"arch" => "x86"
)
);
$d = $s->find($s->convert($queryArray));
$s->convert($queryArray)
преобразовал
Array
(
[release] => Array
(
[arch] => x86
)
)
к
Array
(
[release.arch] => x86
)
C. Модуль $mod
print_r($s->find(array(
"release.version" => array(
'$mod' => array(
23 => 0
)
)
)));
//Checks release.version % 23 == 0 ;
D. Подсчитать элементы с $size
print_r($s->find(array(
"release.arch" => array(
'$size' => 2
)
)));
// returns count(release.arch) == 2;
Проверить, соответствует ли он всем элементам в массиве $all
print_r($s->find(array(
"release.arch" => array(
'$all' => array(
"x86",
"x64"
)
)
)));
Выход
Array
(
[3] => Array
(
[name] => MongoBuster
[release] => Array
(
[arch] => Array
(
[0] => x86
[1] => x64
)
[version] => 23
[year] => 2013
)
[type] => db
)
)
F. Если вы не уверены в названии ключа элемента, вы можете использовать $has
это как opposite
из $in
print_r($s->find(array(
"release" => array(
'$has' => "x86"
)
)));
================================================== =====================
Старое обновление
@Baba предоставил отличный класс, который написан с использованием SPL. Интересно, как переписать этот код без SPL. Причина в том, что многократный вызов этого класса приведет к дополнительным затратам на функции, что позволит избежать переписывания его в сыром PHP и, возможно, использовать оператор goto в окончательной версии, чтобы избежать рекурсивных вызовов функций.
================================================== =====================
Так как ты не хочешь SPL
и функции.. это заняло некоторое время, но я смог придумать альтернативный класс, который также является гибким и простым в использовании
Чтобы избежать загрузки массива несколько раз, вы объявляете его один раз:
$array = json_decode($json, true);
$s = new ArrayStandard($array);
А. Найти где release.year
является 2013
$d = $s->find(array(
"release.year" => "2013"
));
print_r($d);
Выход
Array
(
[0] => Array
(
[name] => Mongo
[type] => db
[release.arch] => x86
[release.version] => 23
[release.year] => 2013
)
)
B. Впервые вы можете запустить комплекс $and
или же $or
заявление как найти где release.arch
знак равно x86
а также release.year
знак равно 2012
$d = $s->find(array(
"release.arch" => "x86",
"release.year" => "2012"
), ArrayStandard::COMPLEX_AND);
print_r($d);
Выход
Array
(
[0] => Array
(
[name] => Mongo
[type] => db
[release.arch] => x86
[release.version] => 22
[release.year] => 2012
)
)
C. Представьте себе гораздо более сложный запрос
$d = $s->find(array(
"release.year" => array(
'$in' => array(
"2012",
"2013"
)
),
"release.version" => array(
'$gt' => 22
),
"release.arch" => array(
'$func' => function ($a) {
return $a == "x86";
}
)
), ArrayStandard::COMPLEX_AND);
print_r($d);
Выход
Array
(
[0] => Array
(
[name] => Mongo
[type] => db
[release.arch] => x86
[release.version] => 23
[release.year] => 2013
)
)
Новый модифицированный класс
class ArrayStandard {
const COMPLEX_OR = 1;
const COMPLEX_AND = 2;
private $array;
private $tokens;
private $found;
function __construct(array $array) {
$this->array = $array;
foreach ( $array as $k => $item ) {
$this->tokens[$k] = $this->tokenize($item);
}
}
public function getTokens() {
return $this->tokens;
}
public function convert($part) {
return $this->tokenize($part, null, false);
}
public function find(array $find, $type = 1) {
$f = array();
foreach ( $this->tokens as $k => $data ) {
$this->check($find, $data, $type) and $f[$k] = $this->array[$k];
}
return $f;
}
private function check($find, $data, $type) {
$o = $r = 0; // Obigation & Requirement
foreach ( $data as $key => $value ) {
if (isset($find[$key])) {
$r ++;
$options = $find[$key];
if (is_array($options)) {
reset($options);
$eK = key($options);
$eValue = current($options);
if (strpos($eK, '$') === 0) {
$this->evaluate($eK, $value, $eValue) and $o ++;
} else {
throw new InvalidArgumentException('Missing "$" in expession key');
}
} else {
$this->evaluate('$eq', $value, $options) and $o ++;
}
}
}
if ($o === 0)
return false;
if ($type == self::COMPLEX_AND and $o !== $r)
return false;
return true;
}
private function getValue(array $path) {
return count($path) > 1 ? $this->getValue(array_slice($path, 1), $this->array[$path[0]]) : $this->array[$path[0]];
}
private function tokenize($array, $prefix = '', $addParent = true) {
$paths = array();
$px = empty($prefix) ? null : $prefix . ".";
foreach ( $array as $key => $items ) {
if (is_array($items)) {
$addParent && $paths[$px . $key] = json_encode($items);
foreach ( $this->tokenize($items, $px . $key) as $k => $path ) {
$paths[$k] = $path;
}
} else {
$paths[$px . $key] = $items;
}
}
return $paths;
}
private function evaluate($func, $a, $b) {
$r = false;
switch ($func) {
case '$eq' :
$r = $a == $b;
break;
case '$not' :
$r = $a != $b;
break;
case '$gte' :
case '$gt' :
if ($this->checkType($a, $b)) {
$r = $a > $b;
}
break;
case '$lte' :
case '$lt' :
if ($this->checkType($a, $b)) {
$r = $a < $b;
}
break;
case '$in' :
if (! is_array($b))
throw new InvalidArgumentException('Invalid argument for $in option must be array');
$r = in_array($a, $b);
break;
case '$has' :
if (is_array($b))
throw new InvalidArgumentException('Invalid argument for $has array not supported');
$a = @json_decode($a, true) ? : array();
$r = in_array($b, $a);
break;
case '$all' :
$a = @json_decode($a, true) ? : array();
if (! is_array($b))
throw new InvalidArgumentException('Invalid argument for $all option must be array');
$r = count(array_intersect_key($a, $b)) == count($b);
break;
case '$regex' :
case '$preg' :
case '$match' :
$r = (boolean) preg_match($b, $a, $match);
break;
case '$size' :
$a = @json_decode($a, true) ? : array();
$r = (int) $b == count($a);
break;
case '$mod' :
if (! is_array($b))
throw new InvalidArgumentException('Invalid argument for $mod option must be array');
list($x, $y) = each($b);
$r = $a % $x == 0;
break;
case '$func' :
case '$fn' :
case '$f' :
if (! is_callable($b))
throw new InvalidArgumentException('Function should be callable');
$r = $b($a);
break;
default :
throw new ErrorException("Condition not valid ... Use \$fn for custom operations");
break;
}
return $r;
}
private function checkType($a, $b) {
if (is_numeric($a) && is_numeric($b)) {
$a = filter_var($a, FILTER_SANITIZE_NUMBER_FLOAT);
$b = filter_var($b, FILTER_SANITIZE_NUMBER_FLOAT);
}
if (gettype($a) != gettype($b)) {
return false;
}
return true;
}
}
Вступление
Я думаю, что оценка MongoDB-подобных запросов JSON в PHP дала всю необходимую вам информацию. все, что вам нужно, это быть творческим с решением, и вы достигнете того, что вы хотите
Массив
Предположим, у нас есть следующее json
преобразован в массив
$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);
Пример 1
проверить, если key
- Different
будет так же просто, как
echo new ArrayCollection($array, array("key" => "Diffrent"));
Выход
{"3":{"key":"Diffrent","value":"cool","children":{"tech":"json","lang":"php","year":2013}}}
Пример 2 Проверьте, если release year
является 2013
echo new ArrayCollection($array, array("release.year" => 2013));
Выход
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Пример 3
Посчитать где Year
является 2012
$c = new ArrayCollection($array, array("release.year" => 2012));
echo count($c); // output 2
Пример 4
Возьмем из вашего примера, где вы хотите проверить version
является grater than 22
$c = new ArrayCollection($array, array("release.version" => array('$gt'=>22)));
echo $c;
Выход
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Пример 5
Проверить, если release.arch
значение IN
набор, такой как [x86,x100]
(Пример)
$c = new ArrayCollection($array, array("release.arch" => array('$in'=>array("x86","x100"))));
foreach($c as $var)
{
print_r($var);
}
Выход
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
)
)
Пример 6
Используя 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);
}
Выход
Array
(
[name] => Mongo
[type] => db
[release] => Array
(
[arch] => x86
[version] => 23
[year] => 2013
)
)
Пример 7
Зарегистрируйте собственное имя выражения
$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;
Выход
{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}
Используемый класс
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);
}
}
Резюме
Он может охватывать не все расширенные функции и должен иметь расширяемую архитектуру.
Приведенный выше класс показывает типичный пример того, что вы хотите.. вы можете легко decouple
это, расширить его для поддержки составных выражений, таких как $and
а также $or
MongoDB-подобные объекты выражений запросов просты для понимания и использования, обеспечивая возможность написания чистого, самообъяснимого кода, поскольку и запрос, и объекты для поиска являются ассоциативными массивами.
Почему бы просто не записать массив в MongoDB
База данных, а не работает, это массивы?? Это более эффективно, и это избавит вас от многих неприятностей
Я должен также упомянуть, что использовать лучший инструмент для лучшей работы... То, что вы хотите, это в основном функция базы данных
По сути, это удобная функция для извлечения информации из массивов php. Зная структуру массива (arrayPath), он позволит выполнять операции над многомерными массивами данных, не требуя множественных вложенных циклов.
В этом примере показано, как использовать путь для поиска значения, но вы по-прежнему зависите от загрузки массива в память, и ваш класс выполняет несколько циклов рекурсии и аннулирования, которые не так эффективны, как база данных.
Я ценю советы по архитектуре, связанный или похожий код, который может быть хорошим примером для построения выражений php "if..else" на лету.
Ты действительно хочешь сказать, что ты хочешь всех этих людей здесь???