I'm looking for a way to modify a request URL before it gets dispatched. For instance, the following URLs should be handled by the same controller/action:
/en/paris
/de/paris
/paris
I would like to capture the country code if it is present, then rewrite the URL without it so that controllers don't have to deal with it. I tried the 'dispatch:beforeDispatchLoop' event but it doesn't seam to be designed for that.
Any idea?
If you can convention that all country code comes first in the path, perhaps an additional rewrite rule can help you:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-z]{2})/(.*)$ index.php?_lang=$1&_url=/$2 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L]
</IfModule>
EDIT
If you really need to do this in PHP, I'd recommend you to intercept the country code at the earliest to not break the default routing behavior (i.e need to write all routes manually). One way to do this is by setting a shared service in your main DI to replace the default 'router' service. The customized router consist simply in a child of Phalcon\Mvc\Router with the method getRewriteUri overridden by something that does whatever you want them just return the URI without the country code part:
namespace MyApp\Services;
use Phalcon\Mvc\Router as PhRouter;
class Router extends PhRouter
{
public function getRewriteUri()
{
$originalUri = parent::getRewriteUri();
// Now you can:
// Check if a country code has been sent and extract it
// Store locale configurations to be used later
// Remove the country code from the URI
return $newUri;
}
}
Related
I have a web directory structure like so:
root
/content
/plugins
/myplugin
/Slim (folder containing Slim Framework)
index.php
/other_folder_1
/other_folder_2
.htaccess
index.html
I'm interested in what to specify in my .htaccess file in order to refer to a directory that isn't actually present on the server, but actually point to the Slim app in the /myplugin directory.
Here are a few example URLs, which I'd like users (or myself) to be able to use in the browser's location bar, or link with in documents:
1. http://example.com/nonexistent_dir
2. http://example.com/nonexistent_dir/info
3. http://example.com/nonexistent_dir/info/details
I'm trying to rewrite these URLs to the following:
1. http://example.com/content/plugins/myplugin/index.php
2. http://example.com/content/plugins/myplugin/index.php/info
3. http://example.com/content/plugins/myplugin/index.php/info/details
...which would all actually be handled by the index.php Slim Framework app in the /myplugin directory. It's important the apparent URLs remain as they appear in the first example, without being changed in the location bar.
Here's what is currently in the .htaccess file in the root directory:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/schedule [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /content/plugins/myplugin/index.php [QSA,NC,L]
</IfModule>
This redirects all 3 of the test examples to http://example.com/nonexistent_dir, using the / route. So my thought is that I should be capturing everything after the nonexistent_dir, whether it be something or nothing, and appending it to the end of the RewriteRule somehow. But I don't understand how.
I realize that using parentheses around an expression will enable me to use the contents as a variable, referred to it with $1 (or $2, $3... for multiples), but I don't know how to apply it to this solution.
Any help will be most appreciated.
Try:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^nonexistent_dir(/.*)?$ /content/plugins/myplugin/index.php$1 [L]
Slim actually discards the base directory, and sets $env['PATH_INFO'], taking the content of this variable to match against the specified routes.
For example, lets take a /sub/index.php (Slim index file) and this rewrite rule:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^somedir(/.*)?$ /sub/index.php$1 [L]
...and this route specification:
$app->route('/info', function() use ($app) { ... });
So, with a GET request to /somedir/info, Slim strips /somedir from REQUEST_URI and sets $env['PATH_INFO'] with value /info (this is actually done in the constructor of \Slim\Environment class).
Later, the Router class will match /info and execute the closure function.
If you want to pass parameters via url, the route would be, for example:
$app->get('/info/:param', function($param) use ($app){ ... })
Is it possible to use mod_rewrite to write an htaccess rule that takes a url parameter value (for example: id=1, where 'id' is the parameter, and '1' is the parameter value), query a database with the parameter value specified, and then write the value returned from the query as a part of the url of the requested page?
I know the basics of mod_rewrite, for example rewriting a url that appears like:
www.example.com/item.php?id=1
to the following:
www.example.com/item/1
An example of what I would require is writing the following url:
www.example.com/item.php?id=1
to this:
www.example.com/item/name-of-item-based-on-id-specified-in-original-url
However I have no idea if what I am looking to do is possible using mod_rewrite.
If anyone has a solution to this problem I'd be very grateful if you could help me. If what I am trying to do is not possible using htaccess and mod_rewrite, can someone please point me in the direction of how I may go about solving this problem?
It's possible, but you need to use a RewriteMap to define a mapping that you can use within a RewriteRule.
Apache version 2.2 doesn't have direct database access so you'll need to write a script that does the actual query then return the result. You can define this map using the "External Rewriting Program".
So if you have a script that takes "cats" from stdin, then queries the database, and returns "1", you'd define it like so:
RewriteMap item_lookup prg:/path/to/item_lookup.php
That directive has to be in your server or vhost config, it can't be in an htaccess file. But you can use the mapping in an htaccess file:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /item.php?id=${item_lookup:$1} [L]
So this takes the URI /cats and rewrites that to /item.php?id=1.
If you are using apache 2.4, then you can take advantage of the "DBD" map. You can insert a query right into the map definition, bypassing having to use an external script. You'd use it in the same way.
RewriteMap item_lookup "fastdbd:SELECT id FROM items WHERE name = %s"
Then use it in the same way:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /item.php?id=${item_lookup:$1} [L]
Without using a DBD/FastDBD query, I think you're honestly better off just doing the database lookup from item.php, since you'd be duplicating all of that work in a second external script anyways. Just add something like:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^item/([0-9]+)$ /item.php?id=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([A-Za-z0-9-]+)$ /item.php?name=$1 [L]
And in your item.php script, check for both id and name. If you have a name, do the database lookup in order to turn that into an id. It's much easier to manage, you don't need to have server/vhost config access, and you're not complicating matters by using a rewrite map.
I know that in Codeigniter, the default controller is always called if a controller is not specified in the url. Furthermore, if a function is not specified in the url, the index function of the controller will be called by default. However when I enter the following urls in the browser address bar I get different results for each:
http://localhost/appfolder/
And
http://localhost/appfolder/index.php/defaultController
For the first url, it seems that the user is not logged in even if indeed the user is logged in. The second url works fine and does the correct thing whether the user is logged in or not, that is, it excecutes the index function of the default controller. It seems to me that the first url doesn't excecute the index function of the default controller. I'm racking my brain trying to figure out why entering the two urls produces different results because according to what I know, they're supposed to have the same results; i.e they're both supposed to call the index function of the default controller.
I'm sort of a newbie in using codeigniter (have used it for about 2 and half months now) so any help would really be appreciated.
This is an edit:
I know most of the comments here are about using a htaccess file but isn't it supposed to work the same way whether index.php is in the url or not? Does anyone have any other suggestions on what I can do to pinpoint the problem?
If you want to access the site through the url http://localhost/appfolder instead of http://localhost/appfolder/index.php/defaultController you will need to set up a .htaccess file in your sites webroot folder (the folder containing index.php). This is pretty much what I use on my site (customized for your setup):
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /appfolder/index.php/$1 [L]
Alternative
RewriteEngine On
RewriteBase /appfolder
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
Similar question with plenty of discussion and other methods:
How to remove "index.php" in codeigniter's path
Set the default controller in the routes config file:
$route['default_controller'] = 'Blog';
From the docs:
CodeIgniter can be told to load a default controller when a URI is not present, as will be the case when only your site root URL is requested. To specify a default controller, open your application/config/routes.php file and set this variable.
Hey use this one in your htaccess file i think it will work............
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
I am having a serious issue with one application developed in CI.
Currently my URLs look like this
http://www.example.com/content/index/mission/
I want to remove /content/index/ from URL So, It should look something like this.
http://www.example.com/mission
I have routing and .htaccess method as well. But nothing seems to be working.
Here is my .htaccess file
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteCond $1 !^(index\.php|images|css/js/style/system/feature_tab/robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [QSA,L]
I have also tried routing of CI by defining reouters in config/router.php But it was not working :(
For your specific example, you'll want to create a route (in application/config/routes.php) that maps
$route['mission/']
to
"content/index/mission"
In other words, $route['mission/'] = "content/index/mission";
See the CI documentation regarding URI routing for more info
You can go into application/config/routes.php and set your own URL routing rules. (i.e. use something totally different than Controller/Funcction). There should be an array called $route which lets you assign mappings of url => controller/function. Hope this helps.
Check out this guide, its right up you're alley:
http://codeigniter.com/user_guide/general/routing.html
Let's say I have the project folder as follows:
folder/models
folder/view
folder/controls
folder/public
folder/library
Now let's say that the site folder is folder/public/ and inside that folder there's just one file called index.php. This file handle all the site page request via the GET parameter index.php?page=user for example will call the user.php file of the application in another folder. The point is that I'd like that an URL such as:
www.site.com/index.php?page=user&id=1
became
www.site.com/user/id/1
How can I do that?
This was taken from CakePHP .htacess rewrite rule:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
It will render everything under your host
http://www.site.com/* --> http://www.site.com/index.php?url=*
from here your index.php could parse $_GET['url']
//e.g browser requests www.site.com/user/id/1
$url = $_GET['url']; // user/id/1
$params = explode("/",$url); // array(0=>"user",1=>"id",2=>"1")
RewriteRule ^user/id/([0-9]+)$ index.php?page=user&id=$1
But it sounds to me that you should use so called router, redirect all trafic to index.php...
http://anantgarg.com/2009/03/13/write-your-own-php-mvc-framework-part-1/ (check out this link)
In your case there is no point in using /id/, but here you go:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/id/(.*) index.php?page=$1&id=$2
Or what's a way better approach:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php
Then handle the request in your index.php file by checking $_SERVER['REQUEST_URI'] against the patter you dream up.
Without apache rewrite rule, a micro framework named Slim can makes routing and templating for your php project. You'll define your routes only in index.php file. Like ;
Slim::get('/', function () {
Slim::render('index.template');
});
You will be implementing what is called the Front Controller pattern. If you Google that you will find several php implementations. I thought this series on building your own php framework was good.
http://fuelyourcoding.com/php-frameworks-just-roll-your-own-part-1/
Are you using Apache as web server?
If yes you can use *mod_rewrite* to accomplish that.
I have not done this myself, so I can't give you detailed instructions, but searching with google, using a search string like "mod_rewrite examples" lands you a lot of seemingly good tutorials.