Friendly URL Database Strategies - php

I have a website that I want to start using friendly URLs.
So instead of:
http://server.com/company.php?id=12
I could use:
http://server.com/company/steaks_r_us
I know how to do this on the .htaccess side, but I don't know how to set it up on the backend with the database calls, especially if there is a chance that company name isn't unique (multiple locations for instance).
I've thought about inserting the friendly url into the database after checking for duplicates, but I'm curious if there is a better way

No matter if it's an ID or a user friendly string like company name, you need it to be a unique identifier. You won't avoid that.
There are couple of options.
Some websites adds ID (primary key) to the user friendly name like:
http://server.com/company/steaks_r_us_12
or in other part of URL like:
http://server.com/company/12/steaks_r_us
Then you can easily fetch the ID from the URL, but also it still looks nice.
Also as wheatin suggested, you could create a field in your DB that would be this unique identifier.
In this case you would need some additional logic at the time of creation of company row in database. That's of course because you have to handle duplicated names somehow.You could for example add a digit at the and of this value (facebook does something like that), so if a duplicate of steaks_r_us occurs, you would insert a value steaks_r_us2
Then you would have unique URL for these companies:
http://server.com/company/steaks_r_us
and
http://server.com/company/steaks_r_us2

You could create a unique index on the business key (in this case the company name) to prevent duplicates from being inserted in the first place.

Wheatin has the right idea. You'd want to have a table with two columns, the URL and the id it's referring to. If you made a unique key on the URL column, then you could just have a function/method that tries to insert the clean URL with the content id; I usually do something like
###(pseudocode)
function create_unique_url($url, $id) {
try to insert the url, id combination
if success:
return url
else:
key = 1
start a loop
try to insert the url+key, id combination
if success:
return url
key++
}
Adding a number to the end is a good fail-safe way to make sure you always get a unique url returned. Sort of how Drupal or Wordpress would handle a post url with an identical name.

Related

Dynamic URL rewriting using codeigniter/php/htaccess when change in url

I have URL like base_url()/controller/rowtitle-rowid.
Where this URL is manipulated using function and arranged according to row in database.
As mentioned above I need to change whole URL when I am changing rowid in the URL, that means it should rewrite to particular id of row in database.
For example:
Consider following URLs
https://www.marketsandmarkets.com/Market-Reports/medical-device-testing-market-254474064.html
2.https://www.marketsandmarkets.com/Market-Reports/timing-relay-market-241993160.html
if I change bold numbers in number 2 URL to bold numbers in number 1 URL then it will rewrite the URL to URL number 1 and redirect to URL number 1
Can this possible?
Thanks in advance.
Your say you are modifying the rowid which I assume are the numbers you are bolding in your 1,2 statements, and at the same time you want to redirect to a different slug and rowid which is the dashed statement before the rowid at the end of the url e.g. some-page-name.
I'm not sure what the rowid has to do with anything, perhaps it's just a random int to make sure you don't have duplicate slugs, but it isn't strictly required as long as you increment your titles if you have duplicates like some-page-name and some-page-name-1.
In PHP and codeigniter what you are trying to do is indeed possible as long as you keep a database with all the iterations of the slug. Then in your Market-Reports controller you just look for the most recent iteration of the slug and serve that as a link to the user. Or if the user is coming from a search engine, on the say Market-Reports single page controller to timing-relay-market-241993160 you query the database where rowid = 'someid' and order by created or something and then redirect the user to that slug which would be medical-device-testing-market-254474064.
Further if your database table for keeping track of slugs has the following rows rowid, rowtitle, fullslug you could literally just use intval() to get the rowid from the fullslug and do the same type of thing as I just outlined in the previous paragraph.
NOTE: You cannot do this with static HTML pages. I am assuming since you tagged PHP and codeigniter you are using php and controllers.

get row in mysql using data from friendly url and using regular expression

