Let me first give you a little background to explain what I'm trying to do. My websites use URL's that look like this: MySite/World/Isthmus_of_Panama
I'm working on a major upgrade (and may eventually upgrade further by switching to a CMS, like Drupal or WordPress), and it sounds like the general consensus is that URL's with hyphens are better than underscores. So I'm changing my URL's to MySite/World/Isthmus-of-Panama. In the meantime, I'm also trying to figure out if I should change my URL's to all lower case, and what about special symbols like accents or parentheses?
And what if someone typed in a URL that looks like MySite/World/Isthmus of Panama ? Wikipedia has a script that automatically converts the spaces to underscores. It will also default to the correct URL if you use the wrong case.
Of course, if I change my URL's, I'll also have to forward visitors from my old URL's. It's getting very confusing.
Then I realized that I could cover all of the bases with a script that accepts any URL that matches the characters in my database, 1) regardless of case, 2) and regardless of whether multiple words are separated by hyphens, underscores, spaces or %20. So imagine the following URL's:
MySite/World/Isthmus-of-Panama
MySite/World/Isthmus of Panama
MySite/World/Isthums%20of%20Panama
MySite/World/isthumus_of_panama
MySite/World/Isthmus-of_PANAMA
Where the database value is Isthmus-of-Panama.
Below is one of my queries, where $MyURL = the database value URL (e.g. Isthmus-of-Panama). Can anyone tell me how to modify it so that all of the above URL's will be accepted, with the page then defaulting to the database value?
Wikipedia has a similar feature. If you go to their article about Crazy Horse, then replace the URL Crazy_Horse with crazy_horse or Crazy Horse, it will default to Crazy_Horse. Thanks.
$sql= "SELECT COUNT(URL) AS num FROM gs_reference
WHERE URL = :MyURL";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':MyURL',$MyURL,PDO::PARAM_STR);
$stmt->execute();
$Total = $stmt->fetch();
switch($Total['num'])
{
case 1:
// DISPLAY A PAGE
break;
case 0:
// 404 NOT FOUND ERROR
break;
default:
// DUPLICATE RESULTS
break;
}
I would convert input, example Isthums%20of%20Panama, to the database value in php.
If the converted value is equal to the input one then don't do a 301 redirect to the url with the converted text else do one
EDIT
I would create in database a column slug (generally called like this) which contain the text normalized (ascii character and -) and create an unique index on it
You could use this function to generate the slug in php: PHP function to make slug (URL string)
Related
I have a problem concerning php,mysql, apache's mod_rewrite and a slug function for friendly urls.
I have a table in mysql with series.
This table has an auto_increment ID and an unique_key string that is the name of the serie.
What I want to do is:
The user could write something like series/name-of-a-serie (because I would prefer to use the unique string more than IDs in this case), and I would get something like series.php?serieName=name-of-a-serie but the name I have in the database is "name of a serie"
then I was thinking about revert the slugged string to take back the original... but then I have other problem:
If I have a function that replace white spaces with hyphens, I would have problems with, for example, the string "this - name",because if I revert the process, I would get "this name" and that's not the original name.
Any ideas?
Thanks id advance and sorry because i'm not english and I can't express myself as well as I would like.
You could always use a second column in your database where you store the already clean up version of the series name, like removing all special characters, substitute spaces with dashes and so on.
When using that link, you just have to check the database for that prepared text and get the real entry.
As far as i know wordpress does is exactly this way. They store a url-friendly post_name with every post that you can use.
By passing all urls through a script (via .htaccess) they can check for all those variants and show the corresponding pages.
Please see How to rewrite urls in wordpress for some details.
some code to clean up your titles might be like:
// Define all the characters you want to get rid of / replace
$arrBadChars = array('Ä', 'Ö', 'Ü', 'ä', 'ö', 'ü', 'ß', ' ', '_', '~', '-/', chr(10), chr(13));
// define the corresponding characters/texts for the above ones
$arrGoodChars = array ('ae', 'oe', 'ue', 'ae', 'oe', 'ue', 'ss', '-', '', '/', '', '','');
// Replace the bad with the good ones
$strNewTitle = str_replace($arrBadChars, $arrGoodChars, html_entity_decode($strTitle));
// simply paranoia, to remove everything else you might not have thought of above...
$strNewTitle = preg_replace('#[^[:space:]~a-zA-Z0-9_-]#', '', $strNewTitle);
the $strNewTitle is the one you could save and use for your URL.
If you are sure that you won't have any - in the Database Title, simply do that:
$id=str_replace("-"," ",$_GET['id']);
$stm=$db->prepare("SELECT * FROM movie WHERE movie_title=:movie");
$result=$stm->execute(array(":movie"=>$id))->fetchAll();
You can also use any other replacement character, like _ in the URL.
This way you can keep friendly URLs but also maintain your Database Titles. Another way which I have seen sometimes is to create a second database field which stores the URL.
The solution to this problem is to use numeric identifers in the URL. You said the table already has been implemented this way, so it is easy to do. The basic concept is to extract the numeric id from the url, and then verify that the slug is equal to the slug in your database. If not, then redirect to the correct one (301). This is the most popular pattern that I've recognized.
Your URL will look like this:
http://example.com/12345/name-of-a-serie
However you get that ID is up to you, but mod_rewrite, will work.
$id = $_GET['id'];
$slug = $_GET['slug'];
// verify the id
$record = getRecord($id);
if(! $record) exit;
if($record->slug != $slug) {
$slug = $record->slug;
// these values are NOT arbitary, because we have validated the record
// against the arbitrary ID first, so we're safe. as long as your
// internal API is using prepared statements.
header("Location: /$id/$slug");
exit;
}
If you want to revert from a slugged string back to the original string, you have to ensure that the slugging function is bijective, then write the reverse function.
BTW, slugging functions can't be bijective since they map an extended charset (the one of your language) to a restricted charset (the one used in urls).
Hopefully, if the slug has a UNIQUE constraint in your table, you can use it in your PHP code as a key to retrieve your item, thus its name.
Thank you very much.
I have now an idea of what I could do.
Every time I Insert a new tittle in DB, I would check the original name.
If there is already an entry, then that means that this movie has already in the DB,
If not, I would insert the original tittle and the slugged one.
In the case that "A serie" and "A-serie" were a completely different series but the slugged tittle were the same
"A serie" -> "A-serie"
"A-serie" -> "A-serie"
then I would only have to change the slugged tittle, something like:
ID | original name | slugged name
----------------------------------------------
201 | A name | a-name
----------------------------------------------
202 | A-name | a-name1
Being the slugged name the one that the user would write in the URL.
The URLs would be something like:
series/a-serie
series/a-serie1
I have a script that allows a user to submit a search query, usually in the form of a Site Name or using a device's MAC Address. I want to keep the search as simple as possible, so only want the one search field, and don't want to clutter it up with select fields or radio buttons for the user to specify which they're searching for. I want to take care of that automatically on the back-end.
Here is how I expect a Site Name to be searched by, in one of these formats:
The letters and numbers are just examples, can be anything, just in this format.
TX-DAL0099A1
TX-DAL0099A
TX-DAL0099
DAL0099A1
DAL0099A
DAL0099
OR By MAC Address
00 11 22 33 44 55
00:11:22:33:44:55
00.11.22.33.44.55
00-11-22-33-44-55
001122334455
I'm looking for the best way to first check if it's a Site Name (the first examples), and then if not, make sure it's a MAC address. I don't want to run a preg_replace function on the search query to strip any misc characters, like the hyphens, periods, colons, etc. because it's important to have the prefixed TX- portion of the Site Name - if it is in fact a Site Name that's being searched for.
Note: I would need to know if the Site Name does have the prefix, as well as the ending A/A1 from the examples. Those are important.
I hope that made sense. =/
Oh, and I'm doing this in PHP - forgot to mention that.
UPDATE: Would this code snippet work?
if(preg_match("/^([0-9A-F]{2}[:-\s]?){5}([0-9A-F]{2})$/", $input)) {
// SEARCH IS A MAC ADDRESS
}
else if((($query = $mysqli->query("SELECT * FROM `table` WHERE `site` LIKE '%$input%'")) !== false) && $query->num_rows() > 0) {
// SEARCH IS A SITE AND FOUND ROW IN DATABASE
}
else {
// NEITHER SITE NOR MAC, OR COULDN'T BE FOUND
}
Here are some snippets that should help.
See if we have a MAC address (regex pattern is taken (and tweaked) from What is a regular expression for a MAC Address?):
if(preg_match("/^([0-9A-F]{2}[:-\s]?){5}([0-9A-F]{2})$/", $input)) {
// We have a MAC address
}
See if we have a dash in the input (indicating a prefix) and what it is:
$siteNamePieces = explode("-",$input);
if(count($siteNamePieces) >= 2) {
// Site name has a prefix, and it is $siteNamePieces[0]
}
See if we end with A or A1:
if(substr($input, -1) == "A") {
// Ends in A
} else if(substr($input, -2) == "A1") {
// Ends in A1
}
I expect these will need to be adapted base on the different types of endings you're looking for, whether dashes can appear without necessarily meaning it's a prefix, etc. I'm guessing you need to pull off the prefix and the ending and get the core site name value for querying purposes.
Once you know what kind of data you're dealing with (mac address, site name) you can query your database appropriately.
Hopefully these will get you moving in the right direction!
The below SQL query will find rows where site is similar to the input, or mac is exactly the input.
SELECT * FROM `table` WHERE `site` LIKE '%$input%' OR `mac` = '$input';
you can try with variable1 ==== varaible2
it will compare the string with data type as it has three equals character
else it will only compare the values
I'm developing a web application where users have profiles, and skills related to that profile. I want to develop a page where a user can see all profiles that correspond to a particular skill. For example, if I wanted to see all users with the skill of "HTML" I could use http://site.com/skills/HTML. Pretty simple.
I've got it working, however some users have skills with spaces (for example project management) and some have special characters (for example C#). When I browse to a URL like http://site.com/skills/C#, Cake automatically makes it http://site.com/skills/C because it parses out the special character (# in this case).
How can I safely allow skills in the URL that have special characters in them? This is the action I'm currently using:
public function view($name) {
// Find skill using $name
$skill = $this->Skill->find('first', array(
'conditions' => array('Skill.name' => $name)
));
if(!$skill) {
// Skill doesn't exist, return 404
// TODO: route to 404 page
throw new NotFoundException();
}
$this->set('skill', $skill);
}
The # is a "special" character that by default jumps to a named anchor. In order to use special characters in an URL, you will need to use urlencode().
But please note that your URL's will not look "fancy", it will just be encoded to the raw HTML entity of the special character. In your case C# will become C%23. So you might want to consider using a different URL alias for your tag, like CSharp (you can just set a "background" database field to "translate" the original value to an URL-friendly one).
I'm new here I and need your help.
I started playing with .htaccess and php and I came across a problem.
When doing url rewriting, I pass into the url a string which is the title of an article extracted from the database. The problem is that the string(title) has a lot of characters who in the url are misspelled. EG: localhost/news/php%5%is%out
Here % are the blank spaces. I tried to format every title with preg_replace and I replaced every space with '-' but there are a lot of characters and I wanted to know if there is any way of doing this without preg_replace so any string can be good for a query.
In news.php I get the string from the url and I use it for the query in the database from which I extract the body of the entire article.
RewriteRule ^news/([a-zA-Z0-9._]+)/?$ /news.php?news_title=$1
This is my .htaccess file so in the news.php i get the 'news_title' variable through $_GET and then query the database to find the articol with this title.
So my question is, am I doing this all wrong? Is there any other way of doing this? I started working with htaccess only 2 days ago and I want to make my urls more friendly.
I hope my question is clear.
Thank everyone who helps me.
Just for an example, this is what I use to transform the normal tile in a string that won't be change with symbols(;amp, %, ?, etc) in the url
function generateUrl($url) {
$v1 = preg_replace("/[\s\:\;\,\_\'\`\"\?\!\%\(\)\+\=\#\#\[\]\{\}\/]/", "-", $url );
$v2= preg_replace('/[-]{2,}/', '-', $v1);
$v3 = preg_replace('/^[-]/', '', $v2);
$final = preg_replace('/[-]$/', '', $v3);
return $final;
}
I think the answer for your problem is here URL Friendly Username in PHP?. When you add article to the table, use this function (Slug) to convert article title and store converted title in column "slug". When user enters the address (.....)/article.php?name=some-title, use $slug = $_GET['title'] and find article by a slug. Before you save article you should check whether the article with this slug exists. If exists add to slug some number and then save to db. You can't allow to exists two record with the same slug in the table.
I have a site that offers a keyword search. The user can perform a search by either selecting from a set of pre-defined keywords displayed as hyperlinks or utilize a search form on the same page.
When the user searches for Russian Blue Cat, the following is added to the page URL:
If using the pre-defined hyperlink search term, then ?keywords=Russian%20Blue%20Cat is added to the URL as follows:
http://mydomain.com/index.php?keywords=Russian%20Blue%20Cat
If using the search form, then ?keywords=Russian+Blue+Cat is added to the URL as follows:
http://mydomain.com/index.php?keywords=russian+blue+cat
The following $_GET line of code is placed within two PHP files, the original index.php file that contain both the pre-defined hyperlink search terms and the search form and another PHP file called process.php that utilizes the keywords for another process.
if(empty($_GET['keywords'])){$keywords = '';} else {$keywords = $_GET['keywords'];}
The above $_GET line of code contained within the index.php file works properly and retrieves all three keywords. In this case the words Russian Blue Cat is retrieved.
The above $_GET line of code contained within the process.php file does not work properly and only retrieves the first of the three keywords. In this case only the word Russian is retrieved.
Is there a simple or proper way to fix this such that all keywords are retrieved properly?
Thank you in advance.
Check for the string '%20' and if present, explode by '%20'. Otherwise, check for the presence of a plus sign and explode by it instead.
This method is agnostic of the differing input format from the two sources entering the same script.
The caveat is that the string '%20' or the character '+' cannot occur inside a word in the other format or you will get unusual behavior.
$keyword = array();
if(stripos($keywords,"%20")) {
$keyword = explode("%20",$keywords);
}
else if(stripos($keywords,"+")) {
$keyword = explode("+",$keywords);
}
'$keyword' will then contain your keywords in an array.