I am creating an MVC framework with PHP. I am not able to get the query string. The following code does not return the query string
index.php
<?php
/**
* Front controller
*
* PHP version 5.4
*/
/**
* Autoloader
*/
spl_autoload_register(function ($class) {
$root = dirname(__DIR__); // get the parent directory
$file = $root . '/' . str_replace('\\', '/', $class) . '.php';
if (is_readable($file)) {
require $root . '/' . str_replace('\\', '/', $class) . '.php';
}
});
/**
* Routing
*/
$router = new Core\Router();
// Add the routes
$router->add('', ['controller' => 'Home', 'action' => 'index']);
$router->add('{controller}/{action}');
$router->add('{controller}/{id:\d+}/{action}');
$router->dispatch($_SERVER['REQUEST_URI']);
.htaccess
# Remove index.php from the request but maintain the query string
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
#RewriteRule ^(.*)$ /index.php?$1
</IfModule>
#---working--
#<IfModule mod_rewrite.c>
# RewriteEngine On
# Options +FollowSymLinks -Indexes
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteRule ^(.*)$ index.php [QSA,L]
#</IfModule>
#-also has no error---
#<IfModule mod_rewrite.c>
# RewriteEngine On
# RewriteBase /
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteRule . /index.php [L]
#</IfModule>
<?php
namespace Core;
/**
* Router
*
* PHP version 5.4
*/
class Router
{
/**
* Associative array of routes (the routing table)
* @var array
*/
protected $routes = [];
/**
* Parameters from the matched route
* @var array
*/
protected $params = [];
/**
* Add a route to the routing table
*
* @param string $route The route URL
* @param array $params Parameters (controller, action, etc.)
*
* @return void
*/
public function add($route, $params = [])
{
// Convert the route to a regular expression: escape forward slashes
$route = preg_replace('/\//', '\\/', $route);
// Convert variables e.g. {controller}
$route = preg_replace('/\{([a-z]+)\}/', '(?P<\1>[a-z-]+)', $route);
// Convert variables with custom regular expressions e.g. {id:\d+}
$route = preg_replace('/\{([a-z]+):([^\}]+)\}/', '(?P<\1>\2)', $route);
// Add start and end delimiters, and case insensitive flag
$route = '/^' . $route . '$/i';
$this->routes[$route] = $params;
}
/**
* Get all the routes from the routing table
*
* @return array
*/
public function getRoutes()
{
return $this->routes;
}
/**
* Match the route to the routes in the routing table, setting the $params
* property if a route is found.
*
* @param string $url The route URL
*
* @return boolean true if a match found, false otherwise
*/
public function match($url)
{
foreach ($this->routes as $route => $params) {
if (preg_match($route, $url, $matches)) {
// Get named capture group values
foreach ($matches as $key => $match) {
if (is_string($key)) {
$params[$key] = $match;
}
}
$this->params = $params;
return true;
}
}
return false;
}
/**
* Get the currently matched parameters
*
* @return array
*/
public function getParams()
{
return $this->params;
}
/**
* Dispatch the route, creating the controller object and running the
* action method
*
* @param string $url The route URL
*
* @return void
*/
public function dispatch ($url)
{
$url = $this->removeQueryStringVariables($url);
#$url = trim($url, "/"); no route found
if ($this->match($url)) {
$controller = $this->params['controller'];
$controller = $this->convertToStudlyCaps($controller);
$controller = "App\Controllers\\$controller";
if (class_exists($controller)) {
$controller_object = new $controller();
$action = $this->params['action'];
$action = $this->convertToCamelCase($action);
if (is_callable([$controller_object, $action])) {
$controller_object->$action();
} else {
echo "Method $action (in controller $controller) not found";
}
} else {
echo "Controller class $controller not found";
}
} else {
echo 'No route matched.';
}
}
/**
* Convert the string with hyphens to StudlyCaps,
* e.g. post-authors => PostAuthors
*
* @param string $string The string to convert
*
* @return string
*/
protected function convertToStudlyCaps($string)
{
return str_replace(' ', '', ucwords(str_replace('-', ' ', $string)));
}
/**
* Convert the string with hyphens to camelCase,
* e.g. add-new => addNew
*
* @param string $string The string to convert
*
* @return string
*/
protected function convertToCamelCase($string)
{
return lcfirst($this->convertToStudlyCaps($string));
}
/**
* Remove the query string variables from the URL (if any). As the full
* query string is used for the route, any variables at the end will need
* to be removed before the route is matched to the routing table. For
* example:
*
* URL $_SERVER['QUERY_STRING'] Route
* -------------------------------------------------------------------
* localhost '' ''
* localhost/? '' ''
* localhost/?page=1 page=1 ''
* localhost/posts?page=1 posts&page=1 posts
* localhost/posts/index posts/index posts/index
* localhost/posts/index?page=1 posts/index&page=1 posts/index
*
* A URL of the format localhost/?page (one variable name, no value) won't
* work however. (NB. The .htaccess file converts the first ? to a & when
* it's passed through to the $_SERVER variable).
*
* @param string $url The full URL
*
* @return string The URL with the query string variables removed
*/
protected function removeQueryStringVariables($url)
{
if ($url != '') {
$parts = explode('&', $url, 2);
if (strpos($parts[0], '=') === false) {
$url = $parts[0];
} else {
$url = '';
}
}
return $url;
}
}
#-----------
Home.php
<?php
namespace App\Controllers;
/*
* Home controller
*
*/
;Class Home
{
/**
* show the index page
* @return void
*/
public function index()
{
echo 'Hello from the index action in the Home controller';
}
}
When I try URL with http://localhost/posts/index I have Hello from the index action in the Home controller
But when I try a query string in the URL like this http://localhost/posts/index?page=1
It return the same Hello from the index action in the Home controller While it should return the array [page]=1 as well
I also have the following warning Hello from the index action in the Home controllerPHP Warning: Undefined array key "REQUEST_URI"
I was looking online and in here since yesterday and tried many suggestions, but still could not get it working.
Please advise and many thanks
Its working now (retruns the query string from the URL). This is the changes I made:
in the index.php The last line was amended as shown below:
In the Router.php, the code in the dispatch function will be fetched as the following:
Finally I tried many alternatives in the .htaccess files (and kept the ones that work so you will see many hash-tagged code for reference and resources
Hope this help