I need to write code for getting data from a database by a friendly url.
I have a table company with the field title for storing some info about a company. I want to get data by title using friendly url. E.g. example.com/company/aurum-1. First I tried to change some defined symbols to - :
function seoUrl2CompanyName($string) {
$string = preg_replace("/[-ecsui]/","%",$string);
return $string."%";
}
[-ecsui] is used because my native language has non-standard symbols like šįėęų which I cant use in my friendly url, so I tried to change them to % and use the following mysql to find the company by title:
$SQL = "SELECT * FROM company
"WHERE title LIKE '".seoUrl2CompanyName($_GET['company'])."';
But if I use this logic I meet with some difficulties when select return more than one row. E.g
example.com/company/aurum -> seoUrl2CompanyName('aurum')-> a%r%m% ->
like a%r%m% -> 24 rows in my table for match this pattern
My goal is to create the fastest way to find the company from company table by name using data from url.
I would take the suggest from #AgeDeO but expand your SQL like this, that you take the data the company-name reflects AND the ID you get from your URL:
$SQL = "SELECT *
FROM company
WHERE title LIKE '".seoUrl2CompanyName($_GET['company'])."'
AND ID = ".$myId.";
With these 2 factors, you should only get one row and can be sure, that no one just replace his 1 with a 2 and gets other companys data.
NEVER EVER DO THIS:
I want get data by title
What are you going to do when the company name changes? What when two companies have the same name? What happens with spaces, special characters etc...
I understand that you want friendly urls and that is possible, just add the company name as dummy data in the url. Show the company name but do not use it.
Use example.com/1/company/aurum-1 instead, where the 1 is the actual company id.
Beware that it is fairly easy to guess other companies like this. When I change the 1 in a 2 I could have access to the other company like this. If you do not want this, make sure you check for permissions on page load.

How to hide MySQL generated ID in URL

Right now I can get the information for a product in my database by simply using its ID in the URL lik so: http://www.example.com/?productID=5
Now I can guess the next one since these IDs are all auto incremented.
How would you hide this ID and replace it with something better? I mean it still has to be a unique identifier.
To complicate it a little I was thinking I could use a global unique identifier and add this in the database in another column. But I have the feeling that this is not the best way to do this :)
Please let me know your thoughts and tell me how you solved/would solve this in your project.
What I basically want is to get rid of knowing the next/previous ID.
There are no security limitations on the products themselves. Users are most likely allowed to see them. I was thinking that this technique could prevent crawling all products?!?
Like what amazon.com does: It looks like they hide the item's ID in some way, right?
You could also use a slug which works great for SEO. so Product 1 slug could be http://www.example.com/?productSlug=exampleitemnameasoneword
You just have to make sure slugs are unique. You would of course need a slug field in your database entry and be able to enter/edit it.
First of all, have a look at mod_rewrite.
I am making use of CakePhp, this allows me to have easy access to urls created by the .htaccess rules. In my case, my titles are 100% unique, which allows me to have a slug version of the title.
For example my title is SZD-51 Junior, this will become SZD-51_Junior. I just add this slug to my database and use this as a secondary unique identifier. When a user visits www.example.com/planes/SZD-51_Junior I can do something like:
// pseudo mysql
SELECT *
FROM table
WHERE slug = url_param
//in cakephp
$this->Plane->findBySlug($this->params['slug']);
There are a lot of approaches, what would you like the url to become? Which format?
you can use some kind of hashing algorithm like md5(), sha1() etc... and yes, it is better to store that hash in another column in your table for faster lookup.
If you use md5() it is a good practice to seed it with fixed or random salt string.
My favorite is to do it with microtime().
Generate hash before db insert:
$salt = "my_secret_salt_string";
$entry['hash_code'] = md5($salt . microtime()); // every time a different result is generated which will ensure uniqueness
// insert into ...
Or if you prefer using generated id as a salt, then update entry:
// insert into ...
// get id
$entry['hash_code'] = md5($id . microtime());
// update ...
A solution to this is to use post instead, this is just a quick mashup i did.
<?php
//how to handle the request
if(isset($_POST['transfer']) && !empty($_POST['transfer']))
{
$transfer = $_POST['transfer'];
//what to do?
}
?>
//how to make a link with id 5
link
//this is for the functionality
<form id="transfer_form" action="http://www.example.com/" method="POST">
<input type="hidden" id="transfer" name="productID" value="" />
</form>
//this should be placed within the <head>
<script>
function tranfer(link)
{
document.getElementById('transfer').value = link;
document.getElementById('transfer_form').submit();
}
</script>

MySQL Remove/Combine Similar Rows

