From e2fb9aecc82307db34b7b8901c1dbdcf1cf8fb51 Mon Sep 17 00:00:00 2001 From: Josh Manders Date: Sun, 19 Jan 2025 14:06:02 -0600 Subject: [PATCH 1/5] feat: support passing except/only args to ziggy command --- src/CommandRouteGenerator.php | 12 +++++++++--- src/Ziggy.php | 14 +++++++++----- tests/Unit/CommandRouteGeneratorTest.php | 12 +++++++++++- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/CommandRouteGenerator.php b/src/CommandRouteGenerator.php index cfa359ad..cd45bad2 100644 --- a/src/CommandRouteGenerator.php +++ b/src/CommandRouteGenerator.php @@ -6,7 +6,6 @@ use Illuminate\Filesystem\Filesystem; use Tighten\Ziggy\Output\File; use Tighten\Ziggy\Output\Types; -use Tighten\Ziggy\Ziggy; class CommandRouteGenerator extends Command { @@ -15,13 +14,20 @@ class CommandRouteGenerator extends Command {--types : Generate a TypeScript declaration file.} {--types-only : Generate only a TypeScript declaration file.} {--url=} - {--group=}'; + {--group=} + {--except=} + {--only=}'; protected $description = 'Generate a JavaScript file containing Ziggy’s routes and configuration.'; public function handle(Filesystem $filesystem) { - $ziggy = new Ziggy($this->option('group'), $this->option('url') ? url($this->option('url')) : null); + $ziggy = new Ziggy( + $this->option('group'), + $this->option('url') ? url($this->option('url')) : null, + $this->option('except') ? explode(',', $this->option('except')) : null, + $this->option('only') ? explode(',', $this->option('only')) : null, + ); $path = $this->argument('path') ?? config('ziggy.output.path', 'resources/js/ziggy.js'); diff --git a/src/Ziggy.php b/src/Ziggy.php index fd121752..f5abb273 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -26,8 +26,12 @@ class Ziggy implements JsonSerializable public function __construct( protected $group = null, protected ?string $url = null, + protected ?array $except = null, + protected ?array $only = null ) { $this->url = rtrim($url ?? url('/'), '/'); + $this->except = $except ?? config('ziggy.except', []); + $this->only = $only ?? config('ziggy.only', []); $this->routes = static::$cache ??= $this->nameKeyedRoutes(); } @@ -43,12 +47,12 @@ private function applyFilters($group) return $this->group($group); } - if (config()->has('ziggy.except') && ! config()->has('ziggy.only')) { - return $this->filter(config('ziggy.except'), false)->routes; + if (count($this->except) > 0 && count($this->only) === 0) { + return $this->filter($this->except, false)->routes; } - if (config()->has('ziggy.only') && ! config()->has('ziggy.except')) { - return $this->filter(config('ziggy.only'))->routes; + if (count($this->only) > 0 && count($this->except) === 0) { + return $this->filter($this->only)->routes; } return $this->routes; @@ -204,7 +208,7 @@ private function folioRoutes(): Collection // Use existing named Folio routes (instead of searching view files) to respect route caching return collect(app(FolioRoutes::class)->routes())->map(function (array $route) { - $uri = rtrim($route['baseUri'], '/') . str_replace([$route['mountPath'], '.blade.php'], '', $route['path']); + $uri = rtrim($route['baseUri'], '/').str_replace([$route['mountPath'], '.blade.php'], '', $route['path']); $segments = explode('/', $uri); $parameters = []; diff --git a/tests/Unit/CommandRouteGeneratorTest.php b/tests/Unit/CommandRouteGeneratorTest.php index 12956a9d..e1bc3005 100644 --- a/tests/Unit/CommandRouteGeneratorTest.php +++ b/tests/Unit/CommandRouteGeneratorTest.php @@ -66,6 +66,16 @@ expect(base_path('resources/js/ziggy.js'))->toEqualFile('./tests/fixtures/ziggy.js'); }); +test('generate file respecting exclude options', function () { + Route::get('posts/{post}/comments', fn () => '')->name('postComments.index'); + Route::get('slashes/{slug}', fn () => '')->where('slug', '.*')->name('slashes'); + Route::get('admin', fn () => '')->name('admin.dashboard'); // Excluded by options + + artisan('ziggy:generate --except=admin.*'); + + expect(base_path('resources/js/ziggy.js'))->toEqualFile('./tests/fixtures/ziggy.js'); +}); + test('generate file with custom output formatter', function () { Route::get('posts/{post}/comments', fn () => '')->name('postComments.index'); Route::get('admin', fn () => '')->name('admin.dashboard'); // Excluded by config @@ -162,7 +172,7 @@ class CustomFile extends File { - function __toString(): string + public function __toString(): string { return << Date: Sun, 19 Jan 2025 14:18:47 -0600 Subject: [PATCH 2/5] add description --- src/CommandRouteGenerator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CommandRouteGenerator.php b/src/CommandRouteGenerator.php index cd45bad2..131f5016 100644 --- a/src/CommandRouteGenerator.php +++ b/src/CommandRouteGenerator.php @@ -15,8 +15,8 @@ class CommandRouteGenerator extends Command {--types-only : Generate only a TypeScript declaration file.} {--url=} {--group=} - {--except=} - {--only=}'; + {--except= : Comma delimited list of route names to exclude.} + {--only= : Comma delimited list of route names to include.}'; protected $description = 'Generate a JavaScript file containing Ziggy’s routes and configuration.'; From 0c37d349b304e8aed183d4cedcf9f0662c3a6cf4 Mon Sep 17 00:00:00 2001 From: Josh Manders Date: Sun, 19 Jan 2025 14:35:35 -0600 Subject: [PATCH 3/5] update to point to vite plugin --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eeccb068..84a95990 100644 --- a/README.md +++ b/README.md @@ -550,7 +550,7 @@ Route::get('ziggy', fn () => response()->json(new Ziggy)); ### Re-generating the routes file when your app routes change -If you are generating your Ziggy config as a file by running `php artisan ziggy:generate`, you may want to re-run that command when your app's route files change. The example below is a Laravel Mix plugin, but similar functionality could be achieved without Mix. Huge thanks to [Nuno Rodrigues](https://github.com/nacr) for [the idea and a sample implementation](https://github.com/tighten/ziggy/issues/321#issuecomment-689150082). See [#655 for a Vite example](https://github.com/tighten/ziggy/pull/655/files#diff-4aeb78f813e14842fcf95bdace9ced23b8a6eed60b23c165eaa52e8db2f97b61). +If you are generating your Ziggy config as a file by running `php artisan ziggy:generate`, you may want to re-run that command when your app's route files change. The example below is a Laravel Mix plugin, but similar functionality could be achieved without Mix. Huge thanks to [Nuno Rodrigues](https://github.com/nacr) for [the idea and a sample implementation](https://github.com/tighten/ziggy/issues/321#issuecomment-689150082). See [vite-plugin-ziggy](https://github.com/aniftyco/vite-plugin-ziggy) for how to use it with Vite.
Laravel Mix plugin example From 0ffc5e394b0dd4f5e4dbe8466a15c0a20ecea71d Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 22 Jan 2025 17:57:35 -0500 Subject: [PATCH 4/5] Use `filter` method --- src/CommandRouteGenerator.php | 13 +++++++------ src/Ziggy.php | 14 +++++--------- tests/Unit/CommandRouteGeneratorTest.php | 22 +++++++++++++++++++++- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/CommandRouteGenerator.php b/src/CommandRouteGenerator.php index 131f5016..8c20223d 100644 --- a/src/CommandRouteGenerator.php +++ b/src/CommandRouteGenerator.php @@ -22,12 +22,13 @@ class CommandRouteGenerator extends Command public function handle(Filesystem $filesystem) { - $ziggy = new Ziggy( - $this->option('group'), - $this->option('url') ? url($this->option('url')) : null, - $this->option('except') ? explode(',', $this->option('except')) : null, - $this->option('only') ? explode(',', $this->option('only')) : null, - ); + $ziggy = new Ziggy($this->option('group'), $this->option('url') ? url($this->option('url')) : null); + + if ($this->option('except') && ! $this->option('only')) { + $ziggy->filter(explode(',', $this->option('except')), false); + } else if ($this->option('only') && ! $this->option('except')) { + $ziggy->filter(explode(',', $this->option('only'))); + } $path = $this->argument('path') ?? config('ziggy.output.path', 'resources/js/ziggy.js'); diff --git a/src/Ziggy.php b/src/Ziggy.php index f5abb273..fd121752 100644 --- a/src/Ziggy.php +++ b/src/Ziggy.php @@ -26,12 +26,8 @@ class Ziggy implements JsonSerializable public function __construct( protected $group = null, protected ?string $url = null, - protected ?array $except = null, - protected ?array $only = null ) { $this->url = rtrim($url ?? url('/'), '/'); - $this->except = $except ?? config('ziggy.except', []); - $this->only = $only ?? config('ziggy.only', []); $this->routes = static::$cache ??= $this->nameKeyedRoutes(); } @@ -47,12 +43,12 @@ private function applyFilters($group) return $this->group($group); } - if (count($this->except) > 0 && count($this->only) === 0) { - return $this->filter($this->except, false)->routes; + if (config()->has('ziggy.except') && ! config()->has('ziggy.only')) { + return $this->filter(config('ziggy.except'), false)->routes; } - if (count($this->only) > 0 && count($this->except) === 0) { - return $this->filter($this->only)->routes; + if (config()->has('ziggy.only') && ! config()->has('ziggy.except')) { + return $this->filter(config('ziggy.only'))->routes; } return $this->routes; @@ -208,7 +204,7 @@ private function folioRoutes(): Collection // Use existing named Folio routes (instead of searching view files) to respect route caching return collect(app(FolioRoutes::class)->routes())->map(function (array $route) { - $uri = rtrim($route['baseUri'], '/').str_replace([$route['mountPath'], '.blade.php'], '', $route['path']); + $uri = rtrim($route['baseUri'], '/') . str_replace([$route['mountPath'], '.blade.php'], '', $route['path']); $segments = explode('/', $uri); $parameters = []; diff --git a/tests/Unit/CommandRouteGeneratorTest.php b/tests/Unit/CommandRouteGeneratorTest.php index e1bc3005..9143b269 100644 --- a/tests/Unit/CommandRouteGeneratorTest.php +++ b/tests/Unit/CommandRouteGeneratorTest.php @@ -66,7 +66,7 @@ expect(base_path('resources/js/ziggy.js'))->toEqualFile('./tests/fixtures/ziggy.js'); }); -test('generate file respecting exclude options', function () { +test('generate file using --except option', function () { Route::get('posts/{post}/comments', fn () => '')->name('postComments.index'); Route::get('slashes/{slug}', fn () => '')->where('slug', '.*')->name('slashes'); Route::get('admin', fn () => '')->name('admin.dashboard'); // Excluded by options @@ -76,6 +76,26 @@ expect(base_path('resources/js/ziggy.js'))->toEqualFile('./tests/fixtures/ziggy.js'); }); +test('generate file using --only option', function () { + Route::get('posts/{post}/comments', fn () => '')->name('postComments.index'); + Route::get('slashes/{slug}', fn () => '')->where('slug', '.*')->name('slashes'); + Route::get('admin', fn () => '')->name('admin.dashboard'); // Excluded by options + + artisan('ziggy:generate --only=postComments.index,slashes'); + + expect(base_path('resources/js/ziggy.js'))->toEqualFile('./tests/fixtures/ziggy.js'); +}); + +test('generate file using both --only and --except', function () { + Route::get('posts/{post}/comments', fn () => '')->name('postComments.index'); + Route::get('slashes/{slug}', fn () => '')->where('slug', '.*')->name('slashes'); + + artisan('ziggy:generate --only=slashes --except=postComments.index'); + + // Options cancel each other out and are ignored + expect(base_path('resources/js/ziggy.js'))->toEqualFile('./tests/fixtures/ziggy.js'); +}); + test('generate file with custom output formatter', function () { Route::get('posts/{post}/comments', fn () => '')->name('postComments.index'); Route::get('admin', fn () => '')->name('admin.dashboard'); // Excluded by config From 33a4b165100504b46a642714b7ba8bbfc9d2e390 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Wed, 22 Jan 2025 17:58:01 -0500 Subject: [PATCH 5/5] Wip --- README.md | 2 +- src/CommandRouteGenerator.php | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 84a95990..16e8b3ce 100644 --- a/README.md +++ b/README.md @@ -550,7 +550,7 @@ Route::get('ziggy', fn () => response()->json(new Ziggy)); ### Re-generating the routes file when your app routes change -If you are generating your Ziggy config as a file by running `php artisan ziggy:generate`, you may want to re-run that command when your app's route files change. The example below is a Laravel Mix plugin, but similar functionality could be achieved without Mix. Huge thanks to [Nuno Rodrigues](https://github.com/nacr) for [the idea and a sample implementation](https://github.com/tighten/ziggy/issues/321#issuecomment-689150082). See [vite-plugin-ziggy](https://github.com/aniftyco/vite-plugin-ziggy) for how to use it with Vite. +If you are generating your Ziggy config as a file by running `php artisan ziggy:generate`, you may want to re-run that command when your app's route files change. The example below is a Laravel Mix plugin, but similar functionality could be achieved without Mix. Huge thanks to [Nuno Rodrigues](https://github.com/nacr) for [the idea and a sample implementation](https://github.com/tighten/ziggy/issues/321#issuecomment-689150082). See [#655](https://github.com/tighten/ziggy/pull/655/files#diff-4aeb78f813e14842fcf95bdace9ced23b8a6eed60b23c165eaa52e8db2f97b61) or [vite-plugin-ziggy](https://github.com/aniftyco/vite-plugin-ziggy) for Vite examples.
Laravel Mix plugin example diff --git a/src/CommandRouteGenerator.php b/src/CommandRouteGenerator.php index 8c20223d..f7c379ec 100644 --- a/src/CommandRouteGenerator.php +++ b/src/CommandRouteGenerator.php @@ -6,6 +6,7 @@ use Illuminate\Filesystem\Filesystem; use Tighten\Ziggy\Output\File; use Tighten\Ziggy\Output\Types; +use Tighten\Ziggy\Ziggy; class CommandRouteGenerator extends Command { @@ -15,8 +16,8 @@ class CommandRouteGenerator extends Command {--types-only : Generate only a TypeScript declaration file.} {--url=} {--group=} - {--except= : Comma delimited list of route names to exclude.} - {--only= : Comma delimited list of route names to include.}'; + {--except= : Route name patterns to exclude.} + {--only= : Route name patterns to include.}'; protected $description = 'Generate a JavaScript file containing Ziggy’s routes and configuration.';