Convert GET links to nice links - php

I'm using Codeigniter in my new web application, and I have a form in page which sends data via post to a server and that server returns the users back to my website but with the parameters via get with ugly links like example.com/id=12&code=Xxxx
What I would like to do, if it's possible and I've been searching and I can't find is how to convert those ugly links into nice friendly links ( example.com/12/Xxxx )
Thanks

You can't have a GET form transform into a nice URL directly. They will automatically become ?key=val format.
Your best option is to have a redirect header to translate the GET to the nice URL's.
eg:
$firstPart = $_GET['myKey'];
$secondPart = $_GET['mySecondKey'];
header('Location: ' . $requestURL . '/' . $firstPart . '/' . $secondPart);

Get parameters are basically standard for any Web API's so you will probably find that you will end up using them a lot so rather than hack fixes for each and every API create a middle man.
Create a new folder at the same level as your index.php (usually your site root). call this folder something like middleman
Add the middleman folder to the list of items in your .htaccess file that should not be routed through the index.php
Now for every API you use you can create a new .php file in the middleman folder which transforms all requests to one that your site can understand.
You then point your external API's to http://yoursite.com/middleman/api_name.php
The reason for creating the middleman is that Code Igniter obliterates the get array so it gets removed before you can process the requests and format them into something meaningful if you try to do it inside Code Igniter so we must perform the transformation outside of Code Igniter's scope.
an example file might looks like this:
mysite.pingback.php
<?php
$from = $_GET['ip'];
$time = $_GET['time'];
$post = $_GET['id'];
header('location: ../mysite/pingback/'.$from.'/'.$post.'/'.$time);
?>
So very simple files. but it also means that when a change is made to the external API it does not affect how your Code Igniter app works as you simple have to change your middleman.

Related

Phalcon redirect with new GET variables

What is the best way to redirect to same page with new &_GET variables added.
I want to do something like Google done in Analytics, WMT...
Lets say user opens the page www.example.com, I would like to redirect that to
www.exaple.com?lang=en&uid=01845654&p=1.
Also, if someone enters www.example.com?p=2&lang=fr I would like to keep that variables, just add necessary one.
Should I do it in ControllerBase or in DI or somewhere else? And what is the pest proper way to do it?
You should be able to do something along the following lines from one of your controllers:
$destination = ltrim($this->di->get('router')->getMatchedRoute()->getPattern(), '/');
$queryString = 'lang=en&uid=01845654&p=1'
return $this->response->redirect($destination . '?' . $queryString);
For the problem of keeping incoming GET parameters and setting only those that have not been used in the request, you would have to check for them manually (e.g. using $this->request->get(PARAM_NAME)) and then build your query string accordingly.

API Component Separation

I'm new to the world of API programming, I just have a bit of a side project at work at the moment and I'm learning as I write, so bear with me.
I'm unsure as to the best way to implement an API for multiple different functions. At the moment I just have a test script I run and an apache redirect that redirects anything under /api to this script, call it TestAPI.php (so /api/anything will redirect). I pass the path variable of the API to the script (so in that example the path would be 'anything').
At the moment I'm just writing it for 1 purpose, to look up some data based on the path, and eventually be about to update and delete etc with PUT/DELETE etc (it's restISH not restFUL). This is fine at the moment where everything redirects to this script, but what about if I need 2 different functions? So I want to look up a different data set? So for example now /api/data1 would go to the 1st set and /api/data2 would go to the second. This is where I start to get unsure.
Do I simply have 1 mega script that grows and grows so that /api/data1 and /api/data2 redirect to the same place (and thus handle any errors like 404s there). Or do I have a script for /api/data1 and /api/data2 with separate redirects to each, then a generic catchall for 404s (I would always like to return JSON/XML rather than HTML for a 404, so I need at least logic to return based on the Accept header).
As a 3rd option, do I have some sort of frontline controller that catches everything, then calls off to the sub components? So 1 script that is redirects to for anything under /api, which then calls off to the required components or 404s if it's an invalid path. This seems like the best way to do it to me, but I have no idea how. Do I have some section of the site that only that script can call, or do I use cURL from the frontline controller to the back end API sections (as I'd need to pass POST/PUT data I assume I'd have to use cURL, is there any other way?). How is this best implemented in Apache?
Yes, you use a front controller. The front controller can use convention like first thing after /api processes the request
i.e.
/api/firstprocessor/method1
/api/firstprocessor/method2
/api/secondprocessor/method14
You can check out Zend_Framework for an example of this in action, or it can be something as simple as
$name = 'Script_' . $this->generateCommandName($request->getPathVariable(1));
$this->executeScript($name, $request);
public function executeScript($class, Request $request) {
if (file_exists("scripts/".$class.'.php')) {
//include the script
require_once "scripts/".$class.'.php';
//execute the script
$command = new $class;
$command->execute($request);
}
}
Then all your scripts just have an execute method that uses $request to get $_GET or $_POST variables