I've got a problem that I just can't seem to find the answer to. I've developed a very small CRM-like application in PHP that's driven by MySQL. Users of this application can import new data to the database via an uploaded CSV file. One of the issues we're working to solve right now is duplicate, or more importantly, near duplicate records. For example, if I have the following:
Record A: [1, Bob, Jones, Atlanta, GA, 30327, (404) 555-1234]
and
Record B: [2, Bobby, Jones, Atlanta, GA, 30327, Bob's Shoe Store, (404) 555-1234]
I need a way to see that these are both similar, take the record with more information (in this case record B) and remove record A.
But here's where it gets even more complicated. This must be done upon importing new data, and a function I can execute to remove duplicates from the database at any time. I have been able to put something together in PHP that gets all duplicate rows from the MySQL table and matches them up by phone number, or by using implode() on all columns in the row and then using strlen() to decide the longest record.
There has got to be a better way of doing this, and one that is more accurate.
Do any of you have any brilliant suggestions that I may be able to implement or build on? It's obvious that when importing new data I'll need to open their CSV file into an array or temporary MySQL table, do the duplicate/similar search, then recompile the CSV file or add everything from the temporary table to the main table. I think. :)
I'm hoping that some of you can point out something that I may be missing that can scale somewhat decently and that's somewhat accurate. I'd rather present a list of duplicates we're 'unsure' about to a user that's 5 records long, not 5,000.
Thanks in advance!
Alex
If I were you I'd give a UNIQUE key to name, surname and phone number since in theory if all these three are equal then it means that it is a duplicate. I am thinking so because a phone number can have only one owner. Anyways, you should find a combination of 2-3 or maybe 4 columns and assign them a unique key. Once you have such a structure, run something like this:
// assuming that you have defined something like the following in your CREATE TABLE:
UNIQUE(phone, name, surname)
// then you should perform something like:
INSERT INTO your_table (phone, name, surname) VALUES ($val1, $val2, $val3)
ON DUPLICATE KEY UPDATE phone = IFNULL($val1, phone),
name = IFNULL($val2, name),
surname = IFNULL($val3, surname);
So basically, if the inserted value is a duplicate, this code will update the row, rather than inserting a new one. The IFNULL function performs a check to see whether the first expression is null or not. If it is null, then it picks the second expression, which in this case is the column value that already exists in your table. Hence, it will update your row with as much as information possible.
I don't think there're brilliant solutions. You need to determine priority of your data fields you can rely on for detecting similarity, for example phone, some kind of IDs, of some uniform address or official name.
You can save some cleaned up values (reduced to the same format like only digits in phones, concatenated full address) along with row which you would be able to use for similarity search when adding records.
Then you need to decide on data completeness in any case to update existing rows with more complete fields, or delete old and add new row.
Don't know any ready solutions for such a variable task and doubt they exist.

Constructing URL without item ID and getting right item

I have had this problem for a while,
Let say we have a movies website
And we have a movie named Test-movies123! in the database,
now what I would do is make a URL watch/test-movie123-{$id}/ and then query DB with the ID,
Now the issue with this is that the ID shouldn't be there, how can I go around this ?
if I get the test-movie123 from url and search it, I wont find it because it has no ! unless I use LIKE but thats not very trusty...
Anyone could suggest anything ? Would be much appreciated
Well, you could create a rule for taking the movie title and turning it into a slug. So, you'd know that you always lowercased the title, removed anything other than letters, numbers and dashes, and converted whitespace into a single dash.
Then store that in another column in your database, and be sure you are forcing uniqueness. Take the URL and search that column from that.
From that point you just have to deal with what happens if you have a second video uploaded that produces the exact same slug. There are a number of options for this ... append a random number slug, increment a number and append it, etc.
To do that, you may have in your database something like the primary_key as
"test-movies123".
Imagine you have a control panel, you insert movies in a form.
Then use the title Test Movies123! to save it in the database like this example:
id: AUTO_INCREMENT NUMBER
keyname: sanityTitle("Test Movies123!") <-- this should save "test-movies123"
title: "Test Movies123!"
stuff: "blablabla"
note sanityTitle() will be your function to prepare friendly url's from titles.
Then your url will look like
watch/test-movie123/ using regex control in url's
or
watch/?id=test-movie123 raw
You will search for the INDEXED or PRIMARY key, "keyname" in the table, it will output 1 row, with all your stuff.

Categories