First of all thank you for taking your time takling this difficult topic.
Goal:
My URL structure is like facebook/twitter: site.com/Username
To let the user set the username, I need to check if a path of a route matches a username.
Possibilities & problems:
If somebody is interested, the possible solutions I came up with:
1.) Using getRouteCollection()
Problem: This method shouldn't be used because it rebuilds the route cache and kills performance (see https://github.com/symfony/symfony-docs/issues/6710)
2.) Using a blacklist as RegExp in the User (for Username) Entity to blacklist all sites like "settings", "about", "login", "register"...
* @Assert\Regex(pattern="/^(?!register)(?!login)...
Problem: This is nearly guaranteed to explode because sometimes a URL is forgotten to add into this RegExp
3.) Using CURL to check if the site.com/username results in a 404
Problem: This seems to be a "hack" for me and unprofessional.
Question:
Whats the professional, secure way of checking if a route doesn't already exists, so that the username can be set and is guaranteed to be "free" (via absolute path like site.com/Username and no other route is in the way)?
By example something like $app->hasURL('/username')
Add: use \Symfony\Component\RoutingException\ResourceNotFoundException;
Then, where $router
is the routing service, you can attempt to match the url to a route. If it doesn't match anything it will throw an exception, but if you have a default catch-all route it will always match something so you would need to just detect if it matches the catch-all instead:
$routeIsAvailable = false;
try {
$route = $router->match( '/' . $username );
// If you are using a catch-all route to load profiles
if ( $route[ '_route' ] === 'name_of_catch_all_route' )
$routeIsAvailable = true;
} catch ( ResourceNotFoundException ) {
// If the url didn't match any route at all
$routeIsAvailable = true;
}
Make sure that you validate $username
first so that it doesn't have any characters like ?
or /
. You can also urlencode
it, but you probably don't want your user's profile urls to have encoded characters in them, so it's better to just restrict the valid usernames.