You should make much more use of Iterators in PHP to divide the job even:
//Pages
$perPage = 10; // Avoid magic numbers
$files = new GlobIterator('docs/*.xml');
$filtered = new FileXmlDoctypeFilterIterator($files, $requestedType);
$count = iterator_count($filtered);
$pagination = new LimitPagination($_GET['page'], $count, $perPage);
foreach ($pagination->getLimitIterator($filtered) as $file)
{
$xml = simplexml_load_file($file);
...
}
So how does this work? First of all by using the pre-defined GlobIterator
which by it's name you might already see what it does. But instead of returning an array as glob()
does, it is an iterator.
This is done especially here to allow stacking with other iterators here. For example with the next one which is a concrete FilterIterator
so you need to move the code you currently have for the filter decision into this iterator. It's documented in the PHP manual how that works.
Then the count of all filtered files is obtained with the iterator_count()
function which then is used with the LimitPagination
object that completely encapsulates the pagination into an object of it's own. See my answer to XML pagination with PHP for more information about it.
It offers another iterator via $pagination->getLimitIterator($filtered)
so that it will offer those filtered files that are within the specified page ($_GET['page']
in the example above). It does also offer a list of pages so that you can output the links to other pages.
So what was done here:
- Your problem with filtering files has been encapsulated into a filter-iterator.
- Your problem with pagination has been encapsulated into a pagination-object which provides an iterator as well.
- Your problem filtering the globbed files has been solved by turning the array into an iterator.
Technically you can solve all these as well with arrays, however the big benefit with iterators here is that those are much more flexible than arrays.
You can for example further improve this by creating an iterator that will create a special child of SimpleXMLElement
which also carries the algorithm to get the doctype and which knowns about the file-path. Giving this a distinct interface will help with the filter-iterator.
Also as pagination is involved it can make sense to cache the filter-iterator so that the count operation does not weight too hard.
The benfits of iterators here clearly is the code-reuse, e.g. the LimitPagination
object just works with any kind of pagination for which you provide the data to paginate in form of an iterator.
If you want to stick with arrays, you need to turn that one into an ArrayPagination
object and instead of the filter-iterator you can make use of array_filter()
with a callback function that filters your files. And if you use the arrays for prototyping, there is also ArrayIterator
so you can switch from arrays to iterator in between (and there is CallbackFilterIterator
which should also allow you to re-use your array filter function).