Skip to content

Commit f5c9db1

Browse files
Merge pull request #894 from bram-pkg/boot-all-models
Check if model has table or route key attribute to determine bindings
2 parents a5b718e + efed9b3 commit f5c9db1

2 files changed

Lines changed: 63 additions & 6 deletions

File tree

src/Ziggy.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Tighten\Ziggy;
44

55
use Illuminate\Contracts\Routing\UrlRoutable;
6+
use Illuminate\Database\Eloquent\Attributes\RouteKey;
7+
use Illuminate\Database\Eloquent\Attributes\Table;
68
use Illuminate\Database\Eloquent\Model;
79
use Illuminate\Support\Arr;
810
use Illuminate\Support\Collection;
@@ -177,10 +179,13 @@ private function resolveBindings(array $routes): array
177179

178180
$model = Reflector::getParameterClassName($parameter);
179181

180-
$override = (new ReflectionClass($model))->isInstantiable() && (
181-
(new ReflectionMethod($model, 'getRouteKeyName'))->class !== Model::class
182-
|| (new ReflectionMethod($model, 'getKeyName'))->class !== Model::class
183-
|| (new ReflectionProperty($model, 'primaryKey'))->class !== Model::class
182+
$class = new ReflectionClass($model);
183+
$override = $class->isInstantiable() && (
184+
$class->getMethod('getRouteKeyName')->class !== Model::class
185+
|| $class->getMethod('getKeyName')->class !== Model::class
186+
|| $class->getProperty('primaryKey')->class !== Model::class
187+
|| count($class->getAttributes(Table::class)) > 0
188+
|| count($class->getAttributes(RouteKey::class)) > 0
184189
);
185190

186191
// Avoid booting this model if it doesn't override the default route key name

tests/Unit/RouteModelBindingTest.php

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
<?php
22

3+
use Illuminate\Database\Eloquent\Attributes\RouteKey;
4+
use Illuminate\Database\Eloquent\Attributes\Table;
35
use Illuminate\Database\Eloquent\Model;
46
use Illuminate\Support\Facades\Route;
57
use Tighten\Ziggy\Ziggy;
8+
use function Orchestra\Testbench\laravel_version_compare;
69

710
beforeEach(function () {
811
Route::get('users/{user}', fn (User $user) => '')->name('users');
@@ -13,6 +16,8 @@
1316
Route::post('users', fn (User $user) => '')->name('users.store');
1417
Route::get('comments/{comment}', fn (Comment $comment) => '')->name('comments');
1518
Route::get('replies/{reply}', fn (Reply $reply) => '')->name('replies');
19+
Route::get('replies-table/{reply}', fn (ReplyWithTable $reply) => '')->name('replies-table');
20+
Route::get('replies-route-key/{reply}', fn (ReplyWithRouteKey $reply) => '')->name('replies-route-key');
1621
Route::get('blog/{category}/{post:slug}', fn (PostCategory $category, Post $post) => '')->name('posts');
1722
Route::get('blog/{category}/{post:slug}/{tag:slug}', fn (PostCategory $category, Post $post, Tag $tag) => '')->name('posts.tags');
1823
});
@@ -140,6 +145,22 @@
140145
'reply' => 'uuid',
141146
],
142147
],
148+
'replies-table' => [
149+
'uri' => 'replies-table/{reply}',
150+
'methods' => ['GET', 'HEAD'],
151+
'parameters' => ['reply'],
152+
'bindings' => [
153+
'reply' => laravel_version_compare('13.0', '>=') ? 'uuid' : 'id',
154+
],
155+
],
156+
'replies-route-key' => [
157+
'uri' => 'replies-route-key/{reply}',
158+
'methods' => ['GET', 'HEAD'],
159+
'parameters' => ['reply'],
160+
'bindings' => [
161+
'reply' => laravel_version_compare('13.0', '>=') ? 'uuid' : 'id',
162+
],
163+
],
143164
'posts' => [
144165
'uri' => 'blog/{category}/{post}',
145166
'methods' => ['GET', 'HEAD'],
@@ -164,13 +185,20 @@
164185

165186
test('include bindings in json', function () {
166187
expect((new Ziggy)->toJson())
167-
->toBe('{"url":"http:\/\/ziggy.dev","port":null,"defaults":{},"routes":{"users":{"uri":"users\/{user}","methods":["GET","HEAD"],"parameters":["user"],"bindings":{"user":"uuid"}},"admins":{"uri":"admins\/{admin}","methods":["GET","HEAD"],"parameters":["admin"],"bindings":{"admin":"uuid"}},"tags":{"uri":"tags\/{tag}","methods":["GET","HEAD"],"parameters":["tag"],"bindings":{"tag":"id"}},"tokens":{"uri":"tokens\/{token}","methods":["GET","HEAD"],"parameters":["token"]},"users.numbers":{"uri":"users\/{user}\/{number}","methods":["GET","HEAD"],"parameters":["user","number"],"bindings":{"user":"uuid"}},"users.store":{"uri":"users","methods":["POST"]},"comments":{"uri":"comments\/{comment}","methods":["GET","HEAD"],"parameters":["comment"],"bindings":{"comment":"uuid"}},"replies":{"uri":"replies\/{reply}","methods":["GET","HEAD"],"parameters":["reply"],"bindings":{"reply":"uuid"}},"posts":{"uri":"blog\/{category}\/{post}","methods":["GET","HEAD"],"parameters":["category","post"],"bindings":{"category":"id","post":"slug"}},"posts.tags":{"uri":"blog\/{category}\/{post}\/{tag}","methods":["GET","HEAD"],"parameters":["category","post","tag"],"bindings":{"category":"id","post":"slug","tag":"slug"}}}}');
168-
});
188+
->toBe('{"url":"http:\/\/ziggy.dev","port":null,"defaults":{},"routes":{"users":{"uri":"users\/{user}","methods":["GET","HEAD"],"parameters":["user"],"bindings":{"user":"uuid"}},"admins":{"uri":"admins\/{admin}","methods":["GET","HEAD"],"parameters":["admin"],"bindings":{"admin":"uuid"}},"tags":{"uri":"tags\/{tag}","methods":["GET","HEAD"],"parameters":["tag"],"bindings":{"tag":"id"}},"tokens":{"uri":"tokens\/{token}","methods":["GET","HEAD"],"parameters":["token"]},"users.numbers":{"uri":"users\/{user}\/{number}","methods":["GET","HEAD"],"parameters":["user","number"],"bindings":{"user":"uuid"}},"users.store":{"uri":"users","methods":["POST"]},"comments":{"uri":"comments\/{comment}","methods":["GET","HEAD"],"parameters":["comment"],"bindings":{"comment":"uuid"}},"replies":{"uri":"replies\/{reply}","methods":["GET","HEAD"],"parameters":["reply"],"bindings":{"reply":"uuid"}},"replies-table":{"uri":"replies-table\/{reply}","methods":["GET","HEAD"],"parameters":["reply"],"bindings":{"reply":"id"}},"replies-route-key":{"uri":"replies-route-key\/{reply}","methods":["GET","HEAD"],"parameters":["reply"],"bindings":{"reply":"id"}},"posts":{"uri":"blog\/{category}\/{post}","methods":["GET","HEAD"],"parameters":["category","post"],"bindings":{"category":"id","post":"slug"}},"posts.tags":{"uri":"blog\/{category}\/{post}\/{tag}","methods":["GET","HEAD"],"parameters":["category","post","tag"],"bindings":{"category":"id","post":"slug","tag":"slug"}}}}');
189+
})->skip(fn () => laravel_version_compare('13.0', '>='));
190+
191+
test('include bindings from model attributes in json', function () {
192+
expect((new Ziggy)->toJson())
193+
->toBe('{"url":"http:\/\/ziggy.dev","port":null,"defaults":{},"routes":{"users":{"uri":"users\/{user}","methods":["GET","HEAD"],"parameters":["user"],"bindings":{"user":"uuid"}},"admins":{"uri":"admins\/{admin}","methods":["GET","HEAD"],"parameters":["admin"],"bindings":{"admin":"uuid"}},"tags":{"uri":"tags\/{tag}","methods":["GET","HEAD"],"parameters":["tag"],"bindings":{"tag":"id"}},"tokens":{"uri":"tokens\/{token}","methods":["GET","HEAD"],"parameters":["token"]},"users.numbers":{"uri":"users\/{user}\/{number}","methods":["GET","HEAD"],"parameters":["user","number"],"bindings":{"user":"uuid"}},"users.store":{"uri":"users","methods":["POST"]},"comments":{"uri":"comments\/{comment}","methods":["GET","HEAD"],"parameters":["comment"],"bindings":{"comment":"uuid"}},"replies":{"uri":"replies\/{reply}","methods":["GET","HEAD"],"parameters":["reply"],"bindings":{"reply":"uuid"}},"replies-table":{"uri":"replies-table\/{reply}","methods":["GET","HEAD"],"parameters":["reply"],"bindings":{"reply":"uuid"}},"replies-route-key":{"uri":"replies-route-key\/{reply}","methods":["GET","HEAD"],"parameters":["reply"],"bindings":{"reply":"uuid"}},"posts":{"uri":"blog\/{category}\/{post}","methods":["GET","HEAD"],"parameters":["category","post"],"bindings":{"category":"id","post":"slug"}},"posts.tags":{"uri":"blog\/{category}\/{post}\/{tag}","methods":["GET","HEAD"],"parameters":["category","post","tag"],"bindings":{"category":"id","post":"slug","tag":"slug"}}}}');
194+
})->skip(fn () => laravel_version_compare('13.0', '<'));
169195

170196
test('skip booting models that dont override their route key', function () {
171197
(new Ziggy)->filter(['tokens', 'users.numbers']);
172198

173199
expect(User::$wasBooted)->toBeTrue();
200+
expect(ReplyWithTable::$wasBooted)->toBeTrue();
201+
expect(ReplyWithRouteKey::$wasBooted)->toBeTrue();
174202
expect(Tag::$wasBooted)->toBeFalse();
175203
});
176204

@@ -263,3 +291,27 @@ public function getKeyName()
263291
return 'uuid';
264292
}
265293
}
294+
295+
#[Table(key: 'uuid')]
296+
class ReplyWithTable extends Model
297+
{
298+
public static $wasBooted = false;
299+
300+
public static function boot()
301+
{
302+
parent::boot();
303+
static::$wasBooted = true;
304+
}
305+
}
306+
307+
#[RouteKey(key: 'uuid')]
308+
class ReplyWithRouteKey extends Model
309+
{
310+
public static $wasBooted = false;
311+
312+
public static function boot()
313+
{
314+
parent::boot();
315+
static::$wasBooted = true;
316+
}
317+
}

0 commit comments

Comments
 (0)