back to

Clean URLs without the Query String

Tags: #<Tag:0x00007f26778b1128>


Hi all,

I’ve been trying to use rewrite rules to have phpList produce ‘Clean URLs’, that is without the query string. Thanks to the awesome assistance provided at Stackoverflow, I was able to apply the following rules.

RewriteEngine On
RewriteBase /mailinglist/
RewriteCond %{THE_REQUEST} \s/([^?]*?)/??p=([^\s&]+)\s [NC]
RewriteRule ^ /%1/%2? [R=301,L,NE]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([\w-]+)/?$ ?p=$1 [L,QSA]

(Credit goes to Anubhava at Stackoverflow.)

The intended result should be a redirect without the ‘?p=’:  ->

On my local machine, this works perfectly. However, there is something in phpList that causes the rules to malfunction in the live site: The query string does get purged out of the URL, but right after that happens, the site gets redirected back to the root!  ->  ->

Any help with this will be greatly appreciated.


Firstly, awesome work, thanks for sharing, and it’d be great if you solve this to find a way to make it available from stock phpList 3.

Secondly, it may be that your rewrite rules aren’t consistently applying to all requests to phpList. In which case the browser will probably be redirected back to the Web root (as you write is the case). You can use PHP global variables to check / log every request that is received by phpList. If im right then you want to hunt for the request which phpList receives which has not been transformed by apache back into the regular ?p=pagename format that it expects. When you find that you can fix it and hopefully resolve the issue.


Thanks Sam. However, credit goes to immensely smarter folk than me. I just go around asking questions to solve whatever pain-of-the-day.

I’ll look into this and see what I can come up with. But I was really hoping that the phpList developers, which know the code much more intimately, would explain why this cannot be done, or, how it could be done.

My guess is that query strings are an important function for phpList to deal with various aspects of campaign management, such as tracking and what not. The only problem I’m trying to solve here is giving each public page a distinct name that can be placed as a class on the document body- for theming purposes.


Regarding the page redirection, it seems to me it would be best if, rather than giving the pages arbitrary new names, you simply told apache to rewrite the URLs as paths with slashes between the parts of the path. That way you don’t need to know all the possible parameters or even page names, as apache will handle this for you, translating the requests into the type of page and parameter combination that phpList is used to. It would need to work both ways, of course, with apache also rewriting redirections and so on to the same path-based Format.

I don’t think you need to know about the internals of phpList to do this. You should only need to know the url format that phpList uses by default, so that you can write the mod_rewrite rules to do the translation.


That’s exactly what I would like to accomplish: Use all the default phpList paths to form ‘clean’ URLs. I never intended to ‘redirect’ to an entirely new page. /?p=subscribe remains /subscribe. I never intended the pages to have arbitrary paths or names at all.


By debugging $_REQUEST and $_SERVER you should be able to see what phpList is receiving, and fix whatever is wrong there.