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
Related
I want to cut a html link with php.
The html link is everytime the same pattern
domain.com/forum/members/84564-name.html
I want to get the 84564 from the name.
the /forum/members/ is everytime the same.
and the "-" after the user-id is also everstime the same.
Can you help me to extract the user id?
I'm going to assume the user id may not always be 5 digits.
$domainSplit = explode("/", $theDomain); // split into parts
$theIdSplit=explode("-", $domainSplit[3]); // split 84564-name.html
$id=$theIdSplit[0];
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)
I am trying to figure out the best way to make a nice looking profile URL in codeigniter.
Normally i would just like to a controller with a third url paramter (the profile id) like so:
http://thesite.com/profile/4
======
This isn't going to work for the site i'm building now because I want a nice looking url with the company name, like so:
http://thesite.com/profile/some-company-name
=======
Their are 2 problems with this and maybe i'm just not thinking straight today and the answer is obvious, but if the url is a hyphenated version of the company name, if 2 of the same company are in the database for some weird reason, then the profile might not be the correct one, really the only good way is to provide a profile id and pull by the id, but then my url doesn't look good...
How would you handle this situation? I guess i could always link to /profile/id and then in the controller just look up the profile and redirect to /profile/company-name, but then the user that went to the site and typed in /profile/company-name would get a 404 page.
Any good ideas for me?
Just check the guide, it shows you with the URL Helper:
Setup a model to handle your getter / setter (for profile name).
Getter gets the proper content to display, setter sets the profile name and handles duplicates (same names by adding a 1 etc;). Think of a createive way to eliminate collisions, addding state name or zip if you don't want something ugly.
Use url_title() to handle clean urls and eliminate odd characters:
$title = "What's wrong with CSS?";
$url_title = strtolower(url_title($title));
// Produces: whats-wrong-with-css
use urlencode and urldecode of php and routing
add in route.php in config
$route['profile/(:any)'] = "controller_link/$1";
then you can use urldecode on your controller file like
public function controller_link($name=FALSE)
{
if ($name != FALSE) {//check if name is passed
$queryname = urldecode($name);
//then query on that name in the database
}
}
if not clear then add comment.
Use unique name of company in Database, search your company by name, i use this function (helper) to translate name in slug.
if(!function_exists('slug')){
function slug($text)
{
// replace non letter or digits by -
$text = preg_replace('~[^\\pL\d]+~u', '-', $text);
// trim
$text = trim($text, '-');
// transliterate
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
// lowercase
$text = strtolower($text);
// remove unwanted characters
$text = preg_replace('~[^-\w]+~', '', $text);
return (!empty($text)) ? $text : FALSE ;
}
}
I've searched for an answer to this question already and found an article relating to it but it does not give an exact answer. That can be found here: PHP - How can I replace dashes with spaces?
I am using this function to convert my blog titles into SEO friendly URL strings:
//SEO Friendly URLS
public static function Seo($input){
$input = str_replace(array("'", "-"), "", $input);
$input = mb_convert_case($input, MB_CASE_LOWER, "UTF-8");
$input = preg_replace("#[^a-zA-Z0-9]+#", "-", $input);
$input = preg_replace("#(-){2,}#", "$1", $input);
$input = trim($input, "-");
return $input;
}
which will convert titles like so "My Blog Title" to "my-blog-title", which is good. However I usually pass the blog ID in the URL to get the blog from the database, but I'm trying to keep really friendly urls.
I understand I can pass the blog ID as a second query string on the end of the title like mysite.com/page.php?post=my-blog-post&id=1 but that still looks bad. I WILL be using .htaccess to remove the .php and '?' from the URL's, but I am unsure how to keep a pretty URL while passing the ID too.
How can I query the database while using the blog title as the URL query?
URL friendly versions of titles are often referred to as slugs. If you store the slug in the database table you could use it to retrieve articles. It would be best to store the slug anyway so that once a slug is created it is never changed.
For example, let's say you find and fix a bug in the Seo function, there's a possibility that it could change your URL, which is obviously bad SEO. Storing the slug in the database avoids that issue.
If you store the slug, you'll probably want a slug for each blog category as well. This way you're more closely imitating a filesystem and would no longer have to ensure that every slug was completely unique. While it's unlikely you'd have articles with the same title in different directories, it's something to consider as you build your site.
You can use mod_rewrite module for Apache. This is the most common practice.
Using .htaccess rewrite rule
RewriteRule ^([^?]*) index.php?route=$1 [L,QSA]
URL http://example.com/en/my-life/first-impression
will be "rewritten" and passed to index.php as GET parameter route.
Exploded it in PHP by dashes.
$parts = explode('/', $_GET['route']);
This is how you will get all parts of url and make your PHP logic accordingly,
$parts[0] => language code
$parts[1] => category
$parts[2] => post SEO title
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.