Skip to content

Commit 4d4ac29

Browse files
committed
added support for names on resource routes, as well as nested resources.
1 parent 337e0dc commit 4d4ac29

4 files changed

Lines changed: 180 additions & 27 deletions

File tree

src/Illuminate/Routing/Controllers/Inspector.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,22 @@ public function getRoutable($controller, $prefix)
3737
{
3838
$data = $this->getMethodData($method, $prefix);
3939

40-
$routable[$method->name][] = $data;
41-
4240
// If the routable method is an index method, we will create a special index
4341
// route which is simply the prefix and the verb and does not contain any
4442
// the wildcard place-holders that each "typical" routes would contain.
4543
if ($data['plain'] == $prefix.'/index')
4644
{
4745
$routable[$method->name][] = $this->getIndexData($data, $prefix);
46+
47+
$routable[$method->name][] = $data;
48+
}
49+
50+
// If the routable method is not a special index method, we will just add in
51+
// the data to the returned results straight away. We do not need to make
52+
// any special routes for this scenario but only just add these routes.
53+
else
54+
{
55+
$routable[$method->name][] = $data;
4856
}
4957
}
5058
}

src/Illuminate/Routing/Router.php

Lines changed: 127 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,11 @@ public function resource($resource, $controller, array $options = array())
259259
{
260260
$defaults = array('index', 'create', 'store', 'show', 'edit', 'update', 'destroy');
261261

262+
$base = $this->getBaseResource($resource);
263+
262264
foreach ($this->getResourceMethods($defaults, $options) as $method)
263265
{
264-
$this->{'addResource'.ucfirst($method)}($resource, $controller);
266+
$this->{'addResource'.ucfirst($method)}($resource, $base, $controller);
265267
}
266268
}
267269

@@ -289,87 +291,189 @@ protected function getResourceMethods($defaults, $options)
289291
/**
290292
* Add the index method for a resourceful route.
291293
*
292-
* @param string $resource
294+
* @param string $r
295+
* @param string $base
293296
* @param string $controller
294297
* @return void
295298
*/
296-
protected function addResourceIndex($resource, $controller)
299+
protected function addResourceIndex($r, $base, $controller)
297300
{
298-
return $this->get($resource, $controller.'@index');
301+
$action = $this->getResourceAction($r, $controller, 'index');
302+
303+
return $this->get($this->getResourceUri($r), $action);
299304
}
300305

301306
/**
302307
* Add the create method for a resourceful route.
303308
*
304-
* @param string $resource
309+
* @param string $r
310+
* @param string $base
305311
* @param string $controller
306312
* @return void
307313
*/
308-
protected function addResourceCreate($resource, $controller)
314+
protected function addResourceCreate($r, $base, $controller)
309315
{
310-
return $this->get($resource.'/create', $controller.'@create');
316+
$action = $this->getResourceAction($r, $controller, 'create');
317+
318+
return $this->get($this->getResourceUri($r).'/create', $action);
311319
}
312320

313321
/**
314322
* Add the store method for a resourceful route.
315323
*
316-
* @param string $resource
324+
* @param string $r
325+
* @param string $base
317326
* @param string $controller
318327
* @return void
319328
*/
320-
protected function addResourceStore($resource, $controller)
329+
protected function addResourceStore($r, $base, $controller)
321330
{
322-
return $this->post($resource, $controller.'@store');
331+
$action = $this->getResourceAction($r, $controller, 'store');
332+
333+
return $this->post($this->getResourceUri($r), $action);
323334
}
324335

325336
/**
326337
* Add the show method for a resourceful route.
327338
*
328-
* @param string $resource
339+
* @param string $r
340+
* @param string $base
329341
* @param string $controller
330342
* @return void
331343
*/
332-
protected function addResourceShow($resource, $controller)
344+
protected function addResourceShow($r, $base, $controller)
333345
{
334-
return $this->get($resource.'/{id}', $controller.'@show');
346+
$uri = $this->getResourceUri($r).'/{'.$base.'}';
347+
348+
return $this->get($uri, $this->getResourceAction($r, $controller, 'show'));
335349
}
336350

337351
/**
338352
* Add the edit method for a resourceful route.
339353
*
340-
* @param string $resource
354+
* @param string $r
355+
* @param string $base
341356
* @param string $controller
342357
* @return void
343358
*/
344-
protected function addResourceEdit($resource, $controller)
359+
protected function addResourceEdit($r, $base, $controller)
345360
{
346-
return $this->get($resource.'/{id}/edit', $controller.'@edit');
361+
$uri = $this->getResourceUri($r).'/{'.$base.'}/edit';
362+
363+
return $this->get($uri, $this->getResourceAction($r, $controller, 'edit'));
347364
}
348365

349366
/**
350367
* Add the update method for a resourceful route.
351368
*
352-
* @param string $resource
369+
* @param string $r
370+
* @param string $base
353371
* @param string $controller
354372
* @return void
355373
*/
356-
protected function addResourceUpdate($resource, $controller)
374+
protected function addResourceUpdate($r, $base, $controller)
357375
{
358-
$this->put($resource.'/{id}', $controller.'@update');
376+
$this->addPutResourceUpdate($r, $base, $controller);
359377

360-
return $this->patch($resource.'/{id}', $controller.'@update');
378+
return $this->addPatchResourceUpdate($r, $base, $controller);
379+
}
380+
381+
/**
382+
* Add the update method for a resourceful route.
383+
*
384+
* @param string $r
385+
* @param string $base
386+
* @param string $controller
387+
* @return void
388+
*/
389+
protected function addPutResourceUpdate($r, $base, $controller)
390+
{
391+
$uri = $this->getResourceUri($r).'/{'.$base.'}';
392+
393+
return $this->put($uri, $this->getResourceAction($r, $controller, 'update'));
394+
}
395+
396+
/**
397+
* Add the update method for a resourceful route.
398+
*
399+
* @param string $r
400+
* @param string $base
401+
* @param string $controller
402+
* @return void
403+
*/
404+
protected function addPatchResourceUpdate($r, $base, $controller)
405+
{
406+
$uri = $this->getResourceUri($r).'/{'.$base.'}';
407+
408+
$this->patch($uri, $controller.'@update');
361409
}
362410

363411
/**
364412
* Add the destroy method for a resourceful route.
365413
*
366-
* @param string $resource
414+
* @param string $r
415+
* @param string $base
367416
* @param string $controller
368417
* @return void
369418
*/
370-
protected function addResourceDestroy($resource, $controller)
419+
protected function addResourceDestroy($r, $base, $controller)
371420
{
372-
return $this->delete($resource.'/{id}', $controller.'@destroy');
421+
$uri = $this->getResourceUri($r).'/{'.$base.'}';
422+
423+
return $this->delete($uri, $this->getResourceAction($r, $controller, 'destroy'));
424+
}
425+
426+
/**
427+
* Get the base resource URI for a given resource.
428+
*
429+
* @param string $resource
430+
* @return string
431+
*/
432+
public function getResourceUri($resource)
433+
{
434+
if ( ! str_contains($resource, '.')) return $resource;
435+
436+
// To create the nested resource URI, we will simply explode the segments and
437+
// create a base URI for each of them, then join all of them back together
438+
// with slashes. This should create the properly nested resource routes.
439+
$nested = implode('/', array_map(function($segment)
440+
{
441+
return $segment.'/{'.$segment.'}';
442+
443+
}, $segments = explode('.', $resource)));
444+
445+
// Once we have built the base URI, we'll remove the wildcard holder for this
446+
// base resource name so that the individual route adders can suffix these
447+
// paths however they need to, as some do not have any wildcards at all.
448+
$last = $segments[count($segments) - 1];
449+
450+
return str_replace('/{'.$last.'}', '', $nested);
451+
}
452+
453+
/**
454+
* Get the action array for a resource route.
455+
*
456+
* @param string $resource
457+
* @param string $controller
458+
* @param string $method
459+
* @return array
460+
*/
461+
protected function getResourceAction($resource, $controller, $method)
462+
{
463+
return array('as' => $resource.'.'.$method, 'uses' => $controller.'@'.$method);
464+
}
465+
466+
/**
467+
* Get the base resource from a resource name.
468+
*
469+
* @param string $resource
470+
* @return string
471+
*/
472+
protected function getBaseResource($resource)
473+
{
474+
$segments = explode('.', $resource);
475+
476+
return $segments[count($segments) - 1];
373477
}
374478

