Wordpress and CI rewrite rule in htaccess - wordpress

I have installed WordPress in example.com. I have also installed CodeIgniter in ci folder here example.com/ci/, ci is the folder name , register is the controller name and working URL of CI is example.com/ci/register . My base URL starts with https:// .
Now I have one WordPress URL example.com/hotel, hotel is the page that I have created in WordPress admin, it works fine.
I want to run my CI path like example.com/hotel/ci/register, I think we can do it with some rewrite rule so that my URL would look like example.com/hotel/ci/register. I have added given htaccess for wordpress that redirecting me here example.com/hotel/ci/register. It is showing me 404 error of CI. It means now I am in CI. Now I did following things in routes.php file.
$route['default_controller'] = 'register';
$route['404_override'] = 'register';
Now this URL example.com/hotel/ci/register is working, but this is not right way, next time there will be more controllers then it will not work.
Note: I can not create hotel folder because hotel is a page in the WordPress. If I create hotel folder then WordPress URL example.com/hotel/ will not work. It will redirect WordPress page to the hotel folder. So I have to do it without creating hotel folder. Note example.com=myurl.com .
I need to find another good solution.Any advise or guidance would be greatly appreciated?
Following is my reWrite rule in wordpress htaccess:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^/?hotel/ci/register(/.*)?$ /ci/$1 [L]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
And following is my CI htaccess:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond $1 !^(index\.php|resources|robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]
</IfModule>

Interesting problem! I set up a Docker container with a fresh install of Wordpress and Codeigniter, I created a hotel page in WP, and a Register controller and view in CI, and got testing. I spent way too long on this, but I did find an answer.
First, your Wordpress .htaccess. As #tobiv pointed out in a comment, you should not add anything between the BEGIN/END WordPress comments as it might get whacked by a WP update. Your redirect has to come before the standard WP rules though, so add it at the top of the file:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^hotel/ci/register /ci/register [L]
</IfModule>
# BEGIN WordPress
# ... These are the default, unchnaged WP rules
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
<IfModule mod_rewrite.c> and RewriteEngine On are duplicated which seems messy but you do need them, as your new rule has to go first so it processes the request before the WP rules do.
You don't need to modify the Codeigniter .htaccess file, the default one is all you need. It should be in the root of your Codeigniter installation, ci/.htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
At this point https://example.com/hotel/ci/register will show the Codeigniter 404 page. If you have logging enabled (see config/config.php), and you watch the logfile, you'll see why:
ERROR - 2017-11-14 17:57:20 --> 404 Page Not Found: Hotel/ci
And here's the root of the whole problem. Since the initial redirect is an internal redirect (means the URL shown in the browser does not change), the URI Codeigniter receives to process is the one still shown in the browser address bar - hotel/ci/register. Codeigniter will try to handle a request like that in 2 ways:
Look for a matching route in application/config/routes.php
Or look for a controller named application/controllers/Hotel.php, with a method called ci;
In our case there is no Hotel controller, and no route to describe how to handle such a request, so boom, 404.
One simple solution is to create a route to handle this request:
$route['hotel/ci/register'] = 'register/index';
And now https://example.com/hotel/ci/register works!
Notes:
Setting your default route to register ($route['default_controller'] = 'register';) means that https://example.com/ci/ will also show register. I'm not sure if you want that? You might run into duplicate-content SEO problems if that URL shows the same as https://example.com/hotel/ci/register, so maybe you want something else, or a 404, there.
Make sure you remove your $route['404_override'] = 'register'; route;
CI base_url is not relevant for this problem, though obviously should be set. Depending on how you want your links to be I think either http://example.com/ci/ or http://example.com/hotel/ci/ would be right.
I am not quite sure what the purpose of this condition in your CI .htaccess is for:
RewriteCond $1 !^(index\.php|resources|robots\.txt)
The existing default conditions already skip files and directories which exist on disk. That's what the !-f and !-d conditions mean - "if the requested pattern does not match a file or directory on disk, then do the redirect".
If you have a robots.txt file on disk (in your ci/ dir), and someone requests https://example.com/ci/robots.txt, the !-f condition will fail, and the rewrite is skipped - meaning the request is handled without rewrites and robots.txt is returned successfully. Same for index.php. If you have a directory called ci/resources, and someone requests https://example.com/ci/resources, the !-d condition will fail, the redirect is skipped, and the request is successfull.
I'm not sure about your resources part, but maybe you can remove that condition completely.
If you don't need pretty Codeigniter URLs (I mean other than https://example.com/hotel/ci/register, this change won't affect it), and it turns out you don't need that extra condition above, you can get rid of the CI .htaccess completely to simplify things. To do that, just change the Wordpress RewriteRule to the non-pretty version:
RewriteRule ^hotel/ci/register /ci/index.php/register [L]
And delete your CI .htacces.

