Created
September 7, 2025 03:14
-
-
Save rydurham/7c6c66ea5fe7f4ca2a5d35bb75efcaa2 to your computer and use it in GitHub Desktop.
Automating Laravel Wayfinder in Docker without Vite
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| FROM php:8.4-alpine | |
| LABEL maintainer="Ryan Durham <[email protected]>" | |
| # Set up a www-data user with UID 1000 and GID 1000 | |
| ARG NAME=www-data | |
| ENV NAME=${NAME} | |
| RUN deluser www-data && \ | |
| adduser -s /bin/sh -D -u 1000 -g '' ${NAME} ${NAME} && \ | |
| chown -R ${NAME}:${NAME} /home/${NAME} | |
| # Install Alpine packages | |
| RUN apk add --no-cache --virtual build-deps autoconf g++ libtool make linux-headers && \ | |
| apk add --no-cache git libzip-dev postgresql-dev | |
| # Install PHP Extensions | |
| RUN docker-php-ext-install pdo pdo_pgsql pgsql zip | |
| # Increase the default memory limit | |
| RUN echo 'memory_limit = 1096M' >> /usr/local/etc/php/conf.d/docker-php-memlimit.ini; | |
| # Install Composer | |
| RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer | |
| # Add Composer to the PATH | |
| ENV PATH="$PATH:/usr/local/bin:/home/${NAME}/.composer/vendor/bin" | |
| # Ensure ~/.composer belongs to user | |
| RUN mkdir /home/${NAME}/.composer && chown -R ${NAME}:${NAME} /home/${NAME} | |
| # Install XDebug extension for code coverage support | |
| RUN pecl install xdebug && docker-php-ext-enable xdebug | |
| COPY xdebug.ini /usr/local/etc/php/conf.d | |
| # Clean up apk dependencies | |
| RUN apk del build-deps | |
| # Set the active directory | |
| WORKDIR /var/www | |
| # Copy utility scripts into the container | |
| COPY watch.php /usr/local/bin/ | |
| COPY start.sh /usr/local/bin/ | |
| RUN chmod +x /usr/local/bin/start.sh | |
| # Set the active user | |
| USER ${NAME} | |
| # Set the default command | |
| STOPSIGNAL SIGQUIT | |
| CMD ["/usr/local/bin/start.sh"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # Start processes | |
| echo "Starting services..." | |
| php -d display_errors=1 -d error_reporting=E_ALL artisan serve --host 0.0.0.0 --no-ansi -vvv & | |
| php /usr/local/bin/watch.php & | |
| # Wait for any child to exit or signal | |
| trap "exit" SIGTERM SIGINT SIGQUIT TERM; while true; do sleep 1; done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| declare(strict_types=1); | |
| /** | |
| * Trigger Wayfinder when changes are made to controller or route files. | |
| */ | |
| // Initial scan | |
| message("Initializing..."); | |
| $timestamps = scan(); | |
| $interval = 1; // Polling interval in seconds | |
| // Watch loop | |
| message("Watching for controller or route updates..."); | |
| while (true) { | |
| $changes = false; | |
| // Clear PHP's file stat cache to ensure fresh results | |
| clearstatcache(true); | |
| // Get current state of directory | |
| $files = scan(); | |
| // Check for new or modified files | |
| foreach ($files as $path => $mtime) { | |
| if (!isset($timestamps[$path])) { | |
| message("New file: {$path}"); | |
| $changes = true; | |
| } elseif ($timestamps[$path] !== $mtime) { | |
| message("File changed: {$path}"); | |
| $changes = true; | |
| } | |
| } | |
| // Check for deleted files | |
| foreach ($timestamps as $path => $mtime) { | |
| if (!isset($files[$path])) { | |
| message("File deleted: {$path}"); | |
| $changes = true; | |
| } | |
| } | |
| // Update our list of file timestamps | |
| $timestamps = $files; | |
| // Update Wayfinder if changes have been detected | |
| if ($changes) { | |
| runWayfinder(); | |
| } | |
| // Memory cleanup | |
| unset($files); | |
| gc_collect_cycles(); | |
| // Wait before next check | |
| sleep($interval); | |
| } | |
| // Log messages to STDOUT with a timestamp | |
| function message(string $message) | |
| { | |
| fwrite(STDOUT, " " . date('Y-m-d H:i:s') . " MONITOR: {$message}\n"); | |
| fflush(STDOUT); | |
| } | |
| // Run the Wayfinder artisan command with exec() | |
| function runWayfinder() | |
| { | |
| exec('php artisan wayfinder:generate --with-form --skip-actions', $output, $returnCode); | |
| message('TypeScript route definitions updated'); | |
| if ($returnCode !== 0) { | |
| message("Task failed with code {$returnCode}"); | |
| message(json_encode($output)); | |
| } | |
| } | |
| // Read file modification timestamps from the file system | |
| function scan(array $directory = ['app/Http', 'routes']) | |
| { | |
| $files = []; | |
| foreach ($directory as $dir) { | |
| $iterator = new RecursiveIteratorIterator( | |
| new RecursiveDirectoryIterator($dir) | |
| ); | |
| foreach ($iterator as $file) { | |
| if ($file->isDir() || $file->getExtension() !== 'php') { | |
| continue; | |
| } | |
| $files[$file->getPathname()] = $file->getMTime(); | |
| } | |
| // Free the iterator; | |
| unset($iterator); | |
| } | |
| return $files; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment