Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.5] Route model binding with key in route definition #18197

Closed

Conversation

sailingdeveloper
Copy link
Contributor

See laravel/ideas#260

This allows for the following:

Route::get('events/{event:slug}', 'EventController@show')->name('event.show'); // Finds Event by slug.
Route::get('admin/events/{event}', 'Admin\EventController@show')->name('admin.event.show'); // Finds Event by ID (or whatever is defined in getRouteKeyName()).

route('event.show', $event) -> http://events.dev/events/laracon-2016
route('admin.event.show', $event) -> http://events.dev/events/142

I realise that this is far from pretty or the ideal implementation, but I am very open to suggestions/edits from the community!

@GrahamCampbell GrahamCampbell changed the title Route model binding with key in route definition [5.5] Route model binding with key in route definition Mar 3, 2017
@devcircus
Copy link
Contributor

I like this. Definitely needs some tests though.

@sailingdeveloper
Copy link
Contributor Author

I will definitely do that as soon as possible

@sailingdeveloper
Copy link
Contributor Author

sailingdeveloper commented Mar 4, 2017

Thinking I might create a dedicated RouteParameter class to tidy up the explode(':') and other things. Good idea, or not?

return is_string($value) && strlen($value) > 0;
});
foreach ($parameterNames as $value => $name) {
$name_without_key = preg_replace('/:\w+/', null, $name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use camel-case variable instead: $nameWithoutKey

if (isset($routeParameters[$index])) {
$key = $routeParameters[$index];
}
$parts = explode(':', isset($key) ? $key : $index);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's looking like this code is duplicated...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How so?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if ($parameter instanceof UrlRoutable) {
$parameters[$key] = $parameter->getRouteKey();
if ($parameter instanceof Model) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would imply to require illuminate/database to illuminate/routing, I am not sure this is worth it.
For now only \Illuminate\Database\Eloquent\Model implements \Illuminate\Contracts\Routing\UrlRoutable.
Why not just checking that getAttribute method key exists ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree and I changed it, but for the record: it's also being used here: https://github.com/laravel/framework/blob/5.4/src/Illuminate/Routing/ImplicitRouteBinding.php#L5
illuminate/database is not in the composer.json though...

@lucasmichot
Copy link
Contributor

Thinking I might create a dedicated RouteParameter class to tidy up the explode(':') and other things. Good idea, or not?

I would go for it

@sailingdeveloper
Copy link
Contributor Author

@lucasmichot Done, what do you think?

@lucasmichot
Copy link
Contributor

lucasmichot commented Mar 7, 2017

@lucasmichot Done, what do you think?

👍

This would imply to require illuminate/database to illuminate/routing, I am not sure this is worth it.

Damn, did not see that. I suppose you can thus check that $parameter is an instanceof of \Illuminate\Database\Eloquent\Model then...
You should probably add "illuminate/database": "5.4.*" to src/Illuminate/Routing/composer.json, it has probably been forgotten

Thijs de Maa and others added 2 commits March 7, 2017 15:57
* RouteParameter constructor.
*
* @param string $parameter
* @param mixed $value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @return void

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

@@ -359,15 +360,22 @@ protected function formatAction($action)
* Format the array of URL parameters.
*
* @param mixed|array $parameters
* @param Route $route
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@param \Illuminate\Routing\Route $route

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

@@ -426,6 +426,18 @@ public function signatureParameters($subClass = null)
}

/**
* Get the parameters as instances of RouteParameter.
*
* @return RouteParameter[]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually use @return array notation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

*/
protected function parts()
{
return explode(':', $this->parameter);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return explode(':', $this->parameter, 2); maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't really matter, but added anyway.

@@ -1495,6 +1516,10 @@ class RoutingTestExtendedUserModel extends RoutingTestUserModel
{
}

class RoutingTestWithRouteKey extends RoutingTestUserModel
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use an empty comment for empty classes, as for RoutableModelStub

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

public function testParsingName()
{
$parameter = new RouteParameter('baz');
$this->assertEquals('baz', $parameter->name());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose al assertEquals comparing a string can be replace by stricter assertSame assertions ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you say so 😄
Changed.

@lucasmichot
Copy link
Contributor

A conflict needs to be solved @sailingdeveloper

@sailingdeveloper
Copy link
Contributor Author

@lucasmichot I don't see it, can you give me a line number?

@lucasmichot
Copy link
Contributor

lucasmichot commented Mar 17, 2017

Line 38

@sailingdeveloper
Copy link
Contributor Author

Either I'm blind, or we're not looking at the same file(s). Can you tell me what the conflict is, by screenshot or some other way?

@lucasmichot
Copy link
Contributor

lucasmichot commented Mar 17, 2017

In src/Illuminate/Routing/ImplicitRouteBinding.php

screen shot 2017-03-17 at 08 21 27

! $route->parameter($parameter->name) instanceof Model) {
$model = $container->make($class->name);
foreach ($routeParameters as $routeParameter) {
if ($routeParameter->name() == $parameter->name &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not using a stricter comparison === ?

@taylorotwell
Copy link
Member

I think I'm going to leave this to manual use of bind for now.

@sailingdeveloper
Copy link
Contributor Author

That's a bummer. Too bad

@mokhosh
Copy link
Contributor

mokhosh commented Aug 6, 2018

Any news on this feature?

@sandervankasteel
Copy link

This would have been so sweet to have in Laravel

@ZacharyDuBois
Copy link
Contributor

Would really like to see this implemented. Adds a really elegant way for slugs to be used on a user facing interface and IDs for an admin facing interface. It also would allow the admin interface to change a slug without the need to redirect to the new slug on form submit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants