I have been trying to get pretty url with the router with Cake.
www.mysite.com/category/slug
www.mysite.com/slug
www.mysite.com/category/
I think there is no formula to get exactly what I want so I want explicitly match each url. I want my route table to look like this
id | url | controller | action | param
So when someone goes to
www.mysite.com/mysubcategory/my-title-of-page
I want it to cross reference "mysubcategory/my-title-of-page" with the url column and proceed. What is the best way to do this?
My guess would be to be to direct all traffic to a Route Controller
Router::connect('/*', array('controller' => 'Routes', 'action' => 'redirs'));
But when it redirects i want it to show the pretty url in the browser, i dont want it to show articles/view/12
thank you
You could either dynamically create your routes with the information retrieved from the database, or use a custom route class that looks up the table. If you only have a few routes, then you may want to use the former.
In your routes.php simply read your table and connect the routes, it should be as simple as that. Here's a very basic example:
use Cake\ORM\TableRegistry;
$Routes = TableRegistry::get('Routes');
$routes = $Routes->find();
foreach ($routes as $route) {
Router::connect(
$route->url,
[
'controller' => $route->controller,
'action' => $route->action
],
[
'pass' => [$route->param]
]
);
}
For something dynamic, check for example Mapping slugs from database in routing
Related
I am facing a problem with URLs having same structure but serving different resources.
Consider example Below:
GET /mumbai/mobiles
GET /travel/best-getaways-from-delhi
now in my routes.php I have Rule definition as below:
Route::get('/{city}/{category}', array(
'as' => 'citySearch',
'uses' => 'SearchController#doSearch'
));
Route::get('/{category}/{pageSlug}', array(
'as' => 'pageUrl',
'uses' => 'pageController#pageView'
));
Obviously, If I request /travel/best-getaways-from-delhi it'll match first rule and I won't be able to serve the content. My Logic here is either I can write a filter/or in controller a code which will lookup all cities and if there is no city ( i.e. travel is no city) it'll forward my requests to second rule (pageUrl).
How can I do that? or can anyone suggest me a better approach. Thanks
I would add a prefix to the URL to differentiate. For example have the links like /city/mumbai/mobiles and /page/travel/best-getaways-from-delhi
I'm seeing an issue with Laravel 4 when I have two routes pointing to the same action, one within a group and one just "loose" in the routes.php file.
<?php
// Routes.php
Route::group(array('domain' => '{subdomain}.domain.com'), function()
{
Route::get('profile/{id}/{name}', 'ProfileController#index');
});
Route::get('profile/{id}/{name}', 'ProfileController#index');
// Template.blade.php
Jim Smith
The template links to: currentsubdomain.domain.com/profile/%7Bid%7D/%7Bname%7D instead of the expected behaviour of swapping the ID and name for 123 and JimSmith respectively.
If I comment out, the first route (the one within the group), the code works as expected. Why does adding this additional route break the URL generation? Is there a way to work around this? Am I missing something obvious?
P.s. For those wondering why I need this route in two places it's so I can optionally generate the url with the subdomain using URL::action('ProfileController#index' array('subdomain' => 'james', 'id' => 123, 'name' => 'JimSmith');
The problem is that you don't have names/aliases for the routes so it's defaulting to the first one it comes across.
Consider this an alternate route structure:
Route::group(array('domain' => '{subdomain}.domain.com'), function() {
Route::get('profile/{id}/{name}', [
'as' => 'tenant.profile.index',
'uses' => 'ProfileController#index'
]);
});
Route::get('profile/{id}/{name}', [
'as' => 'profile.index',
'uses' => 'ProfileController#index'
]);
Now that you have these routes named, you can do:
{{ URL::route('profile.index', [123, 'jSmith']) }}
Or alternatively:
{{ URL::route('tenant.profile.index', ['subdomain', 123, 'jSmith']) }}
As just an added extra, you could only have this route defined once, then in all the controller methods you'd have something like:
public function index($subdomain = null, $id, $name) { }
Then you can just simply pass www through as the subdomain and have some code somewhere that discounts the www.domain.com domain from certain actions.
Multi-tenancy (if that is indeed what you're after) isn't easy and straight forward but there are some methods used to tackle certain parts. I'm actually planning on writing a tutorial regarding it, but for now I hope this helps somewhat.
Regarding the use of named routes, these 2 lines allow me to access the same page so which is correct?
// Named route
Route::get('test/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
// Much simpler
Route::get('apples', 'TestController#getApples');
Is there any reason I should be using named routes if the latter is shorter and less prone to errors?
Named routes are better, Why ?
It's always better to use a named route because insstsead of using the url you may use the name to refer the route, for example:
return Redirect::to('an/url');
Now above code will work but if you would use this:
return Redirect::route('routename');
Then it'll generate the url on the fly so, if you even change the url your code won't be broken. For example, check your route:
Route::get('apples', 'TestController#getApples');
Route::get('apples', array('as' => 'apples.show', 'uses' => 'TestController#getApples'));
Both routes are same but one without name so to use the route without name you have to depend on the url, for example:
return Redirect::to('apples');
But same thing you may do using the route name if your route contains a name, for example:
return Redirect::route('apples.show');
In this case, you may change the url from apples to somethingelse but still your Redirect will work without changing the code.
The only advantage is it is easier to link to, and you can change the URL without going through and changing all of its references. For example, with named routes you can do stuff like this:
URL::route('apples');
Redirect::route('apples');
Form::open(array('route' => 'apples'));
Then, if you update your route, all of your URLs will be updated:
// from
Route::get('test/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
// to
Route::get('new/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
Another benefit is logically creating a URL with a lot parameters. This allows you to be a lot more dynamic with your URL generation, so something like:
Route::get('search/{category}/{query}', array(
'as' => 'search',
'uses' => 'SearchController#find',
));
$parameters = array(
'category' => 'articles',
'query' => 'apples',
);
echo URL::route('search', $parameters);
// http://domain.com/search/articles/apples
The only reason to name the route is if you need to reference it later. IE: from your page in a view or something, check whether you are in that route.
I have a problem with the url rewriting.
The problem that I am facing is that currently our urls are like this:
http://www.xyz.com/sc_users/index
I dont want the controller name to be shown in that url.
Is there a way to achieve that??
First of all thank your guys..
Like I have 8 controllers I dont want the controller name to be shown in my url....this is what I want..
To be more precise no controller name in my url
You can define custom routes in app/config/routes.php. You'll find the all about routes in the CakePHP cookbook under Defining Routes. For example, a custom route can look like this:
Router::connect(
'/the_url_you_want_to_use/*', array('controller' => 'sc_users', 'action' => 'index')
);
You need to read up about CakePHP routing, look at the examples under 'defining routes'. Update your question with what you would actually like your URLs to look like and we will be able to help you more effectively.
That's simple :
there is a file called routes.php in /config directory :
You can do url rewriting stuff there like this :
Router::connect('/pages/*', array('controller' => 'cmsPage', 'action' => 'render'));
You can pass more complicated variables to your controller :
Router::connect('/:id-:lang-:profile-:firstName-:lastName-:profile.htm',
array('controller' => 'profiles','action' => 'view'),
array('id'=>'[0-9]*', 'lang'=>'fr','firstName'=>'[^-]*','lastNAme'=>'[^-]*','profile' => $util->keywords['profiles'][0]['fr'], 'pass' => array('id', 'lang'),'profile' => $util->keywords2['profiles'][0]['en'])
)
;
As you can see in the last example I have passed 2 parameters to the controller through 'pass' => array('id', 'lang')
I've got a question considering Zend_Controller_Router. I'm using a a modular-structure in my application. The application is built upon Zend-Framework. The normal Routes are like this:
/modulename/actionname/
Since I always use an IndexController within my modules, it's not necessary to provide it in the url. Now I am able to append params like this:
/modulename/actionname/paramkey/paramvalue/paramkey/paramvalue
So this is normal in ZF, I guess. But in some cases I don't want to provide a paramkey within the url. For example I want a blog-title to be shown within the url. Of course this is intended for SEO:
/blog/show/id/6/this-is-the-blog-title
In this case, blog is the module, show is the action. id is a paramkey and 6 is the id of the blogpost I want to show. this-is-the-blog-title is of course the headline of the blogpost with the id 6. The problem is, that if I do use the assemble()-method of the router like this:
assemble(array('module' =>'blog',
'action' => 'show',
'id' => $row['blog_id'],
$row['blog_headline_de'] . '.html'));
the url results in:
blog/show/id/6/0/this-is-the-blog-title.html
As you can see a 0 is inserted as a key. But I want this 0 to be omitted. I tried this by using the blogtitle as key, like this:
assemble(array('module' =>'blog',
'action' => 'show',
'id' => $row['blog_id'],
$row['blog_headline_de'] . '.html' => ''));
This results in:
blog/show/id/6/this-is-the-blog-title.html/
Now the 0 is omitted, but I've got the slash at the end.
Do you have any solution to get an url without 0 as key and without an ending slash?
Regards,
Alex
You might want to use a custom route for this:
$router->addRoute(
'blogentry',
new Zend_Controller_Router_Route('blog/show/:id/:title',
array('controller' => 'index', 'module' => 'blog'
'action' => 'info'))
);
And call your assemble with the route as second parameter. See the Zend_Controller_Router_Route section of the documentation for more details (they even provide examples with assemble).
Or in a more general way:
$router->addRoute(
'generalseo',
new Zend_Controller_Router_Route(':module/:action/:id/:title',
array('controller' => 'index'))
);