URL Routing using RewriteRule - php

I am trying to create my own PHP MVC framework for learning purpose. I have the following directory structure:
localhost/mvc:
.htaccess
index.php
application
controller
model
view
config/
routes.php
error/
error.php
Inside application/config/routes.php I have the following code:
$route['default_controller'] = "MyController";
Now what I am trying to achieve is when any user visits my root directory using browser I want to get the value of $route['default_controller'] from route.php file and load the php class inside the folder controller that matches with the value .
And also if any user tries to visit my application using an url like this: localhost/mvc/cars, I want to search the class name cars inside my controller folder and load it. In case there is no class called cars then I want to take the user to error/error.php
I guess to achieve the above targets I have to work with the .htaccess file in the root directory. Could you please tell me what to code there? If there is any other way to achieve this please suggest me.
I have tried to use the .htaccess codes from here, but its not working for me

It all sounds well and good from a buzzword standpoint, but to me this is all a little confusing because I see PHP's model as an MVC model already. It's providing the API for you to program with and deliver your content to your web server Apache and your database (something like MySQL). It translates the code(model) for you into HTML(view) ... provided that's what you intend, and you're supplying code as the user input (control). Getting too wrapped up in the terminologies gets a little distracting and can lead to chaos when you bring someone in to collaborate who isn't familiar with your conventions. (This should probably never be used in a production environment for a paying gig.)
I can tell you that on the page that you referenced they guy's .htaccess file needs a little work. The [L] flag tells mod_rewrite that this is the last command to process when the rule returns true. So you would either need to do this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
Or the following... but he was using a passthru flag which means that he is implying there are other things that could be processed prior to the last rule (eg. might be rewrite_base or alias), but that's not actually the case with his .htaccess file since it's a little bare. So this code would work similar to the code above but not exactly the same. They can't be used together though, and really there would be no need to:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php?url=$1
</IfModule>
The difference is the in the way it's processed. On the first .htaccess example you're passing any file to index.php regardless of whether it exists or not. You can [accidentally] rewrite a path that has a real file so that the real file is never accessed using this method. An example might be you have a file called site.css that can't be accessed because it's being redirected back to index.php.
On the second ruleset he's at least checking to see if the server doesn't have a file or a directory by the name being requested, then they're forwarding it to index.php as a $_GET variable (which seems a little pointless).
The way I typically write these (since I know mod_rewrite is already loaded in the config) is to to this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^mydomain.com
RewriteRule (.*) http://www.mydomain.com/$1 [R=301,L]
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule .* index.php
In my PHP code I pull the $_SERVER['REQUEST_URI'] and match it against a list of URIs from the database. If there's a match then I know it's a real page (or at least a record existed at some point in time). If there's not a match, then I explode the request_uri and force it through the database using a FULLTEXT search to see what potentially might match on the site.
Note: if you blindly trust the request_uri and query the database directly without cleaning it you run the risk of SQL injection. You do not want to be pwnd.
<?php
$intended_path = $_SERVER['REQUEST_URI'];
if(in_array($intended_path,$uris_from_database)){
//show the page.
} else {
$search_phrase = preg_replace('!/!',' ',$intended_path);
$search_phrase = mysqli_real_escape_string($search_phrase);
$sql = "SELECT * FROM pages WHERE MATCH (title,content) AGAINST ('$search_phrase');"
}
Sorry if this sounds a bit pedantic, but I've had experience managing a couple of million dollar (scratch) website builds that have had their hurdles with people not sticking to a standard convention (or at least the agreed upon team consensus).

Related

How to change the name of the directory in url in php using htaccess?

