Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
c6a4f10
Use different fs watchers
seregazhuk May 20, 2020
97dc013
Update scrutinizer PHP version
seregazhuk Jun 13, 2020
5a30602
Fix arguments passing
seregazhuk Jun 13, 2020
e046b1e
Reduce delay in tests
seregazhuk Jun 13, 2020
b69e2b5
Update readme
seregazhuk Jun 13, 2020
07ddb08
Skip signals test
seregazhuk Jun 13, 2020
b9b271d
Update changelog
seregazhuk Jun 13, 2020
dbd8153
Fix fixtures for testing
seregazhuk Jun 13, 2020
adcfedc
Fix fixtures for testing
seregazhuk Jun 13, 2020
f45c144
Fix fixtures folder
seregazhuk Jun 14, 2020
70bf0df
Merge branch 'master' into use-fswatch
Oct 23, 2025
9a72adc
feat: use fswatch
Oct 23, 2025
3e59d28
feat: use fswatch
Oct 23, 2025
0cfdc51
feat: use fswatch
Oct 23, 2025
58181a1
feat: use fswatch
Oct 23, 2025
6e9c9b6
feat: use fswatch
Oct 23, 2025
33b67ad
feat: use fswatch
Oct 23, 2025
3dfff61
feat: use fswatch
Oct 23, 2025
ac122eb
feat: use fswatch
Oct 24, 2025
f4b1883
feat: use fswatch
Oct 24, 2025
dc20323
feat: use fswatch
Oct 24, 2025
ad406f4
feat: use fswatch
Oct 24, 2025
dd2582f
feat: use fswatch
Oct 24, 2025
d03993a
feat: use fswatch
Oct 24, 2025
dd2b5b3
feat: use fswatch
Oct 24, 2025
6f65507
feat: use fswatch
Oct 24, 2025
7d0a56f
feat: use fswatch
Oct 24, 2025
ba26720
feat: use fswatch
Oct 24, 2025
fb5088e
feat: use fswatch
Oct 24, 2025
664da06
feat: use fswatch
Oct 24, 2025
44e6d8f
feat: use fswatch
Oct 24, 2025
058705f
feat: use fswatch
Oct 24, 2025
9e42610
feat: use fswatch
Oct 24, 2025
f6681f8
feat: use fswatch
Oct 24, 2025
ce2a0a3
feat: use fswatch
Oct 24, 2025
0e4c122
feat: use fswatch
Oct 24, 2025
80c5127
feat: use fswatch
Oct 24, 2025
e245a65
feat: use fswatch
Oct 24, 2025
e2ea7ab
feat: use fswatch
Oct 24, 2025
2a53dbf
feat: use fswatch
Oct 24, 2025
95be314
feat: use fswatch
Oct 24, 2025
5a18375
feat: use fswatch
Oct 24, 2025
84ef8fc
feat: use fswatch
Oct 24, 2025
3438367
feat: use fswatch
Oct 24, 2025
191d39d
feat: use fswatch
Oct 24, 2025
5cc4e9d
feat: use fswatch
Oct 24, 2025
81c7158
feat: use fswatch
Oct 24, 2025
cf6fa44
feat: use fswatch
Oct 24, 2025
e0d0361
feat: use fswatch
Oct 24, 2025
baae204
feat: use fswatch
Oct 24, 2025
611dc93
feat: use fswatch
Oct 24, 2025
7771823
feat: use fswatch
Oct 24, 2025
bf12a01
feat: use fswatch
Oct 24, 2025
5c8305b
feat: use fswatch
Oct 24, 2025
8e9388a
feat: use fswatch
Oct 24, 2025
4a437b1
feat: use fswatch
Oct 24, 2025
90ac5da
feat: use fswatch
Oct 25, 2025
cd16c47
feat: use fswatch
Oct 25, 2025
e234a5c
feat: use fswatch
Oct 25, 2025
36c4ef9
feat: use fswatch
Oct 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, sockets, grpc, curl
extensions: pcntl

