How to use directory names as options or parameters? - php

I don't even know how this method is called, I just know the behavior I want to achieve.
My example for this is Facebook. If you go to facebook.com/[username or id] you get to the profile page, but I can't imagine that they're creating a directory in their root folder and putting a index file in there for every user.
So how's the following behavior accomplished; You go to somepage.com/foo/bar/hello but actually you're requesting somepage.com/foo?bar=hello ?
Is this even possible with Apache and PHP?

I don't even know how this method is called, I just know the behavior I want to achieve.
That thing is called URI/URL and the local part of it is passed to a webserver. The webserver then processes the request.
Is this even possible with Apache and PHP?
Yes. Not even even. This is what a webserver is for. What happens on the server is entirely shielded by the HTTP protocol which knows only the URI/URL specification which does not regulate if and how that needs to match to concrete processes or files on the webserver.
For example with the Apache HTTP Server there is a famous module called Mod_Rewrite that does URL-Rewriting. Often in a fashion that the user with her browser does not take any notice of it.
Example configuration with a PHP file (Apache HTTPD):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
</IfModule>
In a PHP script you can obtain the URI/URL by making use of special variables like $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING'].

Commonly this is made with mod rewrite. There you can make a "path" to a variable of a script.
E.g. http://example.com/user/1/edit could be translated with mod rewrite to http://example.com/index.php?function=edit&userid=1
Such a rule would look like this:
RewriteEngine on
RewriteRule ^/user/([0-9]+)/([a-z]+)$ index.php=function=$2&userid=$1 [L]
The first line activated the rewrite module the second line has a regular expression which must match for rewrite the url internally. If you like you can also make that externally with an [R] modifier instad of the [L].
Have a look to the whole documentation to learn more.
The stuff in the breckets are so called flags which are also well documentated.
I hope that helps!

Related

How to clean a url with php without using htaccess?

I have a problem with a project I'm doing with PHP and it's in the URLs.
When I load a script like index.php everything works fine, the problem is when I load a script that is located within two or more directories.
In the URL the scripts with the routes begin to be enmeshed
Here is an example of the problem I have
I need to load a script, even if it is in several levels of nesting, make its functionality and in the url is reflected as:
I need to have something like this
1:
I thank you in advance.
Regards
You can't use PHP to achieve this. PHP is not responsible for determining if PHP (let along a particular PHP script) will handle any given URL.
You have to configure your webserver to do it. Since you mention .htaccess but provide no further information about your server, I'm going to assume you are using Apache HTTPD.
For Apache, that means using mod_rewrite, Alias or something similar. You can put the configuration for those tools in .htaccess, but you don't want to and the documentation advises not to use them.
So put your mod_rewrite or Alias configuration in the main Apache configuration.
You're going to need an htaccess rule no matter what. However, it doesn't have to be a mod_rewrite rule. The reason you need this rule is because PHP is not responsible for the routing - it is merely responsible for the execution of your script.
The point of the rule is to direct apache and instruct it to execute the right script (in your case, script32.php) while keeping the request uri as intact as possible.
There are two ways around it, basically.
Way 1 (cleaner): mod_rewrite
This is pretty straightforward, the set of rules you need are as follows:
# If the requested file name is a valid file/inode
RewriteCond %{REQUEST_FILENAME} -f [OR]
# ...or a directory
RewriteCond %{REQUEST_FILENAME} -d
# ...then throw them straight on it
RewriteRule (.*) - [L]
# ...otherwise, redirect to script32.php with the full content of the request in query string
RewriteRule (.*) /welcome/script32.php?$1 [L]
The requested URL is now in $_SERVER['QUERY_STRING'] and you can now do whatever you like with it in PHP
Way 2: catchall
This does not rely on mod_rewrite and may therefore be slightly faster. However, technically, it's a cheap hack. The way around it is as follows:
ErrorDocument 404 /welcome/script32.php
The requested URL can now be found in $_SERVER['REQUEST_URI'] and is available for parsing in PHP. However, with this, you've also disabled "legit" 404 errors from being generated through apache - and should make sure to obey proper behaviour in PHP to compensate.

How to have a PHP file be used for multiple URLs