How can I do to change the name of the url of my site which is: www.example.com/user/panel.php to www.example.com/username/panel.php where the "username" is unique for each user , And for each login would be the name of the user from database, as it is in jsfiddle.net, could they help me?
Personally I would not use .htaccess for this ( specifically )
that said most the time people do it this way
RewriteEngine On
RewriteRule ^users/([-a-zA-Z0-9_]+)/?$ index.php?user=$1 [L]
So if you had a url like
www.yoursite.com/users/someguy
Then it would pass it to apache ( and php ) as
www.yoursite.com/index.php?user=someguy
Then in PHP you could access it just using $_GET[user].
Now ignoring security concerns I may have ( you shouldn't rely on user input to tell who they are, they can lie about it) for this I would use what I call the URI method ( not URL ) a URI is an imaginary path. This is also the method employed by many MVC systems. So for this I will start with the URI
www.yoursite.com/index.php/users/someguy
Notice where the index.php is ( in the middle ). Then you do a .htaccess like this
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f #if not a real file
RewriteCond %{REQUEST_FILENAME} !-d #if not a real folder
RewriteRule ^(.*)$ index.php/$1 [L] #hide the index.php
So what this does is allow you to remove the index.php giving you a url like this
www.yoursite.com/users/someguy
Which is what we want, and looks basically the same as the first case.
Then you cam use the $_SERVER['QUERY_STRING'] supper global which will give you everything past index.php
/users/someguy
And you can split that up, route it somewhere, do whatever you need to with it. Like this
$uri = array_filter( explode('/', $_SERVER['QUERY_STRING'] ) );
//$uri = [ 'users', 'someguy' ];
Now the reason I like this more, is it's more flexible and it lets you use the query string the ?var part of the url for other stuff. ( like bookmarkable search forms ) ie. it feels less hacky because your not breaking the query parameters of a GET Request. Conversely, with the first method, if your .htaccess is sloppy you could make it were the query part of the URL is unusable on your site, and that just feels wrong to me.
It also easier to maintain, because it requires no further setup for additional pretty urls
For example:
Say you want prettyfy your product. Using the first method you would have to go back to the .htaccess add at least 1 more rule in:
RewriteEngine On
RewriteRule ^users/([-a-zA-Z0-9_]+)/?$ index.php?user=$1 [L]
RewriteRule ^products/(0-9_]+)/?$ index.php?product=$1 [L]
Possibly even more complex levels if you have product categories
RewriteRule ^produts/([-a-zA-Z0-9_]+)/(0-9_]+)/?$ index.php?category=$1&product_id=$2 [L]
After a wile you would wind up with dozens of rules in there, some of which may not be immediately clear as to what they do. Then you realize you spelled products as produts and have to start renaming things. It's just a mess later on.
Now using the second method you don't need to do any additional steps, besides routing it in your index page. You just put the url in
www.yoursite.com/products/123
And pull that stuff from the $_SERVER array with no further messing with rewrite rules.
Here is a previous answer I did that outlines how to build a basic router.
Oop php front controller issue
Make sense.

redirect to a dynamically non existing address using php

I have a userprofile system in which a dynamic page (profile.php) changes as the id of user changes..
For eg. profile.php?id=2 displays the profile of user having id=2.. But i want the address to be as user/user_name.php. So providing each user a unique profile-page address..
Is it possible without creating a seperate page for each user?
Thnx
Ok, let´s talk about apache´s mod_rewrite. Basically what people usually do is that they setup one php page eg. index.php and redirect all the requests there (except those that request existent files and directories) and index.php then routes these requests to proper files/presenters/controllers, etc.
I´m gonna show you a very simple example how can this be done, it´s just to give you the idea how it works in basics and ofc there are better ways to do this (for example take a look at some framework).
So here is the very simple .htaccess file, placed in the same directory as index.php:
<IfModule mod_rewrite.c>
RewriteEngine On
# prevents files starting with dot to be viewed by browser
RewriteRule /\.|^\. - [F]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?query=$1 [L]
</IfModule>
And here is the index.php:
<?php
$request = explode("/", $_GET["query"]);
// now you have your request in an array and you can do something with it
// like include proper files, passing it to your application class, whatever.
// for the sake of simplicity let me just show you the example of including a file
// based on the first query item
// first check it´s some file we want to be included
$pages = array("page1", "page2", "page3");
if(!in_array($request[0], $pages)) $request[0] = $pages[0];
include "pages/".$request[0];
But I highly recommend you not to reinvent the wheel and take a look at some existing php framework. You´ll find out that it saves you a lot of work, once you learn how to use it ofc. To mention some - Zend Framework, Symfony and the one I´m using - Nette Framework. There are many more, so choose whatever suits your needs.

.htaccess mod_rewrite URL query

