Clean url in php mvc - php

In first .htaccess,I send url to public/index.php:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ public/index.php [NC,L]
And my public/index.php:
<?php
// define root path of the site
if(!defined('ROOT_PATH')){
define('ROOT_PATH','../');
}
require_once ROOT_PATH.'function/my_autoloader.php';
use application\controllers as controllers;
$uri=strtolower($_SERVER['REQUEST_URI']);
$actionName='';
$uriData=array();
$uriData=preg_split('/[\/\\\]/',$uri );
$actionName = (!empty($uriData[3])) ? preg_split('/[?].*/', $uriData[3] ): '' ;
$actionName =$actionName[0];
$controllerName = (!empty($uriData[2])) ? $uriData[2] : '' ;
switch ($controllerName) {
case 'manage':
$controller = new Controllers\manageController($controllerName,$actionName);
break;
default:
die('ERROR WE DON\'T HAVE THIS ACTION!');
exit;
break;
}
// function dispatch send url to controller layer
$controller->dispatch();
?>
I have this directory :
application
controller
models
view
public
css
java script
index.php
.htaccess
I want to have clean URL for example localhost/lib/manage/id/1 instead of localhost/lib/manage?id=1,what should I do ?

Using your current rewrite rules, everything is already redirected to your index.php file. And, as you are already doing, you should parse the URL to find all these URL parameters. This is called routing, and most PHP frameworks do it this way. With some simple parsing, you can transform localhost/lib/manage/id/1 to an array:
array(
'controller' => 'manage',
'id' => 1
)
We can simply do this, by first splitting the URL on a '/', and then looping over it to find the values:
$output = array();
$url = split('/', $_SERVER['REQUEST_URI']);
// the first part is the controller
$output['controller'] = array_shift($url);
while (count($url) >= 2) {
// take the next two elements from the array, and put them in the output
$key = array_shift($url);
$value = array_shift($url);
$output[$key] = $value;
}
Now the $output array contains a key => value pair like you want to. Though note that the code probably isn't very safe. It is just to show the concept, not really production-ready code.

You could do this by capturing part of the URL and and placing it as a querystring.
RewriteRule /lib/manage/id/([0-9]+) /lib/manage?id=$1 [L]
The string inside the parenthesis will be put into the $1 variable. If you have multiple () they will be put into $2, $3 and so on.

Related

Best way to remove = and ? from get method in PHP?