I want to have a single PHP file that takes care of multiple URLs in a subdirectory.
For example, my site is http://www.startingtofeelit.com/. I want one php file, say, called playlist.php which would handle when a user goes to http://www.startingtofeelit.com/playlist/101 or if they go to http://www.startingtofeelit.com/playlist/142 etc. I want to be able to strip the number (101, 142 in my example urls above) to use as a variable (the playlist ID), so I can display the correct playlist.
I know that I can create an index.php in my playlist subdirectory and use GET variables like http://www.startingtofeelit.com/playlist?id=102 and get the ID that way, but this is much sloppier looking and I'd like to be able to know how to do it the other way.
My site is built on WordPress, but I don't think this should make a difference in any way.
Well, you cannot achieve this with PHP alone.
If you use Apache, you can use .htaccess
If you use IIS, you can use URL Rewrite
The basic idea behind those modules is to mapping from one URL to another URL. For example: you would want to map from
http://www.startingtofeelit.com/playlist/142 =>
http://www.startingtofeelit.com/playlist.php?id=142
You can express the URL mapping in regular expression. For example, in .htaccess (Apache). You can write like this
RewriteRule ^playlist/([0-9]+)/?$ playlist.php?id=$1
Noted that, you need to have .htaccess file in your website directory. Since, you are using Wordpress, chance that you have existed .htaccess is high. You can simply append that line of code to existed .htaccess
The following is an explanation of the regular expression:
^playlist/ # any URL start with playlist/
([0+9]+) # following by number, and store it as $1
/?$ # end with or without /
Mapping to
playlist.php?id=$1 # where $1 is taken from the matched number from our pattern.
This is usually handled in a way similar to what you already tried. However, it's common to use a re-writing script so that your application will accept a clean URL such as:
http://www.startingtofeelit.com/playlist/142
...and re-write it for your application as such:
http://www.startingtofeelit.com/playlist?id=142
For example, if you're using an Apache web server and have the mod_rewrite module installed and enabled, you can use the following snippet in an .htaccess file and use your GET parameter as you indicated you already know how to do. Other popular web servers have unique URL re-writing modules that will let you do the same.
<IfModule mod_rewrite.c>
RewriteEngine On
# Rewrite this:
# http://www.example.com/somepage/1
# ...into this:
# http://www.example.com/somepage?id=1
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>

htaccess rewrite rule not passing url vars when script file is same as rewrite directory

I'm trying to create nice urls with .htaccess files and have come across a weird issue.
I want to change portfolio.php?id=2 to /portfolio/2/
seems pretty simple solution
RewriteRule ^portfolio/([0-9]+)/$ /portfolio.php?id=$1 [L]
this does redirect to the correct script but when i try and run <?=$_GET['id'];?> it is undefined. but if change the script to something that does not equal the fake directory it works.
RewriteRule ^portfolio/([0-9]+)/$ /portfolioitem.php?id=$1 [L]
and just to make sure that it wasn't being caught by any other rules I tested this
RewriteRule ^portfolioitem/([0-9]+)/$ /portfolioitem.php?id=$1 [L]
and again it failed to pick up the id paramater!
any ideas?!
Cheers
This sounds suspiciously like a Multiviews related problem coupled with some PATH_INFO. The Multiviews option is part of mod_negotiation and it will try to match a requested URL path to a file path. It sees:
/portfolio/2/
And sees that there's a /portfolio.php file in the filesystem and assumes that this is what you want (which it is, but not in the same way). I'm willing to bet that instead of looking at $_GET['id'], which is blank of course since there are no GET params, if you look at $_SERVER['PATH_INFO'], you'll see it set to /2/. This is equivalent to going to:
/portfolio.php/2/
where the /2/ part gets passed to portfolio.php as part of the PATH_INFO. And since mod_negotiation is further up in the processing pipeline than mod_rewrite, your rewrite rules never get applied.
Try turning off multiviews. You can do this in your htaccess file using the Options directive (assuming your host has allowed Options):
Options -Multiviews

Rewriting url parameters using rewritemap and mysql