I was hoping someone could help me out. I'm building a CRM application and need help modifying the .htaccess file to clean up the URLs. I've read every post regarding .htaccess and mod_rewrite and I've even tried using http://www.generateit.net/mod-rewrite/ to obtain the results with no success. Here is what I am attempting to do.
Let's call the base URL www.domain.com
We are using php with a mysql back-end and some jQuery and javascript
In that "root" folder is my .htaccess file. I'm not sure if I need a .htaccess file in each subdirectory or if one in the root is enough.
We have several actual directories of files including "crm", "sales", "finance", etc.
First off we want to strip off all the ".php" extensions which I am able to do myself thanks to these posts. However, the querying of the company and contact IDs are where I am stuck.
Right now if I load www.domain.com/crm/companies.php it displays all the companies in a list.
If I click on one of the companies it uses javascript to call a "goto_company(x)" jQuery script that writes a form and submit that form based on the ID (x) of the company. This works fine and keeps the links clean as all the end user sees is www.domain.com/crm/company.php. However you can't navigate directly to a company.
So we added a few lines in PHP to see if the POST is null and try a GET instead allowing us to do www.domain.com/crm/company.php?companyID=40 which displays company #40 out of the database.
I need to rewrite this link, and all other associated links to www.domain.com/crm/company/40
I've tried everything and nothing seems to work. Keep in mind that I need to do this for "contacts" and also on the sales portion of the app will need to do something for "deals".
To summarize here's what I am looking to do:
Change www.domain.com/crm/dash.php to www.domain.com/crm/dash
Change www.domain.com/crm/company.php?companyID=40 to www.domain.com/crm/company/40
Change www.domain.com/crm/contact.php?contactID=27 to www.domain.com/crm/contact/27
Change www.domain.com/sales/dash.php to www.domain.com/sales/dash
Change www.domain.com/sales/deal.php?dealID=6 to www.domain.com/sales/deal/6
(40, 27, and 6 are just arbitrary numbers as examples)
Just for reference, when I used the generateit.net/mod-rewrite site using www.domain.com/crm/company.php?companyID=40 as an example, here is what it told me to put in my .htaccess file:
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^crm/company/([^/]*)$ /crm/company.php?companyID=$1 [L]
Needless to say that didn't work.
OK here is an updated based on the help received from Gohn67 below
It is working with the exception of a small bug I can't seem to figure out. I have created the .htaccess file in the "crm" directory. Here is the code:
RewriteEngine On
RewriteRule ^test/([\d]+)$ /crm/company.php?companyID=$1 [L]
This rewrites www.domain.com/test/40 to www.domain.com/crm/company.php?companyID=40 so it's very close to what I need.
The bug is that I cannot replace "test" with the word "company" in my RewriteRule. I do not know why. I can put anything but the word "company" in there; even the names of other PHP files in the "crm" directory such as "contact" or "add-contact". As a further test I actually renamed company.php to test.php and changed the RewriteRule to:
RewriteRule ^company/([\d]+)$ /crm/test.php?companyID=$1 [L]
which worked.
Yeah, the generated rewrite looks kind of strange there. I'm not sure what it is trying to match here ([^/]*).
Here is an example that may work for you. I tested these on my system.
RewriteEngine On
RewriteRule ^crm/dash/?$ /crm/dash.php [L]
RewriteRule ^crm/company/([\d]+)/?$ /crm/company.php?companyID=$1 [L]
RewriteRule ^crm/contact/([\d]+)/?$ /crm/contact.php?contactID=$1 [L]
This is only a few of your routes as an example. I admit that they could be more robust though, because doing this way will lead to a lot of rewrite rules, some of which you could elminate with better regex patterns. But hopefully this gets you started.
Here are some updated rewrite rules taking into consideration a subdirectory. It also fixes a a mistake from above:
RewriteEngine On
RewriteBase /crm
RewriteRule ^dash/?$ dash.php [L]
RewriteRule ^company/([\d]+)/?$ company.php?companyID=$1 [L]
RewriteRule ^contact/([\d]+)/?$ contact.php?contactID=$1 [L]

Pretty URLs from DB

I am working on creating page links from DB like the following example.
Current page:
www.example.com/page.php?pid=7
In the DB it is saved as title "contact-us" under category "Company Info"
I want it to be like:
www.example.com/company-info/contact-us.html
I have tried different solution and answers but did not got any luck. I am not sure, where will be the PHP part and which rules to write for .htaccess files.
In apache (or .hataccess) do something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /proxy.php?_url=$1 [QSA,L]
So in a nutshell, if the resource being requested doens't exist, redirect it to a proxy.php file. From there $_REQUEST['_url'] will be the url the user was requesting.
Then create proxy.php in your home directory and add whatever logic you'd like to load the correct content.
If you use this from .htaccess, then you may need to add RewriteBase / to your config.
If you want to find this page by url, you will probably do this through php and .htaccess. Make a .htaccess that calls page.php for each and every request. You don't need the pid=7, because, well, how should the .htaccess know it is 7, right? :)
In page.php, you take the original url and split it on the slashes, so you get the category (company-info) and the page itself (contact-us.html). Then, you can look these up in the database. This is in a nutshell how many software works, including Wikipedia (MediaWiki) and CodeIgnitor.
Mind that 'company-info' isn't the same as 'Company Info'. You'll have to specify the url-version in the database to be able to use it for look-up.

how can i get my htaccess to make my url look like foo.bar/user with this snippet i have

I have been trying to get my urls to be more user friendly and I have come up with this set up
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ userpage?user=$1 [NC,L]
I added this to my .htaccess but I'm now i'm confused as to how to access these urls.
in my index.php when a user logs in i have tried to redirect the user using
userpage.php?user=s2xi
but the url parses as www.foo.bar/userpage.php?user=s2xi and not www.foo.bar/s2xi
and also tried this as a check to see if user exists (is there a better way?)
if($_GET['user'] != $_SESSION['username']){
header("Location: no_user.php");
}else{
//load page
}
I am using the Smarty template engine on my site and I have my 'themes' in directories that belong to members file
www.foo.bar/users/s2xi/themes
but i want www.foo.bar/s2xi to point to the persons profile page that is viewable by everyone else and not their accounts page.
You're missing the .php in your RewriteRule, if that's verbatim - eg, userpage? => userpage.php?.
However, you're going to run into some problems with this unless you're using a framework to help you distinguish between routes. If you switched to using a separate URI format for user pages (eg /user/foo) you wouldn't have conflicts; but as it stands currently, using .htaccess to rewrite your URLs in that format could potentially cause problems with many other parts of your app.
To do it with a separate URI format, change your last .htaccess line (the RewriteRule) to:
RewriteRule ^user/(.+)/?$ userpage.php?user=$1 [NC,L]
may want to consider adding QSA as well.

Categories