- name: Check Out Code
uses: actions/checkout@v4
Expand Down
70 changes: 70 additions & 0 deletions .github/workflows/tests-chokidar.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: 'Tests with Chokidar'

on:
push:
branches:
- main
paths-ignore:
- '.gitignore'
- 'CHANGELOG.md'
- 'LICENSE'
- 'README.md'

pull_request:
paths-ignore:
- '.gitignore'
- 'CHANGELOG.md'
- 'LICENSE'
- 'README.md'

jobs:
tests:
timeout-minutes: 5
name: Tests with Chokidar (PHP ${{ matrix.php }}, OS ${{ matrix.os }})

runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest]
php: [8.1, 8.2, 8.3, 8.4]

env:
extensions: xdebug

steps:
- name: Check Out Code
uses: actions/checkout@v4

- name: Remove fswatch
run: sudo apt-get remove fswatch

- name: Setup node
uses: actions/setup-node@v6

- name: Install chokidar
run: npm install chokidar

- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: pcntl

- name: Validate composer.json and composer.lock
run: composer validate --strict

- name: Install dependencies with composer
uses: ramsey/composer-install@v3
with:
dependency-versions: ${{ matrix.dependencies }}

- name: Validate lowest dependencies
if: matrix.dependencies == 'lowest' && matrix.php == '8.1'
env:
COMPOSER_POOL_OPTIMIZER: 0
run: vendor/bin/validate-prefer-lowest

- name: Run tests with Phpunit
run: |
XDEBUG_MODE=coverage php vendor/bin/phpunit
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: 'Tests'
name: 'Tests with FsWatch'

on:
push:
Expand All @@ -18,28 +18,31 @@ on:
- 'README.md'

jobs:
tests:
name: Tests (PHP ${{ matrix.php }}, OS ${{ matrix.os }})
tests-fswatch:
timeout-minutes: 5
name: Tests with FsWatch (PHP ${{ matrix.php }}, OS ${{ matrix.os }})

runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest]
os: [macos-latest ]
php: [8.1, 8.2, 8.3, 8.4]

env:
extensions: xdebug

steps:
- name: Check Out Code
uses: actions/checkout@v4

- name: Install fswatch
run: brew install fswatch

- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, sockets, grpc, curl ${{ matrix.extensions-suffix }}
extensions: pcntl

- name: Validate composer.json and composer.lock
run: composer validate --strict
Expand All @@ -57,4 +60,4 @@ jobs:

- name: Run tests with Phpunit
run: |
XDEBUG_MODE=coverage php vendor/bin/phpunit --testsuite unit
php vendor/bin/phpunit
19 changes: 0 additions & 19 deletions .travis.yml

This file was deleted.

