How to create a file watcher with PHP and the Elementary Framework
Tags: php, elementaryframework, filewatcher, filesystem
Published: 2019-07-26 16:16:32

---
title: How to create a file watcher with PHP and the Elementary Framework
published: true
description: Learn how to create a file watcher (like the Facebook Watchman) entirely in PHP by following this article!
tags: php, ElementaryFramework, filewatcher, filesystem
cover_image: https://thepracticaldev.s3.amazonaws.com/i/8y3w1gf5lcrj51a1tbg4.png
series: Elementary Framework
---

# Introduction

Welcome everyone to this second How-To about the [Elementary Framework](https://github.com/ElementaryFramework) (for those who have missed the first How-To, check it [here](https://dev.to/na2axl/how-to-create-a-restful-api-with-php-and-the-elementary-framework-30ij)).

In this article we will talk about the creation of a **file watcher**, a console app which will _watch_ files in a directory and report to us any changes made to these files (deletion, creation, modification), written in the PHP language using [FireFS](https://github.com/ElementaryFramework/FireFS), a part of my framework.

> Creating a file watcher it's just a possibility of FireFS between much more others.

# Prerequisites

Before start, make sure you have:

- A PHP IDE or editor: You can download Visual Studio Code, it's a free and powerful code editor which can support many languages (including PHP).
- Composer: Composer is a dependencies manager for PHP projects. You can download it at https://getcomposer.org/

# Part 1 - Preparing the project

The first thing we have to do is to create our new project. Create a new folder with the name you want, and open a terminal into it.

FireFS is a composer package, so we need first to prepare our project to use composer. In the terminal you previuously opened, type:

```bash
composer init
```

This will initialize our project with composer support. Follow the initialization process to the end.

Now, in the same terminal, we can install FireFS with the command:

```bash
composer require elementaryframework/fire-fs
```

And wait the process finish, this will download the source code of the FireFS project and install it in your own. When the installation succeed, type again:

```bash
composer dump-autoload -o
```

This will generate an _optimized_ autoloader file (useful for production). For a normal autoload file, just omit the `-o` switch.

Once FireFS is installed, we can now create the command line tool to watch our files. Create a file named `watch` inside your project folder and insert into it:

```php
#!/usr/bin/env php

<?php

// Require composer autoload file
require "./vendor/autoload.php";

// Print a message to the console
print "Hello world, this is a file watcher!";

```

What we are doing ?

- We first require the autoloader file from composer
- We print a message to the console output

To test if everything is working, just type in the terminal (while the working directory is the same as our project):

```bash
php watch
```

The console will print the text "**Hello world, this is a file watcher!**" before exit.

> Note that the file name is **watch** (without any extension), and not **watch.php**

# Part 2 - Our file watcher

Building a file watcher with FireFS is very easy, we just have to create a new `FileSystemWatcher` object, follow the build pattern and start it, easy, right?

## The `FireFS` object

In FireFS, instances of the `FireFS` class represent a _file system_, and manage every files and folders in the given **root directory**. When creating a file watcher we have first to create a file system:

```php
// We use the FireFS class
use ElementaryFramework\FireFS\FireFS;

// We create a new file system on the current directory
$fs = new FireFS();
```

This will create a file system at the same path than our `watch` file (to change the root path, just define your prefered path as the first parameter of the FireFS class constructor).

## The watched folder

Now we have to create the folder which will be watched. We can let our console app do it itself by using the great FireFS API:

```php
// Check if the directory to watch exists
if (!$fs->exists("files_to_watch")) {
    // If not, create the directory
    $fs->mkdir("files_to_watch");
}
```

This will create the directory `files_to_watch` only if it not exists at each run of our file watcher.

## The `IFileSystemListener` object

Before enjoying our file watcher, we have to create a class implementing the `IFileSystemListener` interface. This class is used by the watcher to execute specific actions following the _watch_ event (create, delete, update).

```php
// We use the IFileSystemWatcher interface
use ElementaryFramework\FireFS\Listener\IFileSystemListener;

// We use the FileSystemEvent class
use ElementaryFramework\FireFS\Events\FileSystemEvent;

// Our listener
class WatcherListener implements IFileSystemListener
{
    /**
     * Action executed on any event.
     * The returned boolean will define if the
     * specific event handler (onCreated, onModified, onDeleted)
     * have to be called after this call.
     */
    public function onAny(FileSystemEvent $event): bool
    {
        $eventType = $event->getEventType();
        $date = date("d/m/Y H:i:s");

        if ($eventType === FileSystemEvent::EVENT_UNKNOWN) {
            return true;
        }

        switch ($eventType) {
            case FileSystemEvent::EVENT_CREATE:
                print "{$date}  -  [Created]  {$event->getPath()}\n";
                break;

            case FileSystemEvent::EVENT_MODIFY:
                print "{$date}  -  [Updated]  {$event->getPath()}\n";
                break;

            case FileSystemEvent::EVENT_DELETE:
                print "{$date}  -  [Deleted]  {$event->getPath()}\n";
                break;
        }

        return false;
    }

    /**
     * Action executed when a file/folder is created.
     */
    public function onCreated(FileSystemEvent $event)
    { }

    /**
     * Action executed when a file/folder is updated.
     */
    public function onModified(FileSystemEvent $event)
    { }

    /**
     * Action executed when a file/folder is deleted.
     */
    public function onDeleted(FileSystemEvent $event)
    { }
}
```

## The `FileSystemWatcher` object

Once we have a file system object and we know the directory (or the file) we want to watch, we can create the file watcher:

```php
// We use the FileSystemWatcher class
use ElementaryFramework\FireFS\Watcher\FileSystemWatcher;

// Create the file watcher
$watcher = new FileSystemWatcher($fs);
```

The next step is to configure our watcher. The configuration is done by calling some methods:

- `setListener(IFileSystemListener)`: Defines the `IFileSystemListener` instance used to execute specific actions on each files updates ;
- `setPath(string)`: Defines the path of directory/file to watch ;
- `setRecursive(bool)`: Defines if the watcher will watch for files recursively (works only if the watched entity is a directory) ;
- `addPattern(Regex)`: Add a files-to-watch pattern ;
- `addExcludePattern(Regex)`: Add a files-to-exclude pattern ;
- `setPattern(array)`: Set an array of files-to-watch patterns. This will overwrite any existing pattern ;
- `setExcludePattern(array)`: Set an array of files-to-exclude patterns. This will overwrite any existing pattern ;
- `setWatchInterval(int)`: Set the interval in milliseconds in which the watcher will process a _watch_ event.

So we will build our watcher like this:

```php
$watcher
    ->setListener(new WatcherListener)
    ->setRecursive(true)
    ->setPath("./files_to_watch")
    ->setWatchInterval(250)
    ->build(); // It's important to call build to validate the configuration
```

> **Important to know**: The `FileSystemWatcher` class have some default exclude patterns, check them [here](https://github.com/ElementaryFramework/FireFS/blob/master/src/FireFS/Watcher/FileSystemWatcher.php#L97)

At this time, everything is set! Now the last thing to do is to start the watcher:

```php
// Start the file watcher
$watcher->start();
```

## The complete `watch` file

We just have finished to create our file watcher, there is the complete file content:

```php
#!/usr/bin/env php

<?php

// Require composer autoloader
require_once __DIR__ . '/vendor/autoload.php';

// We use the FireFS class
use ElementaryFramework\FireFS\FireFS;

// We use the IFileSystemWatcher interface
use ElementaryFramework\FireFS\Listener\IFileSystemListener;

// We use the FileSystemEvent class
use ElementaryFramework\FireFS\Events\FileSystemEvent;

// We use the FileSystemWatcher class
use ElementaryFramework\FireFS\Watcher\FileSystemWatcher;

// We create a new file system on the current directory
$fs = new FireFS();

// Check if the directory to watch exists
if (!$fs->exists("files_to_watch")) {
    // If not, create the directory
    $fs->mkdir("files_to_watch");
}

// Our listener
class WatcherListener implements IFileSystemListener
{
    /**
     * Action executed on any event.
     * The returned boolean will define if the
     * specific event handler (onCreated, onModified, onDeleted)
     * have to be called after this call.
     */
    public function onAny(FileSystemEvent $event): bool
    {
        $eventType = $event->getEventType();
        $date = date("d/m/Y H:i:s");

        if ($eventType === FileSystemEvent::EVENT_UNKNOWN) {
            return true;
        }

        switch ($eventType) {
            case FileSystemEvent::EVENT_CREATE:
                print "{$date}  -  [Created]  {$event->getPath()}\n";
                break;

            case FileSystemEvent::EVENT_MODIFY:
                print "{$date}  -  [Updated]  {$event->getPath()}\n";
                break;

            case FileSystemEvent::EVENT_DELETE:
                print "{$date}  -  [Deleted]  {$event->getPath()}\n";
                break;
        }

        return false;
    }

    /**
     * Action executed when a file/folder is created.
     */
    public function onCreated(FileSystemEvent $event)
    { }

    /**
     * Action executed when a file/folder is updated.
     */
    public function onModified(FileSystemEvent $event)
    { }

    /**
     * Action executed when a file/folder is deleted.
     */
    public function onDeleted(FileSystemEvent $event)
    { }
}

// Create the file watcher
$watcher = new FileSystemWatcher($fs);

$watcher
    ->setListener(new WatcherListener)
    ->setPath("./files_to_watch")
    ->setWatchInterval(250)
    ->build(); // It's important to call build to validate the configuration

// Start the file watcher
$watcher->start();

```

Now run this file using the command `php watch`, a new folder `files_to_watch` is directly created and the console wait for files changes. Try to create, delete or edit files inside the `files_to_watch` folder and you will be directly notified for these actions inside the console!

```text
php watch

26/07/2019 15:53:20  -  [Created]  D:\AliensGroup\Hyde\hyde-cli\files_to_watch\composer.json
26/07/2019 15:54:24  -  [Created]  D:\AliensGroup\Hyde\hyde-cli\files_to_watch\composer.lock
26/07/2019 15:54:24  -  [Created]  D:\AliensGroup\Hyde\hyde-cli\files_to_watch\hyde
26/07/2019 15:54:29  -  [Deleted]  D:\AliensGroup\Hyde\hyde-cli\files_to_watch\composer.lock
26/07/2019 15:54:47  -  [Updated]  D:\AliensGroup\Hyde\hyde-cli\files_to_watch\hyde
```

# Conclusion

With this article, we have learn **How to create a file watcher with PHP and the Elementary Framework**. Using the FireFS module of the framework, we have seen steps by steps how it's very easy to implement a functionality like this. Now with the knowledge you have you can create more than a simple _event reporting_ app, from crons on your webserver, to your own Jekyll PHP edition ;-), you have everything you need to go further.

# What next?

- Browse the [FireFS](https://github.com/ElementaryFramework/FireFS) source code on GitHub - and give a star if you like it - ;
- Checkout other [Elementary Framework](https://github.com/ElementaryFramework) modules

{% github ElementaryFramework/FireFS %}