I realize this question has been beaten to death by a lot of people asking it, but most of the answers appear to be for a very specific case that only suits their needs, and so far I have not found a suitable solution (at least, as far as i can see).
My problem is that I am trying to make my website redirect URL parameters from an ID to an actual string.
For example:
www.example.com/?category=1
would display as:
www.example.com/software
while
www.example.com/?category=2
would be displayed as:
www.example.com/software/desktop
From what I've read up, I'm supposed to be looking into an apache rewritemap, and this is where my confusion comes in. I'd really rather not have to load from a flat txt file, as I'd like to make this as dynamic as possible, and I have read that I can make it read from a php file and read it from a MySQL database, which is what I'd like.
The problem with that is that I'm really not too sure what the proper way is of achieving this. The RewriteMap document only somewhat covers flat .txt files, and not achieving it with MySQL.
So basically what I'm asking is if someone can explain how to achieve what I'm looking for, or at least point me in the right direction. Most of the threads I've found so far have sadly not been too helpful as of yet, but it's possible I might have passed by useful ones.
If it helps, right now, my MySQL data is formatted in an inherited structure like so:
ID | Title | Link | Parent
1 | Software | /Software/ | NULL
2 | Desktop Software | /Software/Desktop/ | 1
2 | Mobile Software | /Software/Mobile/ | 2
PS:
I should add that most solutions I've found give this as the example:
RewriteMap examplemap prg:/path/to/file.php
RewriteRule (.*) ${examplemap:$1}
Yet it never gives information as to what is in that file.php, and how it queries and returns the value.
EDIT
I should mention that I am on a shared hosting server, not my own private one, and so I may not have access to all possible options
EDIT 2
Just for the sake of clarity:
What I'm trying to do is make it so that a user who accesses 'example.com/software' would be treated as though they are on 'example.com/?category=1'; basically prettying the link and making it more readable. The only thing is, I'm trying to read it from a database
If you don't have access to the server or vhost config, you can't use RewriteMap anyways. The map itself needs to be defined in either the server or vhost config, not in an htaccess file. But apache 2.4 has an option of using mod_dbd to use an SQL query to define a rewrite map.
If you need to access MySQL, you're probably better off doing all of this in PHP instead of using mod_rewrite. You'd use mod_rewrite to route to your php file, which would then redirect. Maybe something like this?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /file.php?link=$1 [L]
So when someone requests http://example.com/Software/Mobile/, the request gets rewritten to: /file.php?link=Software/Mobile/, and your file.php script would do the lookup.
Or if you actually mean the other way around:
RewriteCond %{QUERY_STRING} category=([0-9]+)
RewriteRule ^$ /file.php?ID=%1 [L]
So when someone requests http://example.com/?category=2, the request gets rewritten to: /file.php?ID=2 and the php script does the lookup.
My suggestion would be to look at utilizing a front controller pattern. I think that once you start getting into user friendly URL's or the concept of "routes", that the front controller can really simply things since you no longer have to worry about mapping specific URL's to specific controllers at the web server level.
If you have Apache mod_dir enabled (chances are you do), you could do something like this in your Apache config or .htaccess:
FallbackResource /index.php
This simple directive will direct any requests that would otherwise cause a 404 error to be directed to a front controller at /index.php.
This can also be done via mod_rewrite like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [L,QSA]
In the front controller, you could evaluate the URI and route the request to whatever logic need to handle the request. You could do this via lookup of routes from a database or a hard-coded array of routes or whatever. (I would suggest however that, if using a database, you have a cached version of the routes available for quick access).
There are a number of different PHP route controllers available such that you don't need to reinvent the wheel (most every modern framework has some sort of routing concept).

How to understand PHP's URL parsing/routing?

I just inherited a website built in PHP. The main page of www.mysite.com has a href to www.mysite.com/index/35.html somewhere in the page. In the site's root directory and its children there is no document 35.html.
The number 35 is actually an id found in a DB which also holds the html contents of the page.
If I load URL: www.mysite.com/index.php?id=35 the same page loads.
How does PHP know how to automatically convert
/index/35.html
to
/index.php?id=35
EDIT
Based on the answers, I have found a .htaccess file containing rewrite instructions that would explain the functionality.
However, IIS doesn't seem to (or is not configured) know how to use this. (probably because this is an Apache feature?)
So this begs the following question: Is there a way to configure IIS to work with this?
it will be done usign URL Rewriting using .htaccess - should be in the webroot.
It may look something like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
May have other bits, but what this basically tells apache is to send anything that DOES NOT physically exist to index.php
It doesn't. There is a mod_rewrite rule that rewrites from /index/foo to /index.php?id=foo, either in a .htaccess file somewhere or in the httpd configuration itself.
RewriteEngine On
RewriteRule ^index/([\d]+)\.html /index.php?id=$1 [NC,L]
This is off the top of my head. Any browsers trying to load an address starting with index/ has any number ending in .html will be internally redirected to index.php?id= whatever the number is.
Edit: Just saw that your working on IIS. This probably won't work for you. Sorry.
I think you will be using .htaccess to redirect all requests to index.php. From there You can pass the query string a routing class, which will parse the url and identify the unique ids.
In this case we can say like, your routing class will parse the request /index/35.html to indexController, indexAction, id=35. now you can pass this id to the model to get corresponding page contents
NB : Here I a am assuming you are using mvc pattern. Anyway it can be treated in your own way, with the concept remaining the same. Hope this make sence.

Categories