Zend routes & SEO - php

I was wondering how i would go about implementing my site's URLs like http://mysite.com/ArticleTitleHere using zend framework.
The way i see it is to implement a regex route, but this way zf will not be able to tell say an article URL from a regular module/controller/action or controller/action routes. How would i go about implementing such a thing?
Thanks

you can use placeholders for that in your route:
routes.test.route = "/:article"
routes.test.defaults.module = default
routes.test.defaults.controller = test
routes.test.defaults.action = test
routes.test.defaults.article = ""
You can retrieve the article parameter in your controller using $this->_getParam("article"). The rest (matching the database entry by the article's name) is your part.
But you should add something like an url-prefix and/or article id, otherwise other routes may not be found. So use something like this is much better:
routes.test.route = "/article/:id/:title"
routes.test.defaults.module = default
routes.test.defaults.controller = test
routes.test.defaults.action = test
routes.test.defaults.article = ""
routes.test.defaults.id = ""
You can use the url-Viewhelper this way to create a link:
<?php echo $this->escape($article->title); ?>
And in your controller for a redirect:
$this->_helper->redirector->gotoRoute(array("id" => $article->id, "title" => $article->title), "test");
Keep in mind escaping or filtering the $article->title for invalid characters (or non-ascii-characters).

Related

CodeIgniter Change URL Routes

I have a Real Estate Site, in CodeIgniter my link names is:
htp://examplesite(dot)com/property/31/en/property_title
I want to replace it with:
htp://examplesite(dot)com/my-custom-slug.htm
or
htp://examplesite(dot)com/property_title
Both ways might be ok. My routes are:
$route['default_controller'] = "frontend";
$route['404_override'] = 'frontend';
/* Custom routing */
$route['admin'] = 'admin/dashboard';
//$route['secret'] = 'admin/dashboard';
// To change property->listing in uri
$route['listing/(:num)/(:any)/(:any)'] = "property/$1/$2/$3";
$route['listing/(:num)/(:any)'] = "property/$1/$2";
what is the best way in this case?
I know there is a possible solution that:
Add
$config['listing_uri'] = 'listing';
Than add to:
In ‘application\config\routes.php’
After:
$route['listing/(:num)/(:any)/(:any)'] = "property/$1/$2/$3";
$route['listing/(:num)/(:any)'] = "property/$1/$2";
Add also:
$route['changed/(:num)/(:any)/(:any)'] = "property/$1/$2/$3";
$route['changed/(:num)/(:any)'] = "property/$1/$2";
but is there any way to remove the 'listing', to see only the clean url (for better seo purpose) ??
Welcome, luckily your problem isn't too big :)
Maybe have one slug before the property title to make the solution a bit more scalable:
$route["listing/(:any)"] = "property/view/$1";
Then point your browser to yoursite.com/listing/some_slug or yoursite.com/listing/12
You will need to have a slug associated with each property, otherwise you can use the id, and in the view function just retrieve the property based on the slug or id parameter.
If you don't want to include the listing/ you might have problems down the line when trying to create other routes.

Setting codeigniter custom route

I am trying to set a custom route for friendly url when loading a tag, by that I mean that I want to convert this: http://test.com/en/results?search_query=data&search=tag to this http://test.com/en/tag/data
Tried to do so by setting this in my routes.php:
$route['^(en|es|ro)/tag/(:any)'] = "fetch/results?search_query=$1&search=tag";
But no success, am I doing it wrong?
My routes.php:
$route['default_controller'] = "home";
// URI like '/en/about' -> use controller 'about'
$route['^(en|es|ro)/video/(.+)$'] = "video/id/$2";
$route['^(en|es|ro)/results$'] = "fetch/results$2";
$route['(en|es|ro)/tag/(:any)'] = "fetch/results?search_query=$2&search=tag";
$route['^(en|es|ro)/(.+)$'] = "$2";
// '/en', '/de', '/fr' and '/nl' URIs -> use default controller
$route['^(en|es|ro)$'] = $route['default_controller'];
$route['404_override'] = '';
I'm fairly sure the ^ is not necessary. Try without it:
$route['(en|es|ro)/tag/(:any)'] = "fetch/results?search_query=$1&search=tag";
In that context, ^ will be treated as a literal string. If you wanted top use a regex, I believe you'd have to wrap the regex itself in parentheses, like so:
$route['(^(en|es|ro))/tag/(:any)'] = "fetch/results?search_query=$1&search=tag";
I'm not 100% certain on that, but if I'm correct both should work. However, routes always assume the first part of the pattern is what the string should start with, so the ^ shouldn't be necessary anyways.
One more thing: You aren't using the second match, but the first. I believe you want to replace $1 with $2 in your route.
$route['(en|es|ro)/tag/(:any)'] = "fetch/results?search_query=$2&search=tag";
// ^^^1^^^^ ^^^2^^ ^^
EDIT: Upon further investigation and testing, it seems that Codeigniter cannot properly handle routes that use a query string like ?key=value. If you use a slash before the ? question mark, you can at least get it to route to the right controller and method:
$route['(en|es|ro)/tag/(:any)'] = "fetch/results/?search_query=$2&search=tag";
A url like this:
http://example.com/es/tag/Codeigniter's Router
...will be routed to the results method with this string as an argument, but $_GET will be empty:
?search_query=Codeigniter%27s%20Router&search=tag
So, you could pick apart the argument with parse_str():
function results($request)
{
$request = ltrim($request, '?');
parse_str($request, $get);
// echo $get['search_query']
}
You could always use .htaccess of course, but I understand the desire to keep all the routing logic in one place. Sorry if this isn't the answer you hoped for, but I'm afraid that without writing a custom router it's not possible to do this the obvious way in Codeigniter. My suggestion would probably be to find another way to handle your routing and the way you're accessing data from the URL.
You may need to escape the forwardslashes around tag. So it should look like this:
$route['^(en|es|ro)\/tag\/(:any)']
I have something similar, and it looks like
$route['(:any)/something/(:any)'] = "real/$2/path/$1";

Is there a way to change the route variable separator in Zend Framework?

I'd like to change the way URLs that Zend Framework is generating from this:
$routeString = '/section/:sectionName';
$route = new Zend_Controller_Router_Route(routeString, array( etc, etc... );
...to this...
$routeString = '/section_:sectionName';
$route = new Zend_Controller_Router_Route(routeString, array( etc, etc... );
Note that in the second option the middle slash in $routeString is replaced by an underscore.
When I make this change, the router stops recognizing the route and variables. I find it quite strange that the framework would impose such thing so I'm sure I'm missing something in the docs.
Cheers!
I think you could do it using Zend_Controller_Router_Route_Regex. As an example I'll provide setup for your route in the application.ini:
resources.router.routes.section.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.section.route = "section_(\d+)"
resources.router.routes.section.defaults.module = yourmodule
resources.router.routes.section.defaults.controller = yourcontroller
resources.router.routes.section.defaults.action = youraction
resources.router.routes.section.map.1 = "sectionName"
resources.router.routes.section.reverse = "section/%d"
Hope this will help you or at least point you in the right direction.

CodeIgniter Routing

I am developing an ecommerce website with CI that has product categories and products. I want to route the URL so that it will go to the products controller, then run the getCategoryByName function for the first segment, then run the getProductByName for the second segment. Here is what I have:
URL:
products/docupen/rc805
routes.php:
$route['products/([a-z]+)'] = "products/getCategoryByName/$1";
$route['products/([a-z]+)/([a-z0-9]+)'] = "products/$1/getProductByName/$2";
But its not working. "docupen" is the category, and "rc805" is the product.
Thanks in advance.
Thank you all for your help. This is what I ended up with for what I needed.
$route['products/:any/:num'] = "products/getProductByID";
$route['products/:any/:any'] = "products/getProductByName";
$route['products/:any'] = "products/getCategoryByName";
My answer builds a bit on Colin's answer.
When I played around with the routes in CodeIgniter I came to the conclusion that the order of the routes was important. When it finds the first valid route it won't do the other routes in the list. If it doesn't find any valid routes then it will handle the default route.
My routes that I played around with for my particular project worked as follows:
$route['default_controller'] = "main";
$route['main/:any'] = "main";
$route['events/:any'] = "main/events";
$route['search/:any'] = "main/search";
$route['events'] = "main/events";
$route['search'] = "main/search";
$route[':any'] = "main";
If I entered "http://localhost/index.php/search/1234/4321" It would be routed to main/search and I can then use $this->uri->segment(2); to retrieve the 1234.
In your scenario I would try (order is very important):
$route['products/:any/:any'] = "products/getProductByName";
$route['products/:any'] = "products/getCategoryByName";
I don't know enough to route the way you wanted (products/$1/getProductByName/$2), but I'm not sure how you would create a controller to handle this particular form of URI. Using the $this->uri->segment(n); statements as mentioned by Colin in your controller, you should be able to do what you want.
You should use the URI class to retrieve the "docupen" and "rc805" segments from your url. You can then use those values in whatever functions you need.
For example, if your url is www.yoursite.com/products/docupen/rc805, you would use the following in your products controller to retrieve the segments and assign them to variables:
$category = $this->uri->segment(2); //docupen
$product = $this->uri->segment(3); //rc805
Then you can use $category and $product however you need to.
CodeIgniter routes don't work well with regex. They are supported, not I can never get them to work. It would be much easier to catch them like this
$route['products/(:any)'] = "products/getCategoryByName/$1";
$route['products/(:any)/(:any)'] = "products/$1/getProductByName/$2";

URI re-routing in codeigniter

I'm using URI re-routing in CI to make better URLS. An example here would be:
$route['users/(:any)'] = "users/index/$1";
The aim here is to get rid of the index from URL. This works well. However it stops me from being able to access any functions in the users controller, for example
mywebsite.com/users/messages
Just redirects to the users/index. Is there a way around this?
Define the list of methods you wish to keep then let the rest wildcard match:
$route['users/(messages|login|something)'] = "users/$1";
$route['users/(:any)'] = "users/index/$1";
Hi I'm not familiar with CI but i have a similar routing system. The (:any) works as a sort of catch all. When my router checks the routing rules it stops checking if it has found an exact match. So then the answer would be to just add another functions route before the catch all. Like
$route['users'] = "users/index/";
$route['users/messages/(:any)'] = "users/checkmessages/$1";
$route['users/(:any)'] = "users/$1";
Not sure how CI handles this but i can think of something like the first URL part is the class and the second the function. The router or the controller module should have the intelligence to start calling the function even without the routing table.
The routing table should only be used in case of "other callable names" like i did above with the messages/checkmessages thingy.
hope that gets you going.

Categories