What's the best way to remove the = and ? in a URL from the get method in PHP? I'm working on the pagination structure of my website and currently this is what the URLs look like:
www.example/test/?page=3
I want it to look like this:
www.example/test/3
Can this be addressed directly in the PHP get method with some extra code or does it have to be done through an htaccess file?
This is what my htaccess file looks like right now:
RewriteBase /
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html
RewriteCond %{REQUEST_URI} /index\.html?$ [NC]
RewriteRule ^(.*)index\.html?$ "/$1" [NC,R=301,NE,L]
Here is my try, I compacted some already existing answer from different StackOverflow topics dealing with URL extraction and I came up with this solution :
<?php
function http_protocol() {
/**
* #see https://stackoverflow.com/a/6768831/3753055
*/
return (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://';
}
function http_host() {
return $_SERVER['HTTP_HOST'];
}
function http_uri() {
return parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
}
function http_refactored_query_strings() {
$queries = explode('&', $_SERVER['QUERY_STRING']);
$refactoredQueries = [];
foreach( $queries as $query ) {
$refactoredQueries[] = filter_var(explode('=', $query)[1], FILTER_SANITIZE_STRING);
}
$queries = implode('/', $refactoredQueries);
return $queries ?: '';
}
function http_refactored_url() {
return http_protocol() . http_host() . http_uri() . http_refactored_query_strings();
}
echo http_refactored_url();
?>
Tryied with some examples :
GET http://example.com/test.php : http://example.com/test.php
GET http://example.com/test.php?page=3 : http://example.com/test.php/3
GET https://example.com/test.php?view=page?page=3 : https://example.com/page/3
GET http://example.com/?page=3 : http://example.com/3
For the query string refactoring part, I used $_SERVER['QUERY_STRING] and exploded the value to & character. because the first ? is not contained in $_SERVER['QUERY_STRING']. So you come up with lot of arrays, containing strings like page=3, view=page, ... And foreach one, you split it using = delimiter and get the second element (index : 1) to append it to the solution.
Hope it helps
You can do this by using an intermediate page, say index.php and apply .htaccess rewrite only for index and load page based on GET[] on index.php.
You can refer this:
URL rewriting in PHP without htaccess

How do I get clean URLS for only 2 variables?

I've seen/read questions about clean URLs with .htaccess, but for the life of me, I cannot get them to work for my specific needs. I keep getting 404 message.
Example: www.mysite.com/article.php?id=1&title=my-blog-title
I would like for url to be: www.mysite.com/article/1/my-blog-title
Here's what I have so far in my .htaccess:
Options -MultiViews
#DirectorySlash on
RewriteCond %{HTTP_HOST} !^www [NC]
RewriteRule .* http://www.%{HTTP_HOST}%{REQUEST_URI} [L]
# Rewrite for article.php?id=1&title=Title-Goes-Here
RewriteRule ^article/([0-9]+)/([0-9a-zA-Z_-]+) article.php?id=$1&title=$2 [NC,L]
#Rewrite for certain files with .php extension
RewriteRule ^contact$ contact.php
RewriteRule ^blogs$ blogs.php
RewriteRule ^privacy-policy$ privacy-policy.php
RewriteRule ^terms-of-service$ terms-of-service.php
Also, is this how I would link to article? article.php?id=<?php echo $row_rsBlogs['id']; ?>&slug=<?php echo $row_rsBlogs['slug']; ?> or article/<?php echo $row_rsBlogs['id']; ?>/<?php echo $row_rsBlogs['slug']; ?>
I'm using Dreamweaver, but I am comfortable hand coding.
Thanks in advance.
You could use a dispatcher by telling the webserver to redirect all request to e.g. index.php..
In there a dispatch instance analizes the request and invokes certain controllers (e.g. articlesControllers)
class Dispatcher
{
// dispatch request to the appropriate controllers/method
public static function dispatch()
{
$url = explode('/', trim($_SERVER['REQUEST_URI'], '/'), 4);
/*
* If we are using apache module 'mod_rewrite' - shifting that 'request_uri'-array would be a bad idea :3
*/
//array_shift($url);
// get controllers name
$controller = !empty($url[0]) ? $url[0] . 'Controller' : 'indexController';
// get method name of controllers
$method = !empty($url[1]) ? $url[1] : 'index';
// get argument passed in to the method
$parameters = array();
if (!empty($url[2])) {
$arguments = explode('/', $url[2]);
foreach ($arguments as $argument) {
$keyValue = explode('=',$argument);
$parameters[$keyValue[0]] = $keyValue[1];
}
}
// create controllers instance and call the specified method
$cont = new $controller;
if(!method_exists($cont,$method)) {
throw new MethodNotFoundException("requested method \"". $method . "\" not found in controller \"" . $controller . "\"");
}
$cont->$method($parameters);
}
}
in .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php

RewriteRule: trying to get rid of dashes

I'm trying to rewrite dashes in URL so that they don't exist internally. For example this URL
localhost/mysite/about-me
"about-me" should be rewritten to "aboutme". I need this because the controller class name depends on this route string, and I obviously can't use dashes for this.
This is the condition and rule I found which I thought should fit my needs:
# Condition is to avoid rewrite on files within specified subdirs
RewriteCond $1 !^(css|img|ckeditor|scripts)
RewriteRule ^([^-]+)-([^-]+)$ $1$2 [L]
However it seems that it's not working, since the controller class Aboutme is not instanciated. I get a 404 error instead, and I don't have any problem with similar controller classes without a dash in their names.
Could you please give me a hand on this?
Why not go with routes?
$route['about-me'] = 'aboutme/index';
Try removing ^ and $
# Condition is to avoid rewrite on files within specified subdirs
RewriteCond $1 !^(css|img|ckeditor|scripts)
RewriteRule ([^-]+)-([^-]+) $1$2 [L]
You can extend the Router class.
In /application/core create a file called MY_Router.php (MY is the default prefix) and copy this into it;
<?php if (! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Router extends CI_Router {
function set_class($class) {
$this->class = str_replace('-', '_', $class);
}
function set_method($method) {
$this->method = str_replace('-', '_', $method);
}
function _validate_request($segments) {
// Does the requested controller exist in the root folder?
if (file_exists(APPPATH.'controllers/'.str_replace('-', '_', $segments[0]).'.php')) {
return $segments;
}
// Is the controller in a sub-folder?
if (is_dir(APPPATH.'controllers/'.$segments[0])) {
// Set the directory and remove it from the segment array
$this->set_directory($segments[0]);
$segments = array_slice($segments, 1);
if (count($segments) > 0) {
// Does the requested controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().str_replace('-', '_', $segments[0]).'.php')) {
show_404($this->fetch_directory().$segments[0]);
}
} else {
$this->set_class($this->default_controller);
$this->set_method('index');
// Does the default controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php')) {
$this->directory = '';
return array();
}
}
return $segments;
}
// Can't find the requested controller...
show_404($segments[0]);
}
}
This will automatically rewrite - to _ for you.
If you don't want underscores change the code to replace them with nothing;
all occurences of str_replace('-', '_', to str_replace('-', '',
Here is a way to do it with mod-rewrite:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/(.*)([\w]*)-([\w]*)(.*)/?$ [NC]
RewriteRule .* %1%2%3%4 [L,DPI]
Won't redirect but can do it adding R=301 like this [R=301,DPI,L].
Does not have to be about-me. Can be any words pair at any position. i.e.
localhost/mysite/about-me = .../aboutme or
localhost/mysite/folder1/folder2/folder3/my-folder = .../myfolder or
localhost/mysite/folder1/folder2/my-folder/folder3 = .../myfolder/...

codeigniter url segments containing leading slash

the url to access the method is like this:
http://localhost/site/cont/method
I want to access this method using GET method like this:
http://localhost/new-tera/paper/lookup_doi/segment but my segment part is already containing /like this:
http://localhost/lookup_doi/segment/containing/slashes
note that the whole segment/containing/slashes is one value.
I am getting this value in my method like this:
public function method ($variable)
{
echo $variable;
}
//output: segment
and not : segment/containing/slashes
CodeIgniter passes the rest of them as additional arguments. You can either specify the additional arguments (if the number is fixed) or use:
implode('/', func_get_args())
to get the entire string.
.htaccess mast be
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]
so ok...
$route = empty($_GET['route']) ? '' : $_GET['route'];
$exp = explode('/', $route);
results:
$exp[0] = new-tera
$exp[1] = paper
$exp[2] = lookup_doi
$exp[3] = segment
and so we mast be have routing! run example(with my projects):
if($exp[0] == '')
{
$file = $_SERVER['DOCUMENT_ROOT'] .'/controllers/controller_index.php';
}
else
{
$file = $_SERVER['DOCUMENT_ROOT'] .'/controllers/controller_'.$exp[0].'.php';
}
if(!file_exists($file))
{
engine :: away();
}
include_once $file;
$class = (empty($exp[0]) or !class_exists($exp[0])) ? 'class_index' : $exp[0];
$controller = new $class;
$method = (empty($exp[1]) or !method_exists($controller, $exp[1])) ? 'index' : $exp[1];
$controller -> $method();
you can add slashes by adding "%2F" in your query string hope this will work
segment = 'somethingwith%2F'
http://localhost/new-tera/paper/lookup_doi/segment
You can base64 encode it first and decode it after. Really, you can use a variety of methods to change the / to something else (i.e. a -) and change it back.
echo site_url('controller/method/' . base64_encode($variable));
public function method ($variable)
{
$variable = base64_decode($variable);
}

Zend_Router... Zend_Form... Mod_Rewrite... Rewrite URL get value pairs to slashes

I am submitting a normal <form method="get"> element to the current url... It's part of a search page. The resulting url is below.
http://domain.com/module/controller/action/get1/value1/?get2=get2&value3=value3
The problem is I am using <?= $this->url(array('page' => x)); ?> and similar to navigate around but I want to retain the $_GET params... Whenever I use it, it retains the / slashed $_GET params and looses the ?&= value pairs...
I want to use Mod_Rewrite to change the value pairs to slashes...
My current rule is..
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ zend.php [NC,L]
I'm not confident with Mod_Rewrite and I don't want to conflict with the existing rules.
I also like a trailing slash as well... so that would be a bonus...
Please help!! Many thanks...
PS...
Re "Zend_Router... Zend_Form.." in the title. I am using Zend_Form to construct the form and I realise that I could use javascript on the onSubmit function to write the URL... similarly I could use the Zend_Router to rewrite the url... I think Mod_rewrite is best though...
I do not know how to implement this, using regular expressions and mod_rewrite, but you can extend Zend_Controller_Router_Route like this and use it instead standard router:
<?php
class ZendY_Controller_Router_Route_GetAware extends
Zend_Controller_Router_Route
{
public static function getInstance(Zend_Config $config)
{
$reqs = ($config->reqs instanceof Zend_Config)
? $config->reqs->toArray() : array();
$defs = ($config->defaults instanceof Zend_Config)
? $config->defaults->toArray() : array();
return new self($config->route, $defs, $reqs);
}
public function match($path)
{
foreach ($_GET as $k => $v) {
if (is_array($v)) {
$v = implode(',', $v);
}
$path .= "{$this->_urlDelimiter}{$k}{$this->_urlDelimiter}{$v}";
}
parent::match($path);
}
}
I could not find a nice way to do this... so I resolved to write some minimised PHP code at the top of my zend.php.
list($sURL, $sQuery) = explode('?', $_SERVER['REQUEST_URI']);
$sOriginalURL = $sURL;
if ('/' !== substr($sURL, -1)) $sURL .= '/';
if (isset($sQuery)) {
foreach (explode('&', $sQuery) as $sPair) {
if (empty($sPair)) continue;
list($sKey, $sValue) = explode('=', $sPair);
$sURL .= $sKey . '/' . $sValue . '/';
}
}
if (isset($sQuery) || $sOriginalURL !== $sURL) header(sprintf('Location: %s', $sURL));
If anyone can improve on this please comment below.

Categories