I think you are on the right path, try this:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^/hotel/ci(/.*)?$ /ci/$1 [L] # remove the register part
# so that it would be handled by CI
# also remove the "?" in front of hotel
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
keep your CI htaccess as it is:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond $1 !^(index\.php|resources|robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]
</IfModule>
the last part is match your CI config.php to your new url model
$config['base_url'] = "http://example.com/hotel/ci/";

I don't thing this will be the great answer of your question but if i face the same problem i will use routes see the example code.
$route['(:any)/ci/register'] = "register";
what will the above code do (:any) means any word in first uri and after that you can defined any url you want i defined ci/register you can also do that like this.
$route['(:any)/register'] = "here_you_can_add_your_controller/function";
this will work if hit url like this.
http://www.example.com/any_word_you_want/register
it will hit your controller function. you need to echo something and it will show in your browser.
you can also defined the hotel word in your base url as #am05mhz shows in his answer but i don't thing that's a great idea because in future may you have 2 more words in your url.
Note : the above code example only work if your .htaccess give access of routs as you shows in your question the .htaccess is work for you. For full knowledge of routs please check the documentation of codeigniter URI routing

Use htaccess [P] flag instead.
Make sure the substitute (target) string will start with http://. Otherwise, it will treat the substitute string as an internal file path.
Check the code below.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^/?hotel/ci/(.*)?$ http://example.com/ci/$1 [P]
# If you want rewrite any URI as long it has */ci/* in it.
# Use the following rule instead.
# RewriteRule ^(.*)/ci/(.*)?$ http://example.com/ci/$1 [P]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Also, you don't need to update CI's base url. Empty string will do.
$config['base_url'] = '';
Hope that helps.
Links:
https://httpd.apache.org/docs/current/rewrite/flags.html#flag_p

Related

Redirect url of wordpress site on the basis of string using htaccess

I have a wordpress site eg. http://www.domain.com/ with custom theme hosted on a linux server and working fine. Some marketing strategy requires me to distinguish between 2 kinds of URLs (that they will be shooting from ads) and based on that redirect the site to different links.
eg:
If the URL contains /xyz/ ie:
http://www.domain.com/xyz/category/post I want it to be redirected to
an intermediate page ie: http://www.domain.com/intermediate.php and if
the url doesnt contain /xyz/ ie:
http://www.domain.com/category/post the post should show up as
usual.
I found out that this cant be done inside the wordpress code as before the first hook is triggered, the url is processed and a 404 page is thrown.
The only way I can achieve this is by modifying .htaccess file.
I found a code which reads:
RewriteRule ^(.*)/xyz/(.*)$ http://www.domain.com/intermediate.php [L,R=301]
and second way reads:
RewriteCond %{REQUEST_URI} /xyz/
RewriteRule .* http://www.domain.com/intermediate.php
I am really confused about using it with the existing code in the htaccess file created by wordpress which reads:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
I tried merging the codes ie:
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
RewriteBase /domain/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /domain/index.php [L]
RewriteCond %{REQUEST_URI} /xyz/
RewriteRule RewriteRule ^(.*)/xyz/(.*)$ http://domain.com/intermediate.php
</IfModule>
but only one of them work at a time ie: when the redirection works, wordpress posts doesnt show up and vice versa.
Kindly show me a better way.
Immediately after the RewriteEngine On and RewriteBase directives in the "existing" WordPress code try this:
RewriteRule xyz/ http://www.domain.com/intermediate.php [L,R=301]
This will search for "xyz/" anywhere in the requested URL and redirect when found. Note that in .htaccess files, the directory prefix (/ in this case) is removed from the URL path before pattern matching. So, a pattern that starts / will never match at the start of the URL.
External redirects should generally come before internal rewrites, which is what the default WordPress directives do.
The alternative method you mention is less efficient:
RewriteCond %{REQUEST_URI} /xyz/
RewriteRule .* http://www.domain.com/intermediate.php [R=301,L]
This will effectively do the same thing but will result in every request being processed because of the generic .* pattern. Note that the REQUEST_URI does start with a / (directory prefix).