Can a Directory alone load specific query on a page?

On websites such as facebook and many others you see URLs such as www.facebook.com/username. How does a URL such as this actually load the users information from a MySQL database? and what is the actual file it is displaying on? I would assume there's not really a folder for each user that it is referring to. If my question doesn't make sense can you at least point me in the right direction to set something like this up through PHP?
Again, I want example.com/username to load my users profile. How does this work?
By using apache's .htaccess file to manage a RewriteEngine, all of your pages can be funneled through an index.php file. After confirming that the requested page is not actually a page that you've intended to be a default part of your web page, you can fall back on the code below, to discover a user account. If a user account is not discovered, then the likelihood is that the page being accessed is simply a 404, which you could then redirect to as a catch-all scenario
.htaccess file
RewriteEngine on
RewriteBase /
RewriteRule !\.(xml|js|ico|gif|jpg|png|css|swf|php|txt|html|otf)$ index.php
php logic to run after confirming the requested page, isn't something like a contact-us page, or any typical web page an end user would be attempting to access.
if(preg_match("/^\/(?P<username>[^\/]*)/", $_SERVER['REDIRECT_URL'], $matches)) {
$result = mysql_query("SELECT * FROM users WHERE username = '" . mysql_real_escape_string($matches['username']) . "'");
if($user_record = mysql_fetch_row($result)) {
echo "DO WHATEVER YOUR HEART CONTENTS HERE :)";
} else {
header("Location: error-404.php");
}
}
It is all loaded dynamically via the database. For example, my Facebook name is "benroux". In facebook's user table, there is going to be a unique column called, lets say, nickname. When I visit Facebook, they are parsing the path info and essentially calling a query in the form:
select * from user where nickname = "{$nickName}"
Now, this is an over simplified example, but I hope it gives you an idea of what is going on here. The key is that there are 2 types of url vars, the facebook.com/pagename.php?id=blah and the restful style path info vars facebook.com/pagename/var1/var2/
If you are looking to have example.com/benroux load my user page, you need to make your index.php (I'll use PHP) load the path info ( http://php.net/manual/en/function.pathinfo.php ) and then query the database as I have described above.
try to
print_r($_SERVER);
you will get that parameters. Then you just need to split them.
Something like
$directory = $_SERVER['REQUEST_URI'].split('/')[1];
So, put $directory into query

PHP link control system

I have a question about "link control system" in PHP. The idea is to make script that could make different links than original - something like friendly links with .htaccess. In .htaccess make rule to redirect all traffic to script file - for example linkprocessor.php then in this file should be some conditions, mysql connect and pattern grabber from database(friendlyurl and originalurl columns). So if we write full address - example.com/defined-address it will redirect us(but not change address) to linkprocessor.php and then script is checking if /defined-address is in database, if is it will include certain(based on friendlyurl) originalurl file. Is that script would be optimal? That script could prevent from "hackers".
Example:
example.com/defined-address -> linkprocessor.php -> SELECT originalurl from table WHERE friendlyurl = /defined-address -> include originalurl
=> can be written incoherently but its hard to explain that precisely
What you are asking about here is the Front Controller pattern http://en.wikipedia.org/wiki/Front_controller.
There are various ways to implement it, using a sql database to map URI strings to files to include is a valid way to do it, but might be overkill. The same information could probably be hard coded in a php array.
The standard way to prevent hackers is to only allow whitelisted files to be included. In your case you are using an explicit map to determine which page to include, so it is not an issue.
Some code to get you started:
<?php
$map = array('/home' => 'included_1', '/details' => 'included_2' ... )
if (array_key_exists($_SERVER['REQUEST_URI'], $map)) {
include $map[$_SERVER['REQUEST_URI']]
}
else {
// Send a 404 response
}
What you're looking for is the Front End Controller design pattern.
You described the basic method for solving this, which is to redirect all incoming requests (minus requests for static content such as images, CSS files and JS files) to a single file. Generally this file is the index.php file in the site's root directory, but can be any file.
You can accomplish this redirection using .htaccess on Apache servers or web.config on IIS servers. For .htaccess you can google mod_rewrite and get a load of information that will help you along.
Once you have all of the requests being directed to your Front End Controller, you need to determine what the request is asking for. You can inspect PHP's $_SERVER['REQUEST_URI'] to see what the request is, and handle it accordingly.
The most extensible solutions to this problem that I've seen rely on controllers (classes) being in a specific location and 'static' files being in a separate location. Doing something like the following would make it trivially easy to extend the requests that your site will respond to:
/**
I am assuming at this point that the variable $request is an array
representing the current request. For example, if the request is for:
http://www.example.com/dir/page, $request will contain two entries,
'dir' and 'page'
**/
if(file_exists('/controllers/' . $request[0] . '.php')) {
require_once '/controllers/' . $request[0] . '.php';
$controller = new $request[0]();
$controller->dispatch($request);
} else if(file_exists( '/static/'.$request[0] . '.php')) {
require_once '/static/' . $request[0] . '.php';
} else
throw new Exception('404', 404);
The above is more pseudo-code than actual code, I won't guarantee that it will actually run but the idea is there.
To add another controller to your system, you would simply write a class, make sure that it has a dispatch method, and put it in the proper location.

How do you create domain.com/?stringhere without a .php extension

I want to create a link like the following:
http://www.myurl.com/?IDHERE
What i want to be able to do is be able to goto the above link, and then pull whats after the ? (in this case IDHERE) and be able to use that information to perform a MySQL lookup and return a page.
Can anyone point me into the right direction? please know this is using PHP not ASP
The issue here is not with your scripting language, but with your web server setup. I'll refer to these by their Apache names, but the features should be available in most web servers.
There are three features you might want to use:
1) content negotiation (mod_negotiation), which allows your web server to try a specified list of extensions in a specified order, for example: http://example.com/foo might be http://www.example.com/foo.html or http://example.com/foo.php
2) DirectoryIndex, which tells the web server that when a client asks for http://example.com it should look for a specified list of files in order, so it might server up http://example.com/index.html or http:/example.com/index.php
3) mod_rewrite, which allows you to basically rewrite the URL format received by the server. This allows you to do things like translate http://example.com/foo/bar/baz to http://example.com/foo/bar.php?page=baz
The rest is done by the backend script code as normal.
Create a default PHP file in that directory that will get loaded when no file name is specified (e.g. index.php). In your PHP script you can get the part after the question mark from the variable $_SERVER['QUERY_STRING'].
Do the following in your site's main index.php:
list($id) = array_keys($_GET);
// right now, $id represents the ID you're looking for.
// Do whatever you want with it.
In the link, form or whatever - index.php?id=someid
In your index.php file:
$_GET['id'] = $id
Now you can use it:
e.g.
echo $id;
Since it's your default page, it will work without the extension.
list($id) = array_keys($_GET);
// right now, $id represents the ID you're looking for.
// Do whatever you want with it.
this was exactly what i was looking for, though now i just need to create something to notify if nothing is there or not. Thank you all for your responses.
I would solve it by using .htaccess file if possible.
create a .htaccess file in the main directory with the content:
RewriteEngine on
RewriteRule cat/(.*)/(.*)/(.*)/$ /$1/$2.php?$3
that should translate "example.com/foo/bar/baz" to "example.com/foo/bar.php?page=baz"

Categories