I'm displaying user profiles on a PHP website using usernames as part of the URL that links to the given user profile.
I can achieve this through a controller, the ProfileController, but the URL will look like this thewebsite.com/profile/show_profile/ANYUSERNAMEHERE
What i want is something similar to Facebook, where the username is appended just after the base URL:
https://www.facebook.com/zuck
I tried passing a variable to the Index function (Index()) of the home page controller (IndexController), but the URL becomes thewebsite.com/index/ANYUSERNAMEHERE
and the base url thewebsite.com
throws an error:
Too few arguments to function IndexController::index(), 0 passed and exactly 1 expected.
The home page controller:
<?php
class IndexController extends Controller
{
public function __construct()
{
parent::__construct();
}
// IF LEFT, THE VARIABLE $profile THROWS AN ERROR AT THE BASE URL
public function index($profile)
{
/** AFTER REMOVING THE $profile VARIABLE ABOVE AND THE 'if'
* STATEMENT BELOW, THE ERROR THROWN AT THE BASE URL VANISHES AND
* THE WEBSITE GOES BACK TO IT'S NORMAL STATE. THIS CODE WAS USED
* TRYING TO RENDER THE URL thewebsite.com/ANYUSERNAMEHERE BUT IT
* ONLY WORKS WITH thewebsite.com/index/ANYUSERNAMEHERE
*/
if (isset($profile)) {
$this->View->render('profiles/show_profile', array(
'profiles' => ProfileModel::getSelectedProfile($profile))
);
} else {
$this->View->render('index/index', array(
'profiles' => ProfileModel::getAllProfiles()));
}
}
The profile controller:
<?php
class ProfileController extends Controller
{
public function __construct()
{
parent::__construct();
Auth::checkAuthentication();
}
public function index()
{
$this->View->render('profiles/index', array(
'profiles' => ProfileModel::getAllProfiles())
);
}
public function show_profile($profile)
{
if (isset($profile)) {
$this->View->render('profiles/show_profile', array(
'profiles' => ProfileModel::getSelectedProfile($profile))
);
} else {
Redirect::home();
}
}
}
I was expecting the base URL to pass the argument (the username) to the IndexController's Index($profile) function, but the webpage throws an error and the expected result is being displayed from the wrong URL: thewebsite.com/index/ANYUSERNAMEHERE
You would need to use a router based on regular expressions, like FastRoute, or Aura.Router.
For example, with FastRoute you'd define and add a route to the so-called route collector ($r
) like this:
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
// The /{profile} suffix is optional
$r->addRoute('GET', '[/{profile}]', 'handler');
});
where handler
is just a generic name for a customizable route handler in form of a callable. For example, if you'd additionally use the PHP-DI/Invoker library, the route handler ('handler'
) could look like one of the following callables (at least):
[ProfileController::class, 'show_profile']
'ProfileController::show_profile'
So the complete route definition would be like:
$r->addRoute('GET', '[/{profile}]', [ProfileController::class, 'show_profile']);
$r->addRoute('GET', '[/{profile}]', 'ProfileController::show_profile');
The placeholder name (profile
) corresponds to the name of the parameter of the method ProfileController::show_profile
:
class ProfileController extends Controller {
public function show_profile($profile) {
...
}
}
Even though the URL would look like you want it, e.g. thewebsite.com/zuck
, I imagine that the placeholder {profile}
of the above route definition would come in conflict with the fixed pattern parts defined in other route definitions, like /books
in:
$r->addRoute('GET', '[/books/{bookName}]', 'handler');
So I suggest to maintain a URL of the form thewebsite.com/profiles/zuck
, with the route definition:
$r->addRoute('GET', '/profiles/{profile}', 'handler');
I also suggest to read and apply the PHP Standards Recommendations in your code. Especially PSR-1, PSR-4 and PSR-12.