Cakephp url customisation for SEO - url

I am developing a medical products search site. I need to display my site in search engines whenever a user try to search [COMPANY NAME] medicine [DISEASE]. For this, i created a page in my site which reads COMPANY NAME and DISEASE from url and lists all products.
Now i need to give this page a url like www.sitename.com/[COMPANY NAME]_medicine_[DISEASE].html
I am using Cakephp framework for development. Is there anyway to implement this url formatting in routes.php ? Or is there any other way ? please help.

how about separating them with slashes?
// www.sitename.com/[COMPANY NAME]/medicine/[DISEASE]
Router::connect('/:company/medicine/:disease', array('controller' => 'diseases', 'action' => 'index'),
array('pass'=>array('company','disease'),
'company'=>"[a-zA-Z\.]+*",
'disease'=>'[a-zA-Z\.]+'));
and the controller
function diseases($company,$disease){
}
I'm not sure if you can use the underscore instead of the slashes, I have never tried it before. if you do try I'd like to know the results =)
Good Luck
EDITED: ok, i was too curious about this issue and i wrote a route like this
Router::connect('/:company_medicine_:disease', array('controller' => 'pages', 'action' => 'test'),
array('pass'=>array('company','disease'),
'company'=>'[a-zA-Z]+',
'disease'=>'[a-zA-Z]+'));
and its not working u_U
as i suspected, the problem is that Cake thinks that the name of the custom route element is :company_medicine and not :company.. after a few minutes regarding/reading the code of Cake i found out the exact place where Cake parses the route and extracts the names of the passed elements. It's in /cake/libs/router.php in the class CakeRoute, method _writeRoute() (about line 1369):
preg_match_all('#:([A-Za-z0-9_-]+[A-Z0-9a-z])#', $parsed, $namedElements);
so as you can see in the regexp, the names of the elements can contain an underscore,therefore Cake thinks the name of the parameter is ":company_medicine".
So you have four solutions:
use slashes as separators for your urls
change the order of your parameter so it would be medicine_[COMPANY]_[DISEASE]
modify the line 1369 of the router.php to this (NOT RECOMENDED, i think it will break routes for plugins):
preg_match_all('#:([A-Za-z0-9]+)#', $parsed, $namedElements);
use url rewrite in your .htaccess to redirect all [COMPANY]_medicine_[DISEASE] to [COMPANY]/medicine/[DISEASE] so cake will see it separated by slashes and the browser will see it separated bu underscores. (I haven't tested it, i've never added another rule to the .htaccess for Cake =P)

Related

How to redirect old URL that hasn't any slug to new one which has a slug

Friends, this is a complex problem for me. I have researched on this many times and at last have came to you (with hope that I will get the solution). We had products URLs like:
/product_info.php/products_id/75
As per SEO, I wanted keyword rich URL so, we added a slug in products.php file and modified the URL as:
/product_info.php/products_id/75/product-title
But its also not an ideal URL. I wanted this as:
domainname.com/products/product-title/75
Changes I made in .htaccess file is as follows-
RewriteRule ^products/([A-Za-z0-9-]+)/([0-9]{2})/?$ product_info.php?products_id=$2=$1 [L]
RedirectMatch 301 ^/product_info.php/products_id/([0-9]{2})/([A-Za-z0-9-]+)$ http://www.livevaastu.com/products/$2/$1
Now problem is- our old URLs (which has no slugs) are indexed by Google. And I am not getting any idea how to redirect those old ones to new ones. Also there are many products pages so I couldn't redirect them one-by-one. You guys are genius. Can you help me any how. (without laughing on me). M not a developer.
You can't produce product_info.php?products_id=$2=$1 from your old URLs of /product_info.php/products_id/75 because they don't have the product title ("slug").
For one thing product_info.php?products_id=$2=$1 doesn't make any sense. Is that a typo? What are the key/value pairs in that query string?? This should look something like products_id=$1&product_title=$2 where each derived "value" from the mod_rewrite match gets assigned to a known "key", something you can use in $_GET or $_REQUEST to find the value.
Edit to help with what I think you are trying to achieve here, based on discussion:
If you want your old URLs to lead to the new "pretty" URLs, you will need to use PHP to do this. As mentioned, there simply is not adequate information in the URL to invent the product names. But you could pretty easily have something at the top of each page (i.e. in a header file) which looked to see if the "title" $_GET parameter is present or not (once you clean up the double-equal sign and replace it with proper key/value pairs). This might look something like:
<?php
if( !isset( $_GET['product_title'] ) ) {
// Code here to look up $product_title from the $product_id, presumably in a DB
header("HTTP/1.1 301 Moved Permanently");
header("Location: /products/$product_title/$product_id");
exit();
}

Instagram style unique URLs

I am developing a CakePHP application which allows for photo uploads. It would be really nice if i could give the user a friendly unique URL of something like instagram does, ie:
http://example.com/v/157fd to view their single photo post.
What is the best approach for this, i take it its going to involve CakePHP routing at some point, but has someone got an flow of what would happen when a URL like this is hit and how these unique URLs are formed?
Thanks
the route would be easy with one line (change the controller and action to yours):
Router::connect('/v/*', array('controller' => 'photos', 'action' => 'view'));
You can just use the photo id, or create your own random id. There's also a convenient way in cake to have random id, which is to use UUID

dynamic seo title for news articles

