5

I want be to be able to re-write the code of an existing PHP function in an abstract manner.

Here is an example:

scandir() scans a directory for files and folders, and returns the relative paths '.' and '..' .

While I could just create a new function to run scandir() and remove these entries, I want to try and re-write the code for scandir() to allow for an extra parameter, then add a flag to not include these paths.

So instead of this:

$files = [];
foreach(scandir($path) as $index =>  $ref) {
    if(!in_array(['.','..'], $ref)) {
        $files[] = $ref;
    }
}

I can do this:

$files = scandir($path, true);

Is this possible without rewriting the entirety of scandir() with override_function() ?

Rohit Goyani
  • 103
  • 4
  • 5
    Yes, it is possible. However, you're overcomplicating stuff. Just create a `scandir_alastor` function, taking the two parameters which will internally call the default `scandir`. – Andy Jun 27 '16 at 11:18
  • 3
    This is exactly what makes JavaScript so... *exciting*. Anyone can redefine anything, which means that you can end up with strange behavior practically impossible to debug. Say we can do it in PHP, and somebody (such as a disgruntled colleague) redefines a basic function to return a weird result, but only for a few minutes per year. Would you enjoy it? – Arseni Mourzenko Jun 27 '16 at 11:20

1 Answers1

1

Can you add to a built-in function? Yes, but you really shouldn't. Other code might count on the . and .. directories showing up the results, thus breaking other code.

Instead, opt for things like DirectoryIterator or just create your own class:

class DirectoryFileScanner implements Iterator
{
    public function __construct($path) {
        $this->path = $path;
        $this->position = 0;
    }

    private $files;

    private $path;

    private $position;

    private function getFiles() {
        if (!isset($this->files)) {
            $allFiles = scandir($this->path);
            $this->files = [];

            foreach($allFiles as $index =>  $ref) {
                if(!in_array(['.','..'], $ref)) {
                    $this->files[] = $ref;
                }
            }
        }

        return $this->files;
    }

    public current() {
        return $this->getFiles()[$this->position];
    }

    public key() {
        return $this->position;
    }

    public next() {
        ++$this->position;
    }

    public rewind() {
        $this->position = 0;
    }

    public valid() {
        return isset($this->getFiles()[$this->position]);
    }
}

And to use it:

$files = new DirectoryFileScanner('/foo');

foreach ($files as $index => $file) {
    // do stuff with $file
}

The correct solution is to create your own function or class to encapsulate the specialized behavior you are looking for.

Greg Burghardt
  • 34,276
  • 8
  • 63
  • 114