Доброе время суток. Возникла задача реализовать функцию, которая возвращает данные из массива (в идеале это база данных), таким образом, что элементов можно получить N, независимо от размера этих данных. В итоке получается примерно такая структура:
По-подробности:
имеем
[$model1, $model2, $model3, $model4, $model5, $model6]
. Вызываем нашу функцию таким способом:
$repo = [$model1, $model2, $model3, $model4, $model5, $model6];
$startModel = $repo[3]; //любая рандомная модель, берем $model4
$direction = -1;
$n = 4;
$result = $startModel->seek($direction, $n);
Что здесь есть. Есть модели (не важно что за модели, просто модели, у которых есть метод, позволяющий получить $n элементов в сторону $direction (-1 - лево, 1 - право). И этот метод должен вернуть:
[$model6, $model1, $model2, $model3]
То есть, простыми словами это может выглядеть так:
seek([1, 2, 3, 4, 5, 6], 3, -1, 4)
Результат:
[5, 6, 1, 2]
1й параметр - наши данные, второй - с какого элемента двигаться, третий - направление сдвига, 4й - количество необходимых элементов
Количество элементов может быть даже большим чем всего элементов в базе, например:
seek([1, 2, 3, 4], 3, -1, 10);
Результат:
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2]
Сначала мне пришло в голову сделать такое рекурсивно, и набросал такой код (извиняюсь за его размер):
<?php
class Model {
protected $id;
public function __construct($id) {
$this->id = $id;
}
public function getId() {
return $this->id;
}
public function seek($direction = 1, $count = 5, $context = null) {
global $repo;
$result = array();
is_null($context) and $context = $this;
if ($direction < 0) {
$leftCount = $context->getId() - $count;
$leftCount < 0 and $leftCount = 0;
for($i = $context->getId(); $i > $leftCount; $i--) {
$result[] = $repo[$i];
}
if (count($result) < $count) {
$newContext = $repo[count($repo) - 1];
$newCount = $count - count($result);
$result = array_merge($result, $newContext->seek($direction, $newCount));
}
} else {
$rightCount = $count + $context->getId();
$rightCount > count($repo) and $rightCount = count($repo);
for($i = $context->getId(); $i <= $rightCount; ++$i) {
$result[] = $repo[$i];
}
if (count($result) < $count) {
$newContext = $repo[0];
$newCount = $count - count($result);
$result = array_merge($result, $newContext->seek($direction, $newCount));
}
}
return $result;
}
}
$ids = range(1, 6);
$repo = array();
foreach($ids as $id) {
$repo[] = new Model($id);
}
/**
* Random model
*/
$startModel = $repo[3];
//var_dump($startModel->getId());
$result = $startModel->seek(-1, 10);
foreach($result as $model) {
var_dump($model->getId());
}
В принципе он работает (есть правда баг, который я не могу впоймать, но суть не в этом)
В чем заключается мой вопрос: то что я сделал - работает с уже загруженным масивом данных, а если нельзя загрузить сразу все данные ? Вопрос очень размазанный, я понимаю, но это еще не всё. Мой подход - рекурсия. Я подумал о том, что можно на стороне базы данных попытаться сделать такое. Т.е. например генерировать sql с UNION ALL на стороне php, и потом получать все нужные данные одним запросом..
Если непонятно описал, пните пожалуйста, просто очень специфичная задача какая то, не нашел готовых решений, а своё пока что делает не совсем то что хотелось бы.