I have a news section where the pages resolve to urls like
newsArticle.php?id=210
What I would like to do is use the title from the database to create seo friendly titles like
newsArticle/joe-goes-to-town
Any ideas how I can achieve this?
Thanks,
R.
I suggest you actually include the ID in the URL, before the title part, and ignore the title itself when routing. So your URL might become
/news/210/joe-goes-to-town
That's exactly what Stack Overflow does, and it works well. It means that the title can change without links breaking.
Obviously the exact details will depend on what platform you're using - you haven't specified - but the basic steps will be:
When generating a link, take the article title and convert it into something URL-friendly; you probably want to remove all punctuation, and you should consider accented characters etc. Bear in mind that the title won't need to be unique, because you've got the ID as well
When handling a request to anything starting with /news, take the next part of the path, parse it as an integer and load the appropriate article.
Assuming you are using PHP and can alter your source code (this is quite mandatory to get the article's title), I'd do the following:
First, you'll need to have a function (or maybe a method in an object-oriented architecture) to generate the URLs for you in your code. You'd supply the function with the article object or the article ID and it returns the friendly URL with the ID and the friendly title.
Basically function url(Article $article) => URL.
You will also need some URL rewriting rules to remove the PHP script from the URL. For Apache, refer to the mod_rewrite documentation for details (RewriteEngine, RewriteRule, RewriteCond).

What's the correct way to use Cakephp urls?

it's my first post here :)
I'm having some difficulties with dealing with urls and parameters. I've gone through the router class api documentation over and over again and found nothing useful.
First of all, I'd like to know if there is any 'universal' format in CakePHP(1.3) for handling urls. I'm currently handling all my urls as simple arrays(in the format that Router::url and $html->link accepts) and it's easy as long as I only need to pass them as arguments to cake's own methods. It usually gets tricky if I need something else.
Mainly I'm having problems with converting string urls to the basic array format.
Let's say I want to convert $arrayUrl to string and than again into url:
$arrayUrl=array('controller'=>'SomeController','action'=>'someAction','someValue');
$url=Router::url($arrayUrl); //$url is now '/path/to/site/someController/someAction/someValue'
$url=Router::normalize($url); //remove '/path/to/site'
$parsed=Router::parse($url); /*$parsed is now
Array(
[controller] => someController
[action] => someAction
[named] => Array()
[pass] => Array([0] => someValue)
[plugin] =>
) */
That seems an awful lot of code to do something as simple as to convert between 2 core formats. Also, note that $parsed is still not in the same as $arrayUrl. Of course I could tweak $parsed manually and actually I've done that a few times as a quick patch but I'd like to get to the bottom of this.
I also noticed that when using prefix routing, $this->params in controller has the prefix embedded in the action(i.e. [action] => 'admin_edit') and the result of Router::parse() does not. Both of course have the prefix in it's own key.
To summarize, how do I convert an url between any of these 3(or 4, if you include the prefix thing) mentioned formats the right way?
Of course it would be easy to hack my way through this, but I'd still like to believe that cake is being developed by a bunch of people who have a lot more experience and insight than me, so I'm guessing there's a good reason for this "perceived misbehavior".
I've tried to present my problem as good as I can, but due to my rusty english skills, I had to take a few detours :) I'll explain more if needed.
The "official" format for Cake URLs should be the array notation array('controller' => 'foo', 'action' => 'bar', 'baz', 'admin' => true). Whenever you write URLs, you should use this format. The Router class will translate those to either strings (/admin/foo/bar/baz) or information needed for the Dispatcher (array('named' => array(), 'pass' => array(), …)), depending on where the URL is used.
You should think of it in terms of which controller action you want to invoke. URLs (as strings) are only a necessary evil to accomplish this in a web context. There shouldn't be any need for you to use the Dispatcher format. You should also not use the string notation when specifying URLs, since these can't be reverse-routed if you ever want to change your URL scheme.
Maybe you could explain with an example why you need to convert these three forms from one to the other?

Creating search engine friendly URL's in ASP.NET MVC

I would like to develop URL's which look like the following:
http://mysite.com/products/1/best-product-in-the-world
Where all i need to get to the proper record is the following route:
http://mysite.com/products/1
When I add the product description piece to the URL ("best-product-in-the-world") I get URL encoding issues. I've tried to use Server.UrlEncode when constructing this portion of my URL in an ActionLink(...):
<%= Html.ActionLink(item.Subject, "../Post/Detail",
new { id = item.ID,
descriptiveUrl = Server.UrlEncode(Product.ShortDescription) },
new { rel = "canonical",
title = Product.ShortDescription,
#class = "product-hyperlink" })%>
But this renders regularly encoded elements for special characters and spaces, much like the following:
http://localhost:2392/Products/Detail/1/best+product+in+the+world253f
...which creates a 400, bad request exception. Not sure I've done the question justice, but can provide further clarification if need be.
Update: this post's URL is as follows, and i'm trying to do something very similar!
http://stackoverflow.com/questions/1148955/creating-search-engine-friendly-urls-in-asp-net-mvc
In a deeper Google search, I found the following link for generating slugs:
http://www.intrepidstudios.com/blog/2009/2/10/function-to-generate-a-url-friendly-string.aspx
Thanks #Rob and #Coding the Wheel for giving me the terminology I really needed to find this answer!
A simple option would be to add a property to your model object with an accessor that normalises the appropriate field (short description in this case) down to a suitable "slug"; that is, the bit of junk text after the identifier. You then use this when constructing the URI.
The normalisation process might be as simple as removing any non-alphanumeric characters and replacing spaces with hyphens.
The standard practice here is to store a 'slug' with each post that will function as the post's outward-facing URL. For example, your slug for the above post would be:
best-product-in-the-world
A decent CMS will do this for you automatically, and allow you to tweak the slug before saving.

Resources