375479
/**

tests/Routing/RoutingControllerInspectorTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ public function testMethodsAreCorrectlyDetermined()
88
$data = $inspector->getRoutable('RoutingControllerInspectorStub', 'prefix');
99

1010
$this->assertEquals(3, count($data));
11-
$this->assertEquals(array('verb' => 'get', 'plain' => 'prefix', 'uri' => 'prefix'), $data['getIndex'][1]);
12-
$this->assertEquals(array('verb' => 'get', 'plain' => 'prefix/index', 'uri' => 'prefix/index/{v1?}/{v2?}/{v3?}/{v4?}/{v5?}'), $data['getIndex'][0]);
11+
$this->assertEquals(array('verb' => 'get', 'plain' => 'prefix', 'uri' => 'prefix'), $data['getIndex'][0]);
12+
$this->assertEquals(array('verb' => 'get', 'plain' => 'prefix/index', 'uri' => 'prefix/index/{v1?}/{v2?}/{v3?}/{v4?}/{v5?}'), $data['getIndex'][1]);
1313
$this->assertEquals(array('verb' => 'get', 'plain' => 'prefix/foo-bar', 'uri' => 'prefix/foo-bar/{v1?}/{v2?}/{v3?}/{v4?}/{v5?}'), $data['getFooBar'][0]);
1414
$this->assertEquals(array('verb' => 'post', 'plain' => 'prefix/baz', 'uri' => 'prefix/baz/{v1?}/{v2?}/{v3?}/{v4?}/{v5?}'), $data['postBaz'][0]);
1515
}

tests/Routing/RoutingTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,47 @@ public function testResourceRouting()
9191
}
9292

9393

94+
public function testResourceRouteNaming()
95+
{
96+
$router = new Router;
97+
$router->resource('foo', 'FooController');
98+
99+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.index'));
100+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.show'));
101+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.create'));
102+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.store'));
103+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.edit'));
104+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.update'));
105+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.destroy'));
106+
107+
$router = new Router;
108+
$router->resource('foo.bar', 'FooController');
109+
110+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.bar.index'));
111+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.bar.show'));
112+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.bar.create'));
113+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.bar.store'));
114+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.bar.edit'));
115+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.bar.update'));
116+
$this->assertInstanceOf('Illuminate\Routing\Route', $router->getRoutes()->get('foo.bar.destroy'));
117+
}
118+
119+
120+
public function testResourceRouteUriGeneration()
121+
{
122+
$router = new Router;
123+
$router->resource('foo.bar', 'FooController');
124+
125+
$this->assertEquals('/foo/{foo}/bar', $router->getRoutes()->get('foo.bar.index')->getPath());
126+
$this->assertEquals('/foo/{foo}/bar/{bar}', $router->getRoutes()->get('foo.bar.show')->getPath());
127+
$this->assertEquals('/foo/{foo}/bar/create', $router->getRoutes()->get('foo.bar.create')->getPath());
128+
$this->assertEquals('/foo/{foo}/bar', $router->getRoutes()->get('foo.bar.store')->getPath());
129+
$this->assertEquals('/foo/{foo}/bar/{bar}/edit', $router->getRoutes()->get('foo.bar.edit')->getPath());
130+
$this->assertEquals('/foo/{foo}/bar/{bar}', $router->getRoutes()->get('foo.bar.update')->getPath());
131+
$this->assertEquals('/foo/{foo}/bar/{bar}', $router->getRoutes()->get('foo.bar.destroy')->getPath());
132+
}
133+
134+
94135
public function testControllersAreCalledFromControllerRoutes()
95136
{
96137
$router = new Router;

0 commit comments

Comments
 (0)