25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ PHP-watcher does not require any additional changes to your code or method of
* [Default executable](#default-executable)
* [Gracefully reloading down your script](#gracefully-reloading-down-your-script)
* [Automatic restart](#automatic-restart)
* [Performance](#performance)
* [Spinner](#spinner)

## Installation
Expand All @@ -55,9 +56,6 @@ composer require seregazhuk/php-watcher --dev
```
Locally installed you can run it with `vendor/bin/php-watcher`.

Under the hood, to watch filesystem changes, PHP-watcher uses JavaScript package [chokidar](https://github.com/paulmillr/chokidar).
At first run it will check and install it if required.

## Usage

All the examples assume you've installed the package globally. If you opted for the local installation prepend `vendor/bin/` everywhere where `php-watcher` is mentioned.
Expand Down Expand Up @@ -236,9 +234,28 @@ script crashes PHP-watcher will notify you about that.

![app exit](images/exit.svg)

## Performance

The watcher can use different strategies to monitor your file system changes. Under the hood it
detects the environment and chooses the best suitable strategy.

### Fswatch (OSX only)

[FsWatch](https://github.com/emcrisostomo/fswatch) is a cross-platform (Linux,Mac,Windows) file change monitor that will automatically
use the platforms native functionality when possible. Under the hood the filesystem notifies us
when any changes occur. Currently, it [doesn't work correctly on Linux](https://github.com/emcrisostomo/fswatch/issues/247).
If your system is OSx and has fswatch installed, this strategy will be used.

**Has not been extensively tested.**

### Chokidar

[Chokidar](https://github.com/paulmillr/chokidar) is a JavaScript package for watching file and directory changes.
At first run the watcher will check if Node.js is available in the system. If it is, it will install chokidar into the project.

## Spinner

By default the watcher outputs a nice spinner which indicates that the process is running
By default, the watcher outputs a nice spinner which indicates that the process is running
and watching your files. But if your system doesn't support ansi coded the watcher
will try to detect it and disable the spinner. Or you can always disable the spinner
manually with option '--no-spinner':
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
"react/child-process": "^0.6.1",
"react/event-loop": "^1.1",
"react/stream": "^1.0.0",
"spatie/file-system-watcher": "^1.2",
"seregazhuk/reactphp-fswatch": "^1.1.1",
"symfony/console": "^6.0",
"symfony/finder": "^6.0",
"symfony/process": "^6.0",
"symfony/yaml": "^6.0"
},
"autoload": {
Expand Down
7 changes: 2 additions & 5 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,16 @@
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="true"
stopOnFailure="false"
bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="Common">
<directory suffix="Test.php">tests</directory>
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
<exclude>
<file>src/Filesystem/watcher.php</file>
</exclude>
</whitelist>
</filter>
</phpunit>
5 changes: 0 additions & 5 deletions server.php

This file was deleted.

47 changes: 0 additions & 47 deletions src/Filesystem/ChangesListener.php

This file was deleted.

16 changes: 16 additions & 0 deletions src/Filesystem/ChangesListener/ChangesListenerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace seregazhuk\PhpWatcher\Filesystem\ChangesListener;

use seregazhuk\PhpWatcher\Config\WatchList;

interface ChangesListenerInterface
{
public function start(WatchList $watchList): void;

public function onChange(callable $callback): void;

public function stop(): void;

public function getName(): string;
}
68 changes: 68 additions & 0 deletions src/Filesystem/ChangesListener/ChokidarChangesListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

declare(strict_types=1);

namespace seregazhuk\PhpWatcher\Filesystem\ChangesListener;

use Evenement\EventEmitter;
use React\EventLoop\LoopInterface;
use React\EventLoop\TimerInterface;
use seregazhuk\PhpWatcher\Config\WatchList;
use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\Process;

final class ChokidarChangesListener extends EventEmitter implements ChangesListenerInterface
{
private const INTERVAL = 0.15;

private ?Process $process = null;

private ?TimerInterface $timer = null;

public function __construct(private readonly LoopInterface $loop) {}

public function start(WatchList $watchList): void
{
$command = [
(new ExecutableFinder)->find('node'),
realpath(__DIR__.'/../../../bin/file-watcher.js'),
json_encode($watchList->getPaths()),
json_encode($watchList->getIgnored()),
json_encode($watchList->getFileExtensions()),
];

$this->process = new Process(command: $command);
$this->process->start();

$this->timer = $this->loop->addPeriodicTimer(
self::INTERVAL,
function (): void {
$output = $this->process->getIncrementalOutput();
if ($output !== '') {
$this->emit('change');
}
}
);
}

public function onChange(callable $callback): void
{
$this->on('change', $callback);
}

public function stop(): void
{
if ($this->process instanceof Process && $this->process->isRunning()) {
$this->process->stop();
}

if ($this->timer instanceof TimerInterface) {
$this->loop->cancelTimer($this->timer);
}
}

public function getName(): string
{
return 'chokidar';
}
}
Loading