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() ?

  • 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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.