Introducing PHP-Watcher
The problem
I like PHP for its simplicity: you code something, refresh the page in the browser and you can see your changes. There is no need to wait, to compile something, just refresh the page and you are ready to go. But, PHP is not only about request-response. Sometimes we create some CLI tools and some of these tools are long-living processes. For example, we create an asynchronous HTTP server for uploading files on the server. This server should be always running and listening for incoming connections. The development process of a long-running command in PHP can become really painful. In the terminal, we cannot “refresh the page” to see the changes. Each time we make changes in the source code, we have to manually interrupt our command and restart it. Being a developer I always strive to optimize my workflow. In PHP I haven’t found any appropriate solution, so I have chosen nodemon. It is a tool from NodeJS ecosystem and was built to help in developing NodeJs applications. But with some tweaks, it can be easily used with PHP script. Sometimes it is OK, and sometimes we don’t want to install NodeJS and NPM to just restart my app. Actually, I don’t want to have a bunch of unknown npm packages which are totally redundant for a PHP asynchronous application. So, I have decided to create my own solution which can be used in PHP ecosystem. I have announced it on Twitter and many people liked the idea of having such a tool, which is written in a pure PHP and available via Composer.
Finally, it is ready! PHP-Watcher - a package to automatically restart PHP application once the source code changes. Can be very useful for developing long-running PHP applications 🎉👍https://t.co/wIeuJejDvq
— Sergey Zhuk (@zhukserega) October 3, 2019
PHP-watcher
What is PHP-watcher? Consider it as nodemon but for PHP and written in PHP. It helps develop long-running PHP applications by automatically restarting them when file changes are detected.
Here’s how it looks like:
The package can be installed via Composer:
composer global require seregazhuk/php-watcher
And you are ready to go. Let’s say that we are working on some long-running application based on Symfony framework. The entry point to our app is public/index.php
and we want to monitor changes in src
and config
directories. Thus, once we change the source code or config params we want our app to be automatically restarted. This task can be solved with the watcher:
The command above executes PHP script public/index.php
and starts watching directories src
and config
for changes. Once, any PHP file in these directories is being changed the watcher will restart the script. By default, it detects changes only in *.php
files. But Symfony stores its config files in yaml
format. So, we can explicitly tell the watcher to watch both php
and yaml
extensions providing --ext
option:
Then, let’s say that we don’t want to reload the app for any change in src
directory. For example, we want to ignore src/Migrations
subdirectory. In this case use --ignore
option:
Now, the watcher starts watching src
and config
directories, but ignores Migrations
subdirectory. Note that by default, it ignores all dot and VCS files.
PHP-watcher also supports customization of its behavior with config files. So, instead of passing a bunch of options via CLI command you can create a config file .php-watcher.yml
. For example the previous command can be replaced with the following config file:
Having this config file you can just run php-watcher
and provide a PHP script you want to reload. All other settings will be taken from this file:
What happens if you have both config file and CLI arguments? The specificity is as follows so that a command-line argument will always override the corresponding config file setting.
By default, the watcher uses php
executable to run the script. When we call this:
Under the hood, it creates a new child process that runs this command - php public/index.php
. In most cases it is OK, but if in your environment PHP executable is different, you can explicitly tell the watcher what command it should run. For example, we have several PHP versions in the system, and we want our app to run on PHP 7.4. Use --exec
option and provide your executable:
or via config file:
PHP-watcher doesn’t automatically restart your application if it fails. Actually, there is no need to do this in a dev environment. While we are developing something it is OK if the app crashes. If the crash happens (the app has exited with a non-zero code) the watcher will notify us about it. Once you fix the code, it will detect the changes and restart the app.
Conclusion
Now, you don’t have to install nodemon or any other npm package for developing your long-running PHP application. You can use PHP-Watcher which is pure PHP and provides the same functionality as nodemon does.
If you want to learn more about the watcher, make sure to check out the project homepage. Its documentation describes common usage patterns. The project is still under development, but the API is rather stable. So, feel free to provide any feedback by creating an issue on GitHub.