.htaccess RewriteRule for WordPress: map example.com/yyyy/iframe/ to example.com/yyyy?iframe=1

In a WordPress website, all URLs with a trailing /iframe/ should be rewritten to ?iframe=1, e.g.:
mysite.com/page1/iframe/ should be rewritten as mysite.com/page1?iframe=1
For fun, I tried the following:
RewriteRule ^(.*)/iframe/$ http://microsoft.com [L]
Which is doing what I expected. The RegEx should be correct.
Next, I tried this:
RewriteRule ^(.*)/iframe/$ /$1?iframe=1
In context of WordPress' own rules, the complete file looks like this:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Here goes my line:
RewriteRule ^(.*)/iframe/$ /$1?iframe=1
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
But, despite all my tries and variations, the only thing I constantly get, is a 404.
Where am I going wrong?
When you do the redirect to ?iframe=1, you didn't add the [R] flag, which means the URL will not change in the address bar. This in turn means that Wordpress will see "/iframe/" as part of the URL, and tries to find a page or post with that URL. It doesn't find one, so it gives you a 404.
So modify your rule like this:
RewriteRule ^(.*)/iframe/$ /$1?iframe=1 [R,L]
The L flag makes sure that the processing of the rules ends after this rule, then starts over again. This is required to make the R kick in and actually rewrite the URL before it gets to the Wordpress part.
This does mean that ?iframe=1 will remain visible in your URL.

Modifying wordpress htaccess to forward certain urls to subdirectory

For whatever reason or another I haven't been able to ascertain, my company has decided to go with wordpress for one of their websites. They asked me to build an affiliate application on the same domain, which I did. Everything works great with the exception of this dilemma:
wordpress is installed in the root directory. All pages, videos, sales, etc are made from within wordpress pages.
The affiliate application is in a subdirectory /aff/ and affiliates' pages are found at mydomain.com/aff/index.php?aff=affiliateusername
Affiliates (and their leads) should be able to load their pages simply by typing in www.mydomain.com/affiliateusername but I am struggling to understand how to translate wordpress htaccess rules to do this.
Obviously the best order in which to have this work is for wordpress to first determine if there are any blogs/posts/pages that match the url term FIRST, and if none is found, then to redirect all else to www.mydomain.com/aff/index.php?aff=whatever
Here's what I was finally able to come up with that works for the index page and for the affiliate pages, but does not correctly load any wordpress pages other than index.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^(images|wp-admin|wp-content|wp-includes|go|compliance\.html)($|/) - [L]
#RewriteRule ^([^/].*)$ /aff/index.php?aff=$1 [R,L]
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
You can tell I've attempted to exclude certain directories from the rewrite but have not been successful. I've read other advice via Googling, to put the redirect rules ahead of the wordpress block, but there are few issues. When I put this line ahead of the # BEGIN WordPress line, I get an endless redirect loop which keeps going to /aff/index.php?aff=aff/index.php?... etc (this is the same line I use for the same affiliate application on a different, wordpress-free, domain)
#RewriteRule ^([^/].*)$ http://www.mydomain.com/aff/index.php?aff=$1 [L]
I feel like I'm missing something terribly obvious. Should I just be setting up wordpress to redirect all 404's to /aff/index.php?aff=originalrequest? How would I go about doing that?
Thanks in advance.
You are using RewriteRules incorrectly in place of RewriteConds. Adding them in between the WordPress rules is surely breaking your blog as well. Change your .htaccess code to:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/.]+)$ /aff/index.php?aff=$1 [R=301,QSA,L]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
If you want the URL to stay mydomain.com/affiliate remove the [R] and use only [QSA,L]. I've updated the rules above to show how to exclude a path from affiliate redirection. The following
RewriteCond %{REQUEST_URI} !^/blog\b
excludes all URLs pointing to /blog or its sub-directories /blog/sub/dirs from redirection. If there are root-level .php pages present (even if they are few) the exclusion can more easily be handled by changing the rule to
RewriteRule ^([^/.]+)$ /aff/index.php?aff=$1 [R=301,QSA,L]
assuming that a . and a / can never be present in an affiliate name.

CodeIgniter - multiple entry paths with other CMS on same site

