Add 'username' to URL from 'user_id' with PHP for Dummies - php

I am attempting to publish a question which I know has many answers floating around Stack Overflow. However I, for some reason, just cannot seem to get the information in them to click. I will post my sources at the end of the question.
The question being, how can I pull a user_id from a URL & mod_rewrite it show the username.
Instead of this:
domain/user/index.php?user_id=1
I get this:
domain/username
I had customized other SO answers to my needs on my .htaccess file to this:
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
RewriteOptions MaxRedirects=1
RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule .* - [L]
RewriteRule ^user/([^/]+)$ index.php?user_id=$1
</IfModule>
The if statement at the top of my user page looks like this:
if (isset($_GET['user_id']) || isset($_GET['username']) && queryUserId($user_id)) {
// Render Page Content
} else {
header('Location: sign_up.php');
}
And my queryUsername functions looks like this:
function queryUsername($username) {
$conn = dbConnect('read');
$sql = "SELECT * FROM users WHERE user_id = '".$username."'";
$result = $conn->query($sql) or die(mysqli_error($conn));
$row = $result->fetch_assoc();
return $row['username'];
$username = $row['username'];
}
I have successfully implemented unique URL's for users, and am accessing Account Profiles just fine when appending different user_id's to my URL, so what am I missing to get the username written to the URL instead of variable strings and folder structure?
Cheers!
Other SO Questions:
Directly adding username to URL PHP
Get username from URL in PHP
Using mod rewrite to change URL with username variable
AddedBytes Article
URL Rewriting for Beginners

This line is wrong according to your information:
RewriteRule ^user/([^/]+)$ index.php?user_id=$1
It should at least be:
RewriteRule ^user/([^/]+)$ /user/index.php?user_id=$1 // for a url like domain/user/username
or using your description:
RewriteRule ^([^/]+)$ /user/index.php?user_id=$1 // for a url like domain/username
Also, you are not setting any variable with the name of username in the code you have shown, so the check for $_GET['username'] is unnecessary.
Your check in php should look something like:
if ( isset($_GET['user_id']) && queryUserId($_GET['user_id']) ) {
Apart from that you should not use the deprecated mysql_* functions and use prepared statements as you have an sql injection problem now.
Also note that using two return statements after each other only returns the first value.
Edit: There seems to be some confusion between the user ID and the username. If the value in the url is a username, you'd better call it username in both the .htaccess file and php to avoid confusion with the user ID:
RewriteRule ^([^/]+)$ /user/index.php?username=$1 // for a url like domain/username}
and
if ( isset($_GET['username']) && queryUserName($_GET['username']) ) {
in the function (using the deprecated functions just to illustrate...):
function queryUserName($username) {
$conn = dbConnect('read');
$sql = "SELECT * FROM users WHERE username = '".$username."'";
...
}

Related

.htaccess rewrite with GET variables

am trying to create a url like this using htaccess...
www.example.com/user/david
what i have now is this www.example.com/user?username=david
It works well when i do something like
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*/([a-zA-Z0-9_-]+)|([a-zA-Z0-9_-]+))$ ./user.php?username=$1 [L]
But i am wrong at my php code.
if(isset($_GET["username"]))
{
$stmt = $mysqli->prepare("SELECT * FROM campus_users WHERE campus_name = ?");
$stmt->bind_param("s", $campus_name );
$campus_name = trim($_GET["username"]);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows == 1) {
$row = $result->fetch_array(MYSQLI_ASSOC);
//displaying users rows
} else {
header("location: blank-page");
exit();
}
} else {
header("location: home.php");
exit();
}
But when i enter the url like this www.example.com/user?username=david it works well...
The problem is i want a smart looking url which isnt working due to my php i guess.
Please help me.
Thanks in advance.
If your URL with query string is working fine then it most probably it means your .htaccess rules are not working, usually we give user friendly URLs to users in your case it should be www.example.com/user/david and internally it should route to www.example.com/user.php?username=david. Please try following Rules in your .htaccess file.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/user/(.*)$
RewriteRule ^.*$ /user.php?username=%1 [QSA,NC,NE,L]
NOTE: if possible and you are not on prod systems then you could try to restart your Apache service too, though it's not necessary but sometimes it may be required. Also use user friendly URL as mentioned above in browser make sure you clear the browser cache before hitting it.

How to get URL path in PHP index file?

I'm using cpanel and php to create my website.
how i can get id from url http://example.com/id
problem is that when i'm trying to get url , im redirecting to file with id name 404 error !
and i can't get path in index.php page ?
for example when i try to get this url
http://example.com/01OWUY
i want to get 01OWUY with
$link .= $_SERVER['REQUEST_URI'];
code but i'm going to a 404 error
update :
every user have a id
with this id he can see her info
for example user with id 01OWUY can see her info from database
like this ->
<?php
require 'config.php';
//Database connection
$conn = mysqli_connect(SERVERNAME, USERNAME, PASSWORD, DBNAME);
$user = handle_user($conn, $_SERVER['REQUEST_URI'])
?>
and the function is this ->
// Return true if link is active
function handle_user($conn, $linkId)
{
$sql = "SELECT *FROM users WHERE link_id = '" . $linkId . "'";
$result = $conn->query($sql);
// get user data from db
if ($result->num_rows > 0) {
return $result;
}
return false;
}
but i get a 404 error !!!
You will need to load index.php if the file does not exist.
this is a very common practice in php frameworks like Laravel.
.htaccess file
# Not for real file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
for this to work you must have mod_rewrite enabled
Then you will have the data available in your index.php file.
you will still need to sanitize the input $_SERVER["REQUEST_URI"]
Recommendation for lightweight framework includes routing features:
Lumen
https://lumen.laravel.com/

Create subdomains on the fly with info from database

I am trying to achieve automatic subdomain creation. I have read a lot of tutorials including:
THIS
THIS
THIS
I understood the concept and I implemented it with success in the past for user profiles, but this is a different case and I am stuck.
What I want to do, is basically something like pen.io as functionality. A user creates a page with a password and then, that page name converts into a subdomain.
I thought of doing a function that runs on the index page of the main website and that one used afterwards in HTACCESS to have something like index.php?subdomain=test and that one to redirect to test.domain.tld
EDIT:
Here is the current implementation that works when clicking on a link, but it doesn't work when accessing the url directly from the browser:
Code used in view.php:
<?php
include('inc/config.php');
$url = filter_var($_GET['url'], FILTER_SANITIZE_STRING);
$conn = new mysqli($server, $username, $password, $database) or die ('Unable to execute query. '. mysqli_error($conn));
$query = "SELECT * FROM `pages` WHERE pageTitle = '$url'";
$result = $conn->query($query);
if($row = mysqli_fetch_array($result))
{
$title = $row['pageEditableTitle'];
$content = $row['pageContent'];
echo '<h5 class="mt-5"><mark>'.$title.'</mark></h5>
<p class="lead display-7">'.$content.'</p>';
} else {
echo '<br /><div class="alert alert-info" role="alert">Subdomain does not exist.</div>';
}
$conn->close();
?>
Code used in htaccess:
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.tld
RewriteRule ^(.*)$ https://domain.tld/view.php?url=%1 [L,NC,QSA]
But this redirects www.domain.tld to domain.tld/view.php?url=www and not staying as www.domain.tld in the browser url
I presuppose that you setup a wildcard dns entry (access random.domain.tld to test it!). Then you have two options:
Correct your rewrite rules
Something like [aA-zZ] should be [a-zA-Z] and the RewriteRule should be only after the RewriteCond and not in front of it and two of them. And do you really want to force a - inside the subdomain with ([a-z0-9][-a-z0-9]+)? Maybe you should check this answer. Note: The www inside of your domain is a subdomain as well. So it would rewrite to sub.php?url=www
With the corrected rewriting random.domain.tld returns the content of random.domain.tld/sub.php?url=random. But at the moment your sub.php does not return content. Instead it returns a http redirect to the URL random.domain.tld. This means your sub.php produces an infinite loop on itself. Instead sub.php should only contain something like <?php echo $_SERVER['HTTP_HOST']; ?>.
Maybe you did not understand how URL rewriting works. Then read this answer for further explanation.
Update1
You corrected your code as follows:
RewriteCond %{HTTP_HOST} ^([a-zA-Z0-9]+)\.domain\.tld\.?(:80)?$ [NC]
RewriteRule ([a-zA-Z0-9]+) /view.php?url=$1
But it's still wrong. As I said you need to read and understand this answer. #JoachimIsaksson uses $1 and %1 in his 2nd example:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^(.*)$ /subdomains/%1/$1 [L,NC,QSA]
%1 is the subdomain catched through RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com. And $1 is the path catched through RewriteRule ^(.*)$. You missed to use %1.
But your code can not work as you forced an unempty alphanummeric string by RewriteRule ([a-zA-Z0-9]+). But a path could contain more than that. For example a slash or question mark. And of course it could be empty as well.
And why did you add (:80)?? Do you think someone will access your domain with a specific port?
And why the last optional dot in tld\.??
At last you need to bring the flags into question. You used the NC flag. It means your rule is case-insensitive. So why do you use [a-zA-Z0-9]? As your rule is already case-insensitive it can be [a-z0-9]. And why don't you used the L and QSA flag? They are important.
Update2
Try this:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.tld
RewriteRule .* view.php?url=%1 [L,NC,QSA]
Use PHP only
$_SERVER['HTTP_HOST'] contains your full domain. This answer explains how to extract the subdomain name:
$subdomain = array_shift((explode('.', $_SERVER['HTTP_HOST'])));
Now you are able to use your general index.php to switch between your general page or the users subdomain content:
$domain_parts = explode('.', $_SERVER['HTTP_HOST']);
// access without any subdomain (TLDs like "co.uk" would "need == 4")
if (count(domain_parts) == 3) {
$subdomain = "www";
}
else {
$subdomain = array_shift($domain_parts);
}
if ($subdomain == 'www') {
// general page
}
else {
// users page
}