Here's a weird question for everyone. I've got a situation where an existing site has wordpress running on it as the main CMS to the site, there's some additional code which can't be implemented in WP because of URL structures etc so we'd like to put CI on the same host.
However, there's two potential entry points needed for CI on that site - lets call them /userside and /adminside
I want both to share the same application and system folders which are all in the same accessible folder space.
I've got /userside working co-existing with WP quite easily.
Here's the .htaccess file
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^/userside [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /userside/index.php [L]
RewriteRule ^/adminside [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /adminside/index.php [L]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
My folder layout is as follows
FTP ROOT/
ci/ <- codeigniter root
application/
system/
http/
index.php <- WP index.php
adminside/
index.php <- CI index.php
userside/
index.php <- CI index.php
... wp-content etc
I've copied userside's files to adminside and tried symlinking as well but neither work.
In CI's application/config i've modified the base_url to be:
list($_trash, $_base, $rest) = explode('/', $_SERVER['REQUEST_URI'], 3);
$config['base_url'] = "http://".$_SERVER['HTTP_HOST']."/".$_base;
Which means it automatically puts the first segment of the URI as the application base, i've debugged this code and it sets it correctly.
Now here's the problem, when I access /userside/somecontroller, it works, however, when I access /adminside/somecontroller it doesn't. I get a 404 page.
I can get it to access the default controller's index() function by just accessing /adminside - that works but not when I specify a controller and method.
eg:
http://www.mysite.com/userside/mycontroller/mymethod <- works
http://www.mysite.com/userside/mycontroller/mymethod <- doesn't work - 404 displayed
/userside was set up first and I can't see anywhere that ties CI to /userside other than in application/config/config.php
Permissions have been checked and are identical, owners are identical.
Anyone got an idea why this isn't working? I don't want to have to split the site into a subdomain as we have specific reasons and as it works with /userside there's only something simple keeping me from making /adminside work as well.
You need the RewriteRule to get rid of index.php and append the method:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/userside(.*)$ /userside/index.php$1 [L]
RewriteRule ^/adminside(.*)$ /adminside/index.php$1 [L]
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
This was a little less complicated than I thought.
You simply put CI's .htaccess in the sub-folder you want to run CI in and then set the appropriate site URL variables to match.
I did find a document that showed how to give you access to all of WP's libraries from CI by simply loading wp-load.php from the root of the WP side in CI's index.php.
Hope this helps other people.

.htacess custom redirect rules conflicting with Wordpress redirect rules

I am in the process of moving my current static site to Wordpress, using the same domain name.
Both old and new sites have their content in the root folder and also have identical file names, but on the new (Wordpress) site, I have removed the .php extension that exists on the current site and added a trailing slash, as per Wordpress permalinks.
So I need to redirect all the old pages (for example):
/contact-us.php -> /contact-us/
I have tried the well-documented options such as (and variations on this):
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\.php$ /$1 [R=301,L]
But this seems to be conflicting with the Wordpress .htaccess rules:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
When I try to access www.site.com/contact-us.php, I am getting either an infinite loop OR a redirect to www.site.com/index (no .php, no trailing slash), which Wordpress displays as a 404 page.
I have tried with and without the first set of Rewrite conditions (as I see they are duplicated in the Wordpress rules), and also placed my rule before and after the Wordpress rules. No joy. I've also been Googling for the last few hours but no one seems to have addressed this specific problem. I do usually find what I am looking for by searching, so it's in desperation that I'm actually posting (and which is why it's my first post!)
If anyone can help out, I would be very grateful.
It appears you will run into loops when trying an .htaccess redirect because of the php suffix. Maybe someone else knows a solution.
But try a plugin called Redirection « WordPress Plugins. Out of curiosity, I tried a redirect from contact-us.php to contact-us/ and it worked fine. The plugin redirects via php rather than writing to .htaccess, and that may be the difference.
I use the plugin all the time to mostly log 404's and do a few redirects. It doesn't take too much site overhead.
Be sure and set Options to not do "URL Monitoring," as that will set up automatic redirects to to posts/pages that have their permalinks manually changed. And set your 404 logging to a day or two, because the logs can quickly get big and result in huge database tables.
Try using this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
#Rewrite /something.php to /something/
RewriteRule (.*)/(.*)\.php$ $1/$2/ [R=301,L]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
This method would rewrite:
/contact-us/test/hello.php -> /contact-us/test/hello/
If you don't want subdirectory rewriting replace line 6 with:
RewriteRule /(.*)\.php$ /$1/ [R=301,L]

Resources