Not sure if .htaccess file is correct. Also some fetch problems from mySQL

I have som problems with getting data from my mySQL database after i implemented a more clean URL path.
Instead of: www.example.com/index.php?id=headline
I would have this path: www.example.com/article/headline
My .htaccess file is looking like this, and the path seems to work:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{THE_REQUEST} (\s|%20)
RewriteRule ^([^\s%20]+)(?:\s|%20)+([^\s%20]+)((?:\s|%20)+.*)$ $1-$2$3 [N,DPI]
RewriteRule ^([^\s%20]+)(?:\s|%20)+(.*)$ /$1-$2 [L,R=301,DPI]
RewriteRule ^article/(.*)/?$ index.php?id=$1 [NC,L]
RewriteCond %{REQUEST_URI} !\.(gif|jpg|png|ico|css|js)$
Then this is the link you have to click at, for coming to the article-page:
<a href="article/'. urldecode($row["overskrift"]) .'">
And the fetching from this $row is going smoothly.
The problem is when i then have to $_GET the id, it is like it won't fetch the next step properbly:
if(isset($_GET['id'])) {
$id = $_GET['id'];
$DB = "SELECT * FROM post WHERE overskrift = " . $id;
$fetch=$conn->query($DB);
$blogpost = $fetch->fetch_assoc();
An error appear on the last line, and i have struggled with this in about 3 hours now, but i really can't find the area where there is something wrong!
I can click on the link on the article on my frontpage, however i get this error when i am trying to enter an article:
Fatal error: Call to a member function fetch_assoc() on a non-object in /var/www/web/xxxxxxx/xxxxx.com/index.php on line 198
I hope someone can help.
Add a leading / to the rewrite rule match:
RewriteRule ^/article/(.*)/?$ index.php?id=$1 [NC,L]
Note that this would rewrite www.example.com/article/headline/something/else/ to www.example.com/index.php?id=headline/something/else, if that's not desired, use more restrictive character sets (like [A-z0-9_\- \.]) instead of .*
As for SQL, definitely suggest using PDO or similar to parameterize anything coming from request variables. Also worth doing some filter/sanitize on the variables before using them.
Worth outputting your SQL before running it so you can see it is as you expect. Also try copying that output and running it directly in mysql command line or via PHPMyAdmin (or another similar tool) to see if you get the data you expect.
if(isset($_GET['id'])) {
$id = $_GET['id'];
$DB = "SELECT * FROM post WHERE overskrift = " . $id;
echo '<pre>' . $DB . </pre>;
$fetch=$conn->query($DB);
$blogpost = $fetch->fetch_assoc();
Edit
Saw your response above. the issue with your SQL is that you are passing a string, but not encapsulating it in the SQL (note PDO paramterization would to this automagially for you). Your SQL line should read:
$DB = "SELECT * FROM post WHERE overskrift = '" . $id . "'";
But seriously.. don't do this. Parameterize it!

Rewrite URL, replacing ID with title in query string

I'm pretty new to mod_rewrite, but I've done some searching around and can't find an answer to this question. I've got a site which has only one PHP page serving up dozens of pages of content depending on the ID passed to it in the query string. I'd like to rewrite the URL so that this ID disappears and is replaced by the page's title as drawn from the database. For example
www.example.com/index.php?id=19
is replaced by
www.example.com/my-page-title
where "my-page-title" is the title of a page stored in the database at index 19.
Does anyone have any experience of this kind of rewrite, or is it even possible?
Thanks,
HR
Sure its possible, for a PHP script your .htaccess might look something like this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
This will rewrite all URLs except for directory or file names to "index.php?url=THE-TYPED-ADDRESS".
In your index.php you could then use the value of $_GET['url'] to determine the ID:
// init DB layer
if (isset($_GET['url']) && !empty($_GET['url'])) {
$url = my_filter_function($_GET['url']); // filter input
$pdo = my_get_pdo_function(); // get configured PDO objected
$query = "SELECT id FROM my_router_table WHERE url = ? LIMIT 1"; // use prepared statements for security/performance reasons
$stmt = $pdo->prepare($query);
$stmt->bindValue(1, $url, PDO::PARAM_STR); // bind the value as a string
// ternary operator expanded for readability
if ($stmt->execute()) {
$id = $stmt->fetch(PDO::FETCH_ASSOC);
} else {
$id = -1; // 404 page
}
// fetch content/render page according to ID
}
This is obviously an overly simplified example and you should really make sure you properly escape your input and use prepared statements to avoid security risks. Also, if you use MySQLi or another database access layer your prepare/execute/fetch code will vary slightly.
It's possible. You rewrite the url to send a $_GET-value, and use this value to find desired row. The url MUST be unique though, elsewise it can't find that unique row.
Example:
RewriteRule ^([\d\w-]+)$ index.php?slug=$1 [L]
This gives you the value $_GET['slug'] in PHP, which you can then use to find